要約
最終的なソースコード全体は以下のリンクからご確認いただけます。
関連記事
Terraformの開発環境を整理したのを備忘録も兼ねて複数の記事にしています。この記事はそのうちの2本目として、「Terraformのtfstate
をS3で他者と共有して管理する」ことについてまとめます。
- Terraformで開発環境と本番環境を分けて管理する
-
Terraformの
tfstate
をS3で他者と共有して管理する(この記事)
背景
複数人のチームで開発をしていると、インフラの構成を管理する人が複数人いるということもあるかと思います。または、先代の担当者からインフラの管理を引き継ぐこともあるかもしれません。
「構成はTerraformで管理しているからGitのソースを見て」と渡されていざ見てみると、確かにTerraformの設定はされています。ただterraform plan
とかを実行すると全てのリソースが新規追加になってしまいました。
普段terraform plan
を実行すると、今のリソースと比べて変更される箇所、作り直される箇所、変わらない箇所などを教えてくれます。これは「今のリソース」の情報をTerraform側で記憶しているからできることです。これを管理しているのが terraform.tfstate
といった名前のファイルです。
ただこのterraform.tfstate
には実際のクラウド上のリソースの機微情報が紛れ込むことがあり、Git管理することは望ましくありません。したがって、Terraform.gitignore
にも*.tfstate
が含まれています。
なので上の状況を振り返ると、どのようなリソースかの設定はGit管理されていましたが、それに対して今がどういう状況かはGitでは管理されておらず、terraform plan
しても比較対象がないため全て新規追加という扱いになっていました。これではだいぶ不便です。なにもチーム開発だけの話ではなくて、個人開発の場合でも複数のPCを使っていれば、PCごとにどうtfstate
を共有するのかという問題になります。
そこでよく使われる方法は、この tfstate
をローカルで保持するのではなく、S3のようなリモートのオブジェクトストアで管理するという手段です。この記事では、AWS S3にtfstate
をアップロードするようにして、複数のPC間あるいはメンバー間からでも状態管理が行えるようにしたいと思います。
実装
tfstate
をリモートで管理するという設定は、terraformのbackend
の設定をすることで実現できます。公式のドキュメントにはS3を使用した例も説明されています。S3の例ではDynamoDBを使って変更をロックする実装も説明されていますが、内容が増えてしまうのでこの記事ではロックは設定しません。
ファイル構成は、前の記事の環境ごとに分けたものから引き続き、以下のようになっています。
.
├── .gitignore
├── environments
│ ├── dev
│ │ ├── .terraform.lock.hcl
│ │ └── main.tf
│ └── prod
│ ├── .terraform.lock.hcl
│ └── main.tf
└── modules
├── main.tf
├── variables.tf
└── vpc.tf
backendの設定
実装の方針としてS3のバケット名やstateのファイルパスは環境ごとに変わることを想定し、ハードコーディングではなく初期化時に渡すという方法を取ります。/environments
以下の各環境のmain.tf
を編集し以下の内容を追加しました。
後で指定が必要だよというのを分かりやすくするために、bucket
とkey
の項目もコメントアウトして残すようにしました。
どちらの環境も、設定している内容が全く一緒なので /modules
以下におけば良いじゃんと思い、最初はそうしていました。ただその場合だと terraform init
を実行した時にwarningが出てしまいました。曰く、これらの設定は子のモジュールが持つのではなく、ルートのモジュール(すなわち/environments/dev
直下のファイル)に記述することが望ましいようです。
terraform {
backend "s3" {
region = "ap-northeast-1"
encrypt = false
# bucket = "XXXXXXXXXXXXXXX"
# key = "XXXXXXXXXXXXXXX"
}
}
terraform {
backend "s3" {
region = "ap-northeast-1"
encrypt = false
# bucket = "XXXXXXXXXXXXXXX"
# key = "XXXXXXXXXXXXXXX"
}
}
初期化時にバケット名とキーを指定する
上記の設定ができたら、terraform init
を実行する時にbucket
とkey
の項目を指定する必要があります。指定方法は公式ドキュメントにも説明がありますが、「ファイルで渡す」「コマンドライン引数で渡す」「対話型CLIで渡す」といった選択肢があるようです。今回は「コマンドライン引数で渡す」方法で実施してみます。
/environments/prod
フォルダ、または/environments/dev
フォルダに移動して、以下のコマンドを実行します。バケット名は各自のものを設定してください。
terraform init -backend-config=bucket="hoge" -backend-config=key="test_vpc/dev.tfstate"
こうすることで、ローカルでterraform apply
と実行しても /environments/dev/
直下にterraform.tfstate
ファイルは作られず、リモートのS3上にdev.tfstate
のファイルが作成されていることを確認できるかと思います。
このリモートのstateファイルを、都度ローカルでの実行時に参照することで、別の端末でも、複数のユーザでも同じ挙動をすることができるようになりました。ですので、terraform apply
を実行するユーザには、このS3バケットを参照するIAMポリシーを設定する必要がありますので、あらかじめご確認ください。
参考