コンテンツにスキップ

Terraform実行環境の構築(詳細)

Eponaが提供するpatternモジュールを使用するには、Terraformを実行できる環境が必要です。
その環境構築は、Epona AWS Starter CLIを使用することで簡単に作成できます。

本ページでは、Epona AWS Starter CLIが内部で行っている、各リソースを作成する手順および詳細を説明します。

Eponaを使い始めるうえで、本ページを読むことが必須ではありません。
しかし、本ページの内容を理解しておくと、EponaにおけるState管理、AWSアカウントに対する理解がより進むでしょう。

State管理

AWS環境では、TerraformのState管理にAmazon S3をRemote Stateのバックエンドとして使用します。

バックエンドには、以下の3つのリソースを使用します。

  • Amazon S3
    • Stateの格納先として利用
  • Amazon DynamoDB
    • State更新の際のロックの仕組みとして利用

バックエンドを構成するこれらのリソースは、Delivery環境に作成します


ℹ️ State管理をDelivery環境で行うのはどうして?

Runtime環境は実際のサービスが稼働する環境であり、サービスの運用に直接関係のないリソースを配置するのは好ましくないと考えます。
Eponaにおいては、各Runtime環境から見て開発の基盤となるDelivery環境への配置が適切だと考え、バケットの配置先はDelivery環境に集約する方針としています。


State保存先となるS3バケット

Stateの管理先となるS3バケットは、利用するDelivery環境やRuntime環境といった、環境単位で作成します。

バケット名の命名規則は、[任意の名称]-環境名-terraform-tfstateとします。

以下、バケット名の例になります。

  • myservice-delivery-terraform-tfstate
  • myservice-staging-terraform-tfstate
  • myservice-production-terraform-tfstate

ℹ️ S3のバケット名は、パーティション内でユニークである必要があります。

バケットの制約と制限

[任意の名称]の部分には、サービス名等を利用するとよいでしょう。


リージョンについては、他のサービスと同等のものを指定してください。たとえば、ap-northeast-1などです。

ロック用のAmazon DynamoDB

StateをS3に保存することで、チーム内でのStateを共有できます。その一方で、複数人による変更が可能になるため、意図せず同時更新した場合にStateが不正な状態になってしまうことがあります。

このような事象を避けるため、TerraformではStateに対する排他制御(ロック)をサポートしており、AWSにおいてはその管理をAmazon DynamoDBで行うことができます。

ここでは、State更新時のロックを管理するための、Amazon DynamoDBのテーブルを作成します。

作成するテーブルの数は、Eponaで管理するDelivery環境およびRuntime環境の数に関わらず、ひとつで構いません。

作成するテーブルの名前は、[任意の名称]_terraform_tfstate_lockとします。


ℹ️ DynamoDBのテーブル名は、AWSアカウントおよびリージョン内で一意である必要があります。

DynamoDB テーブルの基本オペレーション

[任意の名称]の部分には、サービス名等を利用するとよいでしょう。


Terraformの実行ユーザー

Terraformの実行ユーザーについては、以下を方針とします。

  1. 各環境毎に個別のTerraform実行ユーザーを用意する
  2. Terraform実行ユーザーをDelivery環境上に集約する

1点目は、誤って意図しない環境を変更してしまう状況を避けることが目的です。環境毎にユーザーを使い分けることで、意図している環境しか変更を行えないようにし、誤った環境変更のリスクを下げます。 2点目については、Eponaのユーザー、グループ、ロールの設計方針に従うものです。こちらについては、ユーザー・グループ・ロールの設計方針を参照してください。

環境構築手順

ここでは、Delivery環境とRuntime環境を構築するための手順を説明します。

本手順を実行することにより、以下のようなTerraformのBackendが構成されます。

Backend

また、以下のようなTerraform実行用のユーザー・グループ・ロールも構成されます。

Terraform実行用ユーザ・グループ・ロール

⚠️
以降に記載されているTerraform実行用の環境を構築するためには、管理者権限を持ったAWSアカウントが必要です。
この手順を実行する時点で利用可能な、管理者権限を持ったユーザーで本ページの手順を実行してください。

Terraform実行環境を構築した後は、Terraformの実行には本ページの手順で作成したTerraform実行用ユーザーを使用します。
AWSマネジメントコンソールへのログイン等の操作については、users pattern等を適用して作成したIAMユーザーを利用してください。

事前作業

以下のように、各環境構築用のテンプレートをコピーしてください。

Terraformテンプレート コピー先 備考
Delivery環境構築用 setup_terraform_accounts/delivery FIXME部分を修正してください。コメントアウトされている部分は後段の手順でコメントインするため、当面はコメントアウトされたままにしてください
Runtime環境構築用 setup_terraform_accounts/runtimes/[環境名] 構築するRuntime環境の数だけコピーしてください

Delivery環境の構築

本手順では、Delivery環境上に、各環境用のバックエンドを整備します。以下の図の通り、Delivery環境上にState管理用のS3バケットと、ロック管理用のDynamoDBテーブルを作成します。

S3バケットには以下のような設定がなされます。

  • バージョニングを有効化し、何か問題があった時などに過去のバージョンのStateを確認できるようにします
  • 秘匿情報を漏洩させないように暗号化します
  • パブリックアクセスブロック設定により、S3バケットへのアクセスを制限します

バックエンド構成

さらに、同環境上に各環境用のTerraform実行ユーザーと所属グループ、そしてDelivery環境上におけるTerraformの実行時に使用するロールを準備します。以下のロールが構築されます。

  • それぞれの環境のバックエンドにアクセスするロール ([環境名]TerraformBackendAccessRole)
  • Delivery環境に対してTerraformを実行するためのロール (DeliveryTerraformBackendAccessRole)

Delivery環境のTerraform実行ユーザー

まず、AWSCLIに設定されているアクセスキーがDelivery環境のユーザーであることを確認してください。
環境構築手順の注記のとおり、事前に管理者権限のあるユーザーを準備していただき、そちらのユーザーが使われていることを確認してください。

$ aws sts get-caller-identity --query Arn --output text
arn:aws:iam::[Delivery環境のアカウントID]:user/[UserName]

また、環境変数AWS_DEFAULT_REGIONに、リージョンが設定されていることを確認してください。
設定されていない場合は、リージョンを設定してください。例えばLinuxの場合は、以下のように設定します。

# リージョンが設定されているか確認
$ echo $AWS_DEFAULT_REGION

# リージョンの設定(未設定の場合)
$ export AWS_DEFAULT_REGION=[リージョン]

Windowsの場合は以下のようになるでしょう。

# リージョンが設定されているか確認
$ echo %AWS_DEFAULT_REGION%

# リージョンの設定(未設定の場合)
$ set AWS_DEFAULT_REGION=[リージョン]

Delivery環境上でStateを格納するS3 Bucketを作成します。バックエンド用のバケットについては、[任意の名称]-環境名-backendとします。例えば、myservice-delivery-backendとなります。バケット名は以降の一連のコマンドで使用するため、環境変数に格納した方がよいでしょう。

Linuxの場合は以下のように環境変数を設定します。Windowsの場合はsetコマンドを利用してください。

$ export DELIVERY_BACKEND_BUCKET_NAME=[バックエンド用バケット名]

その上でバケットを作成してください。 なお、Windowsの場合は$DELIVERY_BACKEND_BUCKET_NAME%DELIVERY_BACKEND_BUCKET_NAME%に読み替えてください。


⚠️ この後は基本的にLinuxを前提に記載します。Windowsをご利用の場合は、適宜読み替えをお願いします。


$ aws s3api create-bucket --bucket $DELIVERY_BACKEND_BUCKET_NAME --create-bucket-configuration LocationConstraint=[リージョン]

その後に以下を実行することで、Delivery環境上に各環境用のバックエンド、およびTerraform実行用ユーザー・グループ・ロールが作成されます。

$ cd setup_terraform_accounts/delivery
$ terraform init -backend-config=./backend.config
$ terraform import -lock=false 'module.delivery.aws_s3_bucket.backend_itself' $DELIVERY_BACKEND_BUCKET_NAME
$ terraform apply -lock=false

最後のterraform applyでは、各環境毎のTerraform実行ユーザーのARNがterraformer_arnとして出力されます。 次の手順で必要になるので、メモを残しておいてください(terraform outputやAWSマネジメントコンソールでも確認可能です)。

terraformer_arn = {
  "Delivery" = {
    "arn" = "arn:aws:iam::[Delivery環境のアカウントID]:user/DeliveryTerraformer"
    "name" = "DeliveryTerraformer"
  }
  "Staging" = {
    "arn" = "arn:aws:iam::[Delivery環境のアカウントID]:user/StagingTerraformer"
    "name" = "StagingTerraformer"
  }
  (snip)
}

Runtime環境の構築

本手順では、Runtime環境上にTerraformを実行用のロールを作成し、Delivery環境上のTerraform実行ユーザーが当該ロールを使えるように信頼関係を設定します。

Runtime環境構築

ここではRuntime環境として、Staging環境を構築する場合の手順を説明します。構築するRuntime環境の数だけ、本手順を実行してください。

まず最初に、AWSCLIに設定されているアクセスキーがStaging環境のユーザーであることを確認してください。
環境構築手順の注記のとおり、事前に管理者権限のあるユーザーを準備していただき、そちらのユーザーが使われていることを確認してください。

$ aws sts get-caller-identity --query Arn --output text
arn:aws:iam::[Staging環境のアカウントID]:user/[UserName]

次に、予めコピーしておいたRuntime環境用テンプレートのmain.tfにおけるprincipalsに、Staging環境用のTerraform実行ユーザーのARNを記載してください。例えば、Staging環境を構築するのであれば、arn:aws:iam::[Delivery環境のアカウントID]:user/StagingTerraformerになります。

記述が必要な該当箇所は以下です。

module "terraformer_execution" {
  (snip)

  principals = ["Delivery環境上に定義された、本Runtime環境用Terraform実行ユーザーのARN"]
}

これらを記述した後に以下の手順を実行し、Staging環境上にTerraform実行ロールを構築します。

なお、バックエンド用のバケット名については、[任意の名称]-環境名-backendとします。例えばStaging環境の場合は、myservice-staging-backendとなります。バケット名は、以降の一連のコマンドで使用するため環境変数に格納した方がよいでしょう。

$ export STAGING_BACKEND_BUCKET_NAME=[バックエンド用バケット名]

その上でバケットを作成してください。

$ aws s3api create-bucket --bucket $STAGING_BACKEND_BUCKET_NAME --create-bucket-configuration LocationConstraint=[リージョン]
$ cd setup_terraform_accounts/runtimes/staging/
$ terraform init -backend-config=./backend.config -lock=false
$ terraform import -lock=false 'module.backend.aws_s3_bucket.tfstate' $STAGING_BACKEND_BUCKET_NAME
$ terraform apply -lock=false

最後のコマンドの実行により、以下のような出力が得られます。この値(arn:aws:...)が作成されたTerraform実行ロールのARNになります。

terraform_execution_role_arn = arn:aws:iam::[Runtime環境のアカウントID]:role/TerraformExecutionRole

Terraform実行ユーザーからTerraform実行ロールを利用可能にする

Runtime環境の構築で作成したTerraform実行ロールを、Delivery環境上のTerraform実行ユーザーから利用できるようにします。

  1. setup_terraform_accounts/delivery/main.tfexecution_role_mapの箇所をコメントインしてください
  2. 当該箇所のRuntime環境名とTerraform実行ロールのARNを追記してください
  execution_role_map = {
    "[Runtime環境1の名前]" = "[Runtime環境1で定義されたTerraform実行ロールのARN]"
  }

その上で以下のコマンドを実行することで、Terraform実行ユーザーがRuntime環境のTerraform実行ロールを利用できるようになります。

$ cd setup_terraform_accounts/delivery
$ terraform apply

Terraformの実行

Terraformを実行するためには、Terraform実行ユーザーのアクセスキーが必要です。 以下のコマンドでアクセスキーが発行されます。アクセスキーについては厳重に管理してください。

$ aws iam create-access-key --user-name [対象環境名]Terraformer

対象環境がDelivery環境の場合は以下のようになります。

$ aws iam create-access-key --user-name DeliveryTerraformer
{
    "AccessKey": {
        "UserName": "DeliveryTerraformer",
        "AccessKeyId": [アクセスキーID]
        "Status": "Active",
        "SecretAccessKey": [シークレットアクセスキー]
        "CreateDate": "2020-07-05T21:44:00+00:00"
    }
}

※ このドキュメントはクリエイティブコモンズ(Creative Commons) 4.0 の「表示—継承」に準拠しています。

※ このドキュメントに記載されている会社名、製品名は、各社の登録商標または商標です。

© 2021 TIS Inc.