メインコンテンツにスキップ
aws

Terraformでforce_destroy=trueでもS3バケットが削除できない問題の解決策

タグ: 🏷 aws ,terraform ,s3
目次

事象

TerraformでS3バケットを管理しており、force_destroy = true を設定しているにもかかわらず、terraform destroy を実行すると以下の BucketNotEmpty エラーで削除に失敗することがあります。

│ Error: deleting S3 Bucket (stag-app-logs): operation error S3: DeleteBucket, https response error StatusCode: 409, RequestID: AJ6PZ1BX9H7FCBSM, HostID: 9Fy0+4zSFv88BgVB947EEny/I1ouWo9OZpPWCzPdF5+9DkNAebcGHMAYf4/dYmDTZcuk48F+ftSD+GTEAusRspHERJtQSugRVMzW1Yqdjaw=, api error BucketNotEmpty: The bucket you tried to delete is not empty

対象のTerraformコードは以下の通りです。

resource "aws_s3_bucket" "this" {
  bucket        = "${var.name_prefix}-app-logs"

  force_destroy = true
  
  lifecycle {
    create_before_destroy = true
  }
  
  tags = {
    env = "{var.env}"
  }
}

原因

この問題の主な原因は、S3バケットでバージョニングが有効になっていることです。

force_destroy = true は、Terraformがバケットを削除する前にバケット内のオブジェクトをすべて削除するよう試みます。しかし、バージョニングが有効な場合、バケット内には過去のバージョンのオブジェクトや削除マーカーが多数存在する可能性があります。

Terraformがこれらのすべてのオブジェクトバージョンと削除マーカーを完全に削除する処理は複雑で、タイムアウトしたり失敗したりすることがあり、結果として BucketNotEmpty エラーが発生します。

解決策

最も確実な解決策は、terraform destroy を実行する前に、AWS CLIを使って手動でバケットを完全に空にすることです。

以下のAWS CLIコマンドを実行することで、バケット内のすべてのオブジェクトバージョンと削除マーカーを強制的に削除し、バケット自体も削除できます。

aws s3 rb s3://your-bucket-name --force

コマンドの解説:

  • aws s3 rb: S3バケットを削除 (remove bucket) するコマンドです。
  • s3://your-bucket-name: 対象のS3バケット名を指定します。your-bucket-name の部分を実際のバケット名に置き換えます。
  • --force: バケットが空でない場合でも、中のオブジェクトをすべて削除してからバケット自体を削除するオプションです。

このコマンドを実行した後、Terraformのstateファイルが古い状態を参照している可能性があるため、terraform apply または terraform destroy を再度実行して、stateを更新します。