はじめに
terraform.tfstate とは
Terraform で管理しているインフラの状態を管理しているファイルで中身は以下のような JSON ファイルとなっている。
{ "version": 1, "serial": 1, "modules": [ { "path": [ "root" ], "outputs": {}, "resources": { "aws_s3_bucket.b": { "type": "aws_s3_bucket", "primary": { "id": "foo-bucket", "attributes": { "acl": "private", "bucket": "foo-bucket", "force_destroy": "true", "hosted_zone_id": "xxxxxxxxxxxxxxxxxxxxxxx", "id": "foo-bucket", "policy": "", "region": "ap-northeast-1", "tags.#": "0", "website.#": "0", "website_endpoint": "" } } } } } ] }
上記は S3 Bucket を terraform apply
で作成した後の terraform.tfstate ファイル(以降 tfstate ファイル)。デフォルトでは tf ファイルと同じディレクトリに生成されるが terraform remote
コマンドを利用することで、Atlas や Consul 等に保存することが出来る。尚、terraform 0.5.0 からは Amazon S3 に保存することも出来るようになっているので、今回は Amazon S3 への保存を試してみたいと思う。
参考
tfstate ファイルの運用管理について参考にさせて頂いた。
tfstate ファイルの S3 への保存について参考にさせて頂いた。
terraform のバージョン
利用する terraform のバージョンは以下の通り。
% terraform -version
Terraform v0.6.1
試す
教材
tfstate ファイルを保存する S3 バケットを作成する tf ファイルを利用する。
やること
- tfstate ファイル保存先の S3 バケットを作成する
- tfstate ファイルの保存先を S3 に設定する
- tfstate ファイルを S3 バケットに保存して確認する
- tfstate ファイルの保存先を S3 からデフォルトに戻す
- tfstate ファイルを保存していた S3 バケットを削除する
tfstate ファイルを S3 で扱う IAM ユーザーの作成
tfstate ファイルを S3 で扱う為の IAM ユーザーを作成する(これも terraform でやって良かったな...と反省)。また、tfstate ファイルを保存する為のバケット名を指定して、以下のような inline policy を適用する。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "s3:*", "Resource": [ "arn:aws:s3:::${your_bucket_name}", "arn:aws:s3:::${your_bucket_name}/*" ] } ] }
作成したユーザーのアクセスキーとシークレットアクセスキーを取得しておく。
terraform plan
% terraform plan \ -var "access_key=AKzzzzzzzzzzzzzzzzzzz" \ -var "secret_key=zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" \ -var "s3_bucket_name=${your_key_name}"
以下のように出力される。
(略) + aws_s3_bucket.b acl: "" => "private" bucket: "" => "oreno-terraform-state-files" force_destroy: "" => "1" hosted_zone_id: "" => "<computed>" region: "" => "<computed>" website_endpoint: "" => "<computed>" Plan: 1 to add, 0 to change, 0 to destroy.
同じディレクトリに terraform.tfstate ファイルが作成されているので、念のため確認すると以下のような状態になっている。
{ "version": 1, "serial": 0, "modules": [ { "path": [ "root" ], "outputs": {}, "resources": {} } ] }
terraform apply で S3 バケットを作成
% terraform apply \ -var "access_key=AKzzzzzzzzzzzzzzzzzzz" \ -var "secret_key=zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" \ -var "s3_bucket_name=${your_key_name}"
以下のように出力される。
aws_s3_bucket.b: Creating... acl: "" => "private" bucket: "" => "oreno-terraform-state-files" force_destroy: "" => "1" hosted_zone_id: "" => "<computed>" region: "" => "<computed>" website_endpoint: "" => "<computed>" aws_s3_bucket.b: Creation complete Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
terraform.tfstate ファイルは以下のように更新されている。
{ "version": 1, "serial": 1, "modules": [ { "path": [ "root" ], "outputs": {}, "resources": { "aws_s3_bucket.b": { "type": "aws_s3_bucket", "primary": { "id": "${your_bucket_name}", "attributes": { "acl": "private", "bucket": "${your_bucket_name}", "force_destroy": "true", "hosted_zone_id": "XXXXXXXXXXXXXXXXX", "id": "${your_bucket_name}", "policy": "", "region": "ap-northeast-1", "tags.#": "0", "website.#": "0", "website_endpoint": "" } } } } } ] }
更に terraform.tfstate.backup ファイルが作成されているので確認してみる。
{ "version": 1, "serial": 0, "modules": [ { "path": [ "root" ], "outputs": {}, "resources": {} } ] }
先ほどの terraform plan
実行時に出力された結果が保存されている。
バケットが作成されているかを念のために確認。
% aws s3api list-buckets --output text | grep ${your_bucket_name} BUCKETS 2015-07-26T04:17:42.000Z ${your_bucket_name}
terraform remote config で tfstate ファイルの保存先を S3 バケットに設定する
作成した S3 バケットを tfstate ファイルの保存先として設定する為の設定を行う。
% terraform remote config \ -backend=S3 \ -backend-config="access_key=AKxxxxxxxxxxxxxxxxxxx" \ -backend-config="secret_key=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ -backend-config="region=ap-northeast-1" \ -backend-config="bucket=${your_bucket_name}" \ -backend-config="key=${your_key_name}"
bucket=
には S3 バケット名を指定、key=
にはオブジェクトのキーを指定する。
実行後に以下のように出力される。
Remote configuration updated Remote state configured and pulled.
terraform remote config
実行後に terraform.tfstate ファイルは .terraform 以下に移動されている。
% ls -l .terraform total 8 -rw-r--r-- 1 kappa staff 1348 Jul 26 13:34 terraform.tfstate
中身を確認する。
% cat .terraform/terraform.tfstate { "version": 1, "serial": 1, "remote": { "type": "s3", "config": { "access_key": "AKxxxxxxxxxxxxxxxxxxx", "bucket": "${your_bucket_name}", "key": "oreno_tf_s3", "region": "ap-northeast-1", "secret_key": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" } }, "modules": [ { "path": [ "root" ], "outputs": {}, "resources": { "aws_s3_bucket.b": { "type": "aws_s3_bucket", "primary": { "id": "${your_bucket_name}", "attributes": { "acl": "private", "bucket": "${your_bucket_name}", "force_destroy": "true", "hosted_zone_id": "XXXXXXXXXXXXXXXXX", "id": "${your_bucket_name}", "policy": "", "region": "ap-northeast-1", "tags.#": "0", "website.#": "0", "website_endpoint": "" } } } } } ] }
注意点として terraform remote config
を実行した際に利用したアクセスキーとシークレットアクセスキーが平文で JSON ファイルに保存されている点。
terraform remote push で S3 に保存
terraform remote push
を実行して terraform.tfstate を S3 バケットに保存する。
% terraform remote push
以下のように出力される。
State successfully pushed!
バケットに保存されているか確認する。
% aws s3 ls s3://${your_bucket_name}/ --recursive 2015-07-26 13:41:16 1348 oreno_tf_s3
tfstate ファイルの保存先をデフォルトに戻す
tfstate ファイルの保存先を S3 からデフォルト(tf ファイルと同じディレクトリ)に戻す場合には以下のように実行する。
% terraform remote config -disable
実行後は tfstate ファイルが tf ファイルと同じディレクトリに作成されているので中身を確認する。
{ "version": 1, "serial": 1, "modules": [ { "path": [ "root" ], "outputs": {}, "resources": { "aws_s3_bucket.b": { "type": "aws_s3_bucket", "primary": { "id": "${your_bucket_name}", "attributes": { "acl": "private", "bucket": "${your_bucket_name}", "force_destroy": "true", "hosted_zone_id": "Z2M4EHUR26P7ZW", "id": "${your_bucket_name}", "policy": "", "region": "ap-northeast-1", "tags.#": "0", "website.#": "0", "website_endpoint": "" } } } } } ] }
S3 を指定していた際には記載されていたアクセスキー等の情報が削除されている。
S3 バケットを削除する
terraform destroy \ -var "access_key=AKzzzzzzzzzzzzzzzzzzz" \ -var "secret_key=zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" \ -var "s3_bucket_name=${your_key_name}"
以下のように出力されるので yes
を入力してリソース(S3)を削除する。
Do you really want to destroy? Terraform will delete all your managed infrastructure. There is no undo. Only 'yes' will be accepted to confirm. Enter a value: yes aws_s3_bucket.b: Refreshing state... (ID: ${your_key_name}) aws_s3_bucket.b: Destroying... aws_s3_bucket.b: Destruction complete Apply complete! Resources: 0 added, 0 changed, 1 destroyed.
といふことで
メリデメ
tfstate ファイルを S3 に管理する方法を試してみた。参考にさせて頂いた Blog 記事等にも記載されているが、
- tfstate ファイル S3 に保存出来ることで CI ツールとの連携
- IAM を設定して公開範囲を限定出来る
等のメリットは大きいとと思うが、tfstate ファイルにアクセスキーやシークレットアクセスキーが平文で保存されている点については .gitignore
には .terraform
を含める等の注意が必要だと感じた。