AWS Provider v4以降、S3バケットの設定リソースが大きく再設計されました。v3以前は1つのリソースブロックに詰め込んでいたバージョニング・ライフサイクル・暗号化の設定が、それぞれ独立したリソースとして分割されています。この変更を知らずに書くと、現場での terraform apply でエラーが連発する原因になります。
この記事では、AWS Provider v4以降の分割設計に対応したS3バケット管理の実践的な書き方を解説します。バージョニングの有効化からライフサイクルルール・サーバーサイド暗号化まで、本番環境での設計判断とよくあるトラブルの切り分け方を整理します。
この記事のポイント
・AWS Provider v4以降ではaws_s3_bucket_*リソースで属性を分割して定義する
・バージョニング有効化後にライフサイクルルールを設定するにはdepends_onが必要
・SSE-S3はbucket_key_enabled = trueでKMS APIコール料金を削減できる
・force_destroyはオブジェクト全削除を伴うため本番バケットへの使用は要注意
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
なぜS3バケット設定をリソース分割で書くのか
AWS Provider v3以前では、次のようにaws_s3_bucketリソース1つにバージョニングやライフサイクルをまとめて書くことが一般的でした。# AWS Provider v3系の旧スタイル(v4以降は非推奨) resource "aws_s3_bucket" "example" { bucket = "my-terraform-bucket" versioning { enabled = true } lifecycle_rule { id = "delete-old-versions" enabled = true noncurrent_version_expiration { days = 30 } } server_side_encryption_configuration { rule { apply_server_side_encryption_by_default { sse_algorithm = "AES256" } } } }
# terraform plan 実行時の警告例 Warning: Argument is deprecated with aws_s3_bucket.example, on main.tf line 8, in resource "aws_s3_bucket" "example": 8: versioning { Use the aws_s3_bucket_versioning resource instead.
・個別設定の変更差分が見やすくなる(monolithicブロックだとdiffが巨大になる)
・各機能の依存関係をdepends_onで明示できる(特にバージョニングとライフサイクルの順序保証)
・リソース削除・再作成の影響範囲が限定できる
aws_s3_bucketと分割リソースの基本構成
1. メインバケットリソースの定義
バケット本体の定義はシンプルになっています。bucket名とtagsのみを定義し、個々の設定は後続の分割リソース側に書くのが現在の実務スタンダードです。resource "aws_s3_bucket" "example" { bucket = "my-terraform-bucket-prod" tags = { Environment = "production" ManagedBy = "terraform" } }
2. パブリックアクセスブロックの設定
本番環境のバケットは原則としてパブリックアクセスを全遮断します。aws_s3_bucket_public_access_block(パブリックアクセスブロック)は独立したリソースとして定義します。resource "aws_s3_bucket_public_access_block" "example" { bucket = aws_s3_bucket.example.id block_public_acls = true block_public_policy = true ignore_public_acls = true restrict_public_buckets = true }
3. バージョニングの有効化
バージョニングはaws_s3_bucket_versioningリソースで設定します。一度有効にしたバージョニングは「無効化」ではなく「停止(Suspended)」にしか戻せない点に注意してください。resource "aws_s3_bucket_versioning" "example" { bucket = aws_s3_bucket.example.id versioning_configuration { status = "Enabled" # status = "Suspended" # 停止(削除はできない) } }
ライフサイクルルールで旧バージョンを自動削除する
バージョニングを有効にするとオブジェクトの旧バージョンが蓄積し続け、ストレージコストが増大します。aws_s3_bucket_lifecycle_configuration(ライフサイクル設定)で旧バージョンの自動削除や低コストストレージクラスへの移行を定義することが、本番運用での鉄則です。Terraformを使ったS3設計パターンの全体像は、Terraform実践記事一覧でもまとめて解説しています。
1. 旧バージョンの自動削除ルール
【重要】ライフサイクルルールを定義する前に、バージョニングが有効になっている必要があります。depends_onでaws_s3_bucket_versioningへの依存を明示しないと、plan/applyの実行順序が保証されず、適用が不安定になります。resource "aws_s3_bucket_lifecycle_configuration" "example" { bucket = aws_s3_bucket.example.id # バージョニングが有効になった後に設定するためdepends_onが必須 depends_on = [aws_s3_bucket_versioning.example] rule { id = "delete-old-versions" status = "Enabled" # 最新版以外のバージョンを30日後に削除 noncurrent_version_expiration { noncurrent_days = 30 } # 不完全なマルチパートアップロードを7日後に削除 abort_incomplete_multipart_upload { days_after_initiation = 7 } } }
2. ストレージクラス移行(Standard-IA / Glacier)
アクセス頻度が低いオブジェクトをStandard-IA(低頻度アクセス)やGlacierに移行することで、保存コストを50~90%削減できます。rule { id = "transition-lifecycle" status = "Enabled" # 90日後にStandard-IAへ移行 transition { days = 90 storage_class = "STANDARD_IA" } # 365日後にGlacier Flexible Retrievalへ移行 transition { days = 365 storage_class = "GLACIER" } # 旧バージョンも同様に移行 noncurrent_version_transition { noncurrent_days = 30 storage_class = "STANDARD_IA" } }
サーバーサイド暗号化(SSE)の設定パターン
1. SSE-S3(AES-256)で全オブジェクトを暗号化する
aws_s3_bucket_server_side_encryption_configuration(サーバーサイド暗号化設定)でSSE-S3を有効にします。SSE-S3はS3が管理するキーを使うため、KMSと比べてコストがかかりません。resource "aws_s3_bucket_server_side_encryption_configuration" "example" { bucket = aws_s3_bucket.example.id rule { apply_server_side_encryption_by_default { sse_algorithm = "AES256" } # S3バケットキーを有効化するとKMS APIコールを削減できる bucket_key_enabled = true } }
2. SSE-KMS(KMSカスタムキー)で証跡管理を強化する
コンプライアンス要件でKMSキーへのアクセス履歴(CloudTrail)が求められる場合は、aws:kmsアルゴリズムを使います。resource "aws_kms_key" "s3" { description = "KMS key for S3 server-side encryption" deletion_window_in_days = 10 enable_key_rotation = true } resource "aws_kms_alias" "s3" { name = "alias/my-s3-key" target_key_id = aws_kms_key.s3.key_id } resource "aws_s3_bucket_server_side_encryption_configuration" "kms" { bucket = aws_s3_bucket.example.id rule { apply_server_side_encryption_by_default { sse_algorithm = "aws:kms" kms_master_key_id = aws_kms_key.s3.arn } bucket_key_enabled = true } }
トラブルシュートとよくある設計ミス
1. 「BucketNotEmpty」エラーでterraform destroyが止まる
オブジェクトが入っているバケットをそのままdestroyしようとすると、次のようなエラーで止まります。# terraform destroy 実行時のエラー例 Error: deleting Amazon S3 Bucket (my-terraform-bucket-prod): BucketNotEmpty: The bucket you tried to delete is not empty. You must delete all versions in the bucket. status code: 409, request id: XXXX, host id: YYYY
要注意なのは、本番データを保管しているバケットに安易に設定してはいけない点です。force_destroy = trueは開発・テスト環境専用の設定と位置づけ、本番バケットでは手動で削除操作を行う運用を推奨します。
resource "aws_s3_bucket" "dev" { bucket = "my-dev-bucket" # 開発環境専用。本番バケットには設定しないこと force_destroy = true }
2. ライフサイクルルールがなぜか適用されない
ライフサイクルルールを書いても旧バージョンが削除されない場合、最初に確認すべきは「バージョニングが有効になっているか」です。depends_onを付けずにterraform applyすると、バージョニングとライフサイクル設定が並行して適用されることがあります。また、ライフサイクルルールはAWS側で反映されるまで最大24時間程度かかる場合があります。apply直後に削除されないことだけで「適用されていない」と判断するのは早計です。AWS CLIでルールの登録状態を確認してから判断してください。
# ライフサイクルルールの登録状態を確認 # aws s3api get-bucket-lifecycle-configuration # --bucket my-terraform-bucket-prod { "Rules": [ { "ID": "delete-old-versions", "Status": "Enabled", "NoncurrentVersionExpiration": { "NoncurrentDays": 30 } } ] }
本記事のまとめ
TerraformでS3バケットを管理する際のポイントをまとめます。| 設定項目 | 使用リソース | 主な注意点 |
|---|---|---|
| バケット本体 | aws_s3_bucket |
v4以降はbucket名・tagsのみ記述する |
| パブリックアクセス遮断 | aws_s3_bucket_public_access_block |
4つのフラグをすべてtrueにする |
| バージョニング | aws_s3_bucket_versioning |
有効化後は削除できない(Suspendedのみ) |
| ライフサイクル | aws_s3_bucket_lifecycle_configuration |
depends_on = [versioning] が必須 |
| 暗号化(SSE-S3) | aws_s3_bucket_server_side_encryption_configuration |
bucket_key_enabled = trueでKMS料金を削減 |
| バケット強制削除 | force_destroy = true(aws_s3_bucket内) | 開発環境専用。本番バケットへの使用は禁止 |
3,100名以上が実践した「型」を無料で公開中
プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら
- 前のページへ:tfstateファイルから読み解くTerraformリソース依存順序|計画どおり壊せる削除設計
- この記事の属するカテゴリ:Terraformへ戻る

無料メルマガで学習を続ける
Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。
登録無料・いつでも解除できます