概要
terraform apply
を実行した際に作成されるステートファイルをクラウド上で管理する方法を記載します。
AWS上のリソースをterraform
で管理しているケースを想定しています。
管理方法
apply
を実行した際の現在の結果を記録しているファイルがtfstate
ファイルとなります。(このファイルを見て差分を割り出してくれていますね)
デフォルトではローカルに生成されますが、チーム開発を行っていくにあたって特定の人物のローカルにしかないと困ってしまいますね。
そこで通常tfstate
ファイルは、以下のように管理します。
- Cloud上にステートファイル管理用のバケット(
ECS
やGCS
)を作成 - Terraform Cloudを利用
AWS S3 Bucketの利用
管理対象となるAWS上で手軽に管理します。
なお、ステートファイルを保管するバケット自体はterraform
での管理するインフラストラクチャ外にあることが理想です。(公式ドキュメントより)
このバケットを管理するためのアカウントを別に発行することが望ましいようですが、ややこしくなるので、ここではaws-cli
を用いてバケットを作成し、terraform
の管理外とすることを実現します。
1. ステート管理バケットの作成
単純に作成するだけでも構いませんが、以下の設定を入れておくと安心でしょう。
- バージョニング :不用意な削除等が行われた場合でも復元することができる
- 暗号化 :バケット自体の暗号化を行う
- ブロックパブリックアクセス:バケットを公開しないよう設定
# バケット作成
aws s3api create-bucket --bucket ${bucket_name} --create-bucket-configuration LocationConstraint=${region}
# バージョニングの有効化
aws s3api put-bucket-versioning --bucket ${bucket_name} --versioning-configuration Status=Enabled
# バケットの暗号化
aws s3api put-bucket-encryption --bucket ${bucket_name} \
--server-side-encryption-configuration '{"Rules": [{"ApplyServerSideEncryptionByDefault": {"SSEAlgorithm": "AES256"}}]}'
# ブロックパブリックアクセス
aws s3api put-public-access-block --bucket ${bucket_name} \
--public-access-block-configuration '{
"BlockPublicAcls" : true,
"IgnorePublicAcls" : true,
"BlockPublicPolicy" : true,
"RestrictPublicBuckets": true
}'
# タグ付け
aws s3api put-bucket-tagging --bucket ${bucket_name} \
--tagging 'TagSet=[{Key=description,Value=manage mintak-terraformer tfstate}]'
2. DynamoDBテーブル作成
DynamoDBを組み合わせることによって、ステートロックを実現可能とします。
※真偽は明らかではないですが、パーティションキー名称はLockID
でないとうまく動作しませんでした。
aws dynamodb create-table \
--table-name ${state_lock_table_name} \
--attribute-definitions '[{"AttributeName":"LockID","AttributeType": "S"}]' \ # S=stringの意味
--key-schema '[{"AttributeName":"LockID","KeyType": "HASH"}]' \ # HASH=パーティションキーの意味
--provisioned-throughput '{"ReadCapacityUnits": 1, "WriteCapacityUnits": 1}' # 念のため最低値を設定しておく
3. backend設定
ステートファイルを上記で作成したバケットに保管するように設定するための実装を行います。
tfファイルがある階層にbackend.tf
を新たに作成します。
terraform {
backend s3 {
bucket = "1で作成したバケット名"
key = "terraform.tfstate"
dynamodb_table = "2で作成したテーブル名"
region = "ap-northeast-1"
encrypt = true
}
}
この状態でapplyやdestroyを行ってみると、ローカルにステートファイルが作成されることがなくなり、
S3バケット上に作成されるようになります。
Terraform Cloudの利用
GithubやGitLabと連携してplan
やapply
を行う機能もあるようですが、
今回はあくまでステートファイルの共有管理の目的に閉じて利用する前提での例となります。
変更内容(履歴)がUI上で確認できる点が優れていると感じました。
1. サインアップ
Terraform Cloudの「Sign up for Cloud」ボタンをクリックしてアカウントを作成します。必要なものはメールアドレスのみです。
作成が必要なものは、アカウント・組織・ワークスペースの3つとなります。
2. ワークスペース設定
あくまでステートファイルの共有管理のみに閉じるため、次の設定を行います。
- 実行モードをLocalに
ワークスペース->Settings->generalの画面Execution Mode
をLocal
に設定します。
- VCS provider off
ワークスペース設定時にVCS providerを設定している場合は今回の用途では不要なためオフにします。
ワークスペース->Settings->Version Controlよりdeleteを行います。
3. CLIログイン
コンソールからログインを行います。このタイミングでAPI Keyを発行します。(key情報は~/.terraform.d/credentials.tfrc.json
に保管されます。1)
Do you want to proceed? (y/n)
は「y」を入力してください。
$ terraform login
Do you want to proceed? (y/n) y
# ここでTerraform CloudのUIでAPI Keyを発行する画面へ遷移する。そのまま発行を行いコピーして、コンソールにペーストする
Terraform must now open a web browser to the tokens page for app.terraform.io.
If a browser does not open this automatically, open the following URL to proceed:
https://app.terraform.io/app/settings/tokens?source=terraform-login
---------------------------------------------------------------------------------
Generate a token using your browser, and copy-paste it into this prompt.
Terraform will store the token in plain text in the following file
for use by subsequent commands:
/Users/mintak/.terraform.d/credentials.tfrc.json
Token for app.terraform.io:
Retrieved token for user mintak21
---------------------------------------------------------------------------------
Success! Terraform has obtained and saved an API token.
4. backend設定
ステートファイルをTerraform Cloud
に保管するように設定するための実装を行います。
tfファイルがある階層にbackend.tf
を新たに作成します。
terraform {
backend remote {
hostname = "app.terraform.io"
organization = "組織名"
workspaces {
name = "ワークスペース名"
}
}
}
この状態でapply
やdestroy
を行ってみると、ローカルにステートファイルが作成されることがなくなり、
Terraform Cloud
上に作成されるようになります。
現在の状態と前回からの差分をUI上で確認することが可能です。