実はここまで、Terraform がどのように AWS リソースの状態を管理しているのかを説明していませんでした。Terraform を使った AWS リソースのデプロイを体験することが、何よりも重要だと考えていたためです。
Chapter.9 では、Terraform がリソースの状態を管理するステートファイル (terraform.tfstate
) の基礎を紹介します。
アーキテクチャ図
デプロイするのは、以下のアーキテクチャ図のような構成です。Amazon S3 バケットと Amazon CloudWatch Logs ロググループをデプロイします。
Terraform でデプロイする
今までと同じ手順でデプロイしてみましょう。
$ cd ${CODESPACE_VSCODE_FOLDER}/chapter09
$ tflocal init
$ tflocal plan
$ tflocal apply
(中略)
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
aws_cloudwatch_log_group.chapter09: Creating...
aws_s3_bucket.chapter09: Creating...
aws_cloudwatch_log_group.chapter09: Creation complete after 0s [id=chapter09-logs]
aws_s3_bucket.chapter09: Creation complete after 0s [id=chapter09-bucket]
Apply complete! Resources: 2 added, 0 changed, 0 destroyed.
Apply complete! Resources: 2 added, 0 changed, 0 destroyed.
と表示されていれば成功です!
ステートファイル
すると、chapter09
ディレクトリに terraform.tfstate
というファイルが作られているはずです。実は Chapter.2 から Chapter.8 でも、同じ名前のファイルが作られていました。
では、terraform.tfstate
ファイルを開いてみましょう。JSON 形式の複雑なファイルなので、すべてを理解する必要はありません。ザッと眺めてみましょう。特に resources
の中を見ていくと、デプロイした aws_cloudwatch_log_group
の chapter09
と、aws_s3_bucket
の chapter09
が見つかるはずです!
重要なのは、Terraform はこのステートファイルを使って「デプロイしたリソースの状態」を管理しているということです。
terraform state
コマンド
Terraform CLI(terraform
コマンド)には、ステートファイルを管理するコマンドもあります。terraform state list
コマンドでリソースの一覧を取得してみましょう。すると、期待通りに2つのリソースを確認できます。
$ terraform state list
aws_cloudwatch_log_group.chapter09
aws_s3_bucket.chapter09
コマンドの詳細はドキュメントに載っています。
また、terraform state show
コマンドで、指定したリソースの詳細を確認できます。
$ terraform state show aws_cloudwatch_log_group.chapter09
# aws_cloudwatch_log_group.chapter09:
resource "aws_cloudwatch_log_group" "chapter09" {
arn = "arn:aws:logs:ap-northeast-1:000000000000:log-group:chapter09-logs"
id = "chapter09-logs"
kms_key_id = null
log_group_class = null
name = "chapter09-logs"
name_prefix = null
retention_in_days = 7
skip_destroy = false
tags_all = {}
}
コマンドの詳細はドキュメントに載っています。
ステートファイルの管理
先ほど、Terraform はステートファイルを使って「デプロイしたリソースの状態」を管理していると説明しました。言い換えると、ステートファイルがないと「どのリソースをデプロイしたのか」という情報がなくなるため、Terraform は新しくリソースを作ろうとしてしまいます。よって、ステートファイルを適切に管理することが重要です。
選択肢は多くありますが、たとえば Amazon S3 バケットでステートファイルを管理する仕組みがあります。
他の案として、HCP Terraform (旧 Terraform Cloud) を使うと、Terraform の実行からステートファイルの管理まで、すべてを HCP Terraform 上で行えます。
Terraform S3 Backend
Chapter.9 では、Amazon S3 バケットでステートファイルを管理する Terraform S3 Backend を試してみましょう。
backend.tf
chapter09/backend.tf
という新規ファイルを作り、Terraform S3 Backend の設定をします。今回は Amazon S3 バケット aws-terraform-workshop-using-localstack-tfstates
に terraform.tfstate
というファイル名のステートファイルを管理するという設定です。
terraform {
backend "s3" {
region = "ap-northeast-1"
bucket = "aws-terraform-workshop-using-localstack-tfstates"
key = "terraform.tfstate"
}
}
なお、この Zenn Book でずっと使っていた LocalStack Terraform CLI(tflocal
コマンド)は、この Terraform S3 Backend を LocalStack 上で動かすこともサポートしていて、自動的に Amazon S3 バケットを LocalStack 上にデプロイする仕組みになっています。よって、ここで terraform init
コマンド(tflocal init
コマンド)を実行すると、LocalStack 上の Amazon S3 バケット aws-terraform-workshop-using-localstack-tfstates
にステートファイルがアップロードされます。
$ tflocal init
Initializing the backend...
Acquiring state lock. This may take a few moments...
Do you want to copy existing state to the new backend?
Pre-existing state was found while migrating the previous "local" backend to the
newly configured "s3" backend. No existing state was found in the newly
configured "s3" backend. Do you want to copy this state to the new "s3"
backend? Enter "yes" to copy and "no" to start with an empty state.
Enter a value: yes
Successfully configured the backend "s3"! Terraform will automatically
use this backend unless the backend configuration changes.
リソース確認
LocalStack Resource Browser を開き、S3 画面に遷移し、aws-terraform-workshop-using-localstack-tfstates バケットを確認してみましょう!terraform.tfstate
ファイルが自動的にアップロードされているはずです。
Chapter.9 はここまでです✋
コード解説
簡単にコードのポイントを解説します。読み飛ばしても大丈夫です👌
provider.tf
Chapter.2 と同じです。
main.tf
Chapter.2 や Chapter.7 と同じで、もう追加の解説は不要ですね!
resource "aws_s3_bucket" "chapter09" {
bucket = "chapter09-bucket"
}
resource "aws_cloudwatch_log_group" "chapter09" {
name = "chapter09-logs"
retention_in_days = 7
}
コード解説はここまでです✋