はじめに
個人開発で AWS アカウントを Terraform で管理する際、tfstate を安全に管理することが重要です。本記事では、S3 をバックエンドとして使用し、DynamoDB をロック機構として組み合わせる最小構成のセットアップについて解説します。特に、bootstrap 用の Terraform コードを分離する理由、S3 バケットのバージョニングについて実体験をもとに説明します。
- Terraform での S3 バックエンドの設定ができる
- DynamoDB を使用したロック機構の設定ができる
- tfstate 管理のベストプラクティスを理解できる
環境
- OS: Ubuntu 20.04
- Terraform バージョン: 1.3.0
- AWS CLI バージョン: 2.5.0
必要な前提:
- AWS アカウントが存在し、AWS CLI によりアクセス可能であること。
- IAM ユーザーが S3 と DynamoDB に対する必要な権限を持っていること。
S3 バックエンドの設定
まずは、Terraform の状態を保存するための S3 バケットを作成します。バージョニングを有効にすることで、過去の状態を追跡できます。
# main.tf
resource "aws_s3_bucket" "tfstate" {
bucket = "<YOUR_BUCKET_NAME>"
lifecycle {
prevent_destroy = true
}
}
resource "aws_s3_bucket_versioning" "tfstate_versioning" {
bucket = aws_s3_bucket.tfstate.id
versioning_configuration {
status = "Enabled"
}
}
resource "aws_s3_bucket_server_side_encryption_configuration" "tfstate_encryption" {
bucket = aws_s3_bucket.tfstate.id
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "AES256"
}
}
}
resource "aws_s3_bucket_public_access_block" "tfstate_public_access" {
bucket = aws_s3_bucket.tfstate.id
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
この設定により、S3 バケットに保存されたすべてのオブジェクトは暗号化され、バージョニングが有効になります。また、パブリックアクセスがブロックされます。
DynamoDB ロック機構の設定
DynamoDB を使用してロック機構を設定することで、同時に複数の Terraform プロセスが状態ファイルを操作することを防ぎます。
# main.tf
resource "aws_dynamodb_table" "terraform_locks" {
name = "terraform-locks"
billing_mode = "PAY_PER_REQUEST"
hash_key = "LockID"
attribute {
name = "LockID"
type = "S"
}
}
この設定では、LockID を partition key として使用し、テーブルのスループットを PAY_PER_REQUEST に設定することで、使用頻度に応じた課金が行われます。
terraform.tf ファイルの設定
次に、terraform {} ブロックを使用してバックエンド設定を記述します。
# terraform.tf
terraform {
backend "s3" {
bucket = "<YOUR_BUCKET_NAME>"
key = "terraform/state"
region = "<YOUR_REGION>"
dynamodb_table = "terraform-locks"
}
}
この設定により、Terraform は指定された S3 バケットに状態を保存し、DynamoDB テーブルをロックに使用します。
ハマったポイント / トラブルシュート
bootstrap 用 Terraform を別ディレクトリに切る理由
bootstrap 用 Terraform は別ディレクトリ (bootstrap/) に分けるべきです。backend を本体と同じにすると、tfstate 管理の鶏卵問題が発生するためです。
terraform init 時のエラー
Failed to get existing workspaces エラーが発生した場合は、IAM 権限不足が原因です。必要な権限を確認してください。
tfstate バケット名のユニーク性
tfstate バケット名はグローバルにユニークである必要があります。推測されにくい suffix(例えば、組織のスラッグなど)を入れると良いでしょう。
terraform init の出力例
$ terraform init
Initializing the backend...
Successfully configured the backend "s3"!
...
まとめ
Terraform での S3 バックエンドと DynamoDB ロック機構の設定を通じて、安全で信頼性のある状態管理が可能となります。次に試すと良いこととしては、複数環境(開発、ステージング、本番)でのバックエンド設定の分離や、IAM ポリシーの最適化です。