【AWS】TerraformでS3バケット作成時にハマった点を深堀りしてみる
はじめに
先日、業務の一環で、Terraformで定義されたAWS環境のテストを実施していました。
そのテストでは、「リージョンを指定している変数の値を変更して、別リージョンでApplyを流しても正しく環境が構築されるか」という項目があったため、TerraformでS3バケットを作成・削除後、別リージョンで同名のS3バケットを再作成する、というオペレーションを行いました。
その時、Applyが終わらず再作成が完了しない、という現象が発生し、原因特定に苦難したので、備忘と共有の目的で、当時調査した内容をまとめます。
まずは結論
AWSのre:Postに、以下のような記述があります。
Amazon S3 は大規模な分散システムであるため、バケットの削除などの変更は、すべての AWS リージョンで結果整合性が取れるまでに時間がかかります。
多くの場合、バケットを作成できるのは、前のバケットを削除してから数時間以内です。ただし、変更の整合性が取れるまでには 48~72 時間かかる場合があります。S3 バケットを再作成するには、少なくとも 48 時間待つことをお勧めします。
(中略)
バケットが Amazon S3 によって完全に削除されるまで、同じバケット名を使用することはできません。
結果整合性とは
結果整合性とは、分散コンピューティングにおいて高可用性を実現するために用いられる整合性モデルです。S3ではこの結果整合性を採用しています。
この仕組みにより、データの更新が全てのノード(今回の場合はすべてのAWSリージョン)に伝播するまでに時間がかかるものの、最終的には全てのノードが同じデータを保持することを保証します。
S3バケットの再作成に失敗した理由
re:Postでの公式アナウンスの通り、S3バケットに対する変更処理が全リージョン内で整合性が取れる状態になるまでに、48~72時間かかる可能性があります。その間は同じバケット名でのS3バケットの作成ができません。
今回は、この結果整合性の仕組みにより、S3バケットの再作成に失敗したと考えられます。
また、毎回発生するわけではありませんが、情報の整合性がとれるまで、削除したはずのS3バケットがAWSマネジメントコンソールのS3管理画面上で以下のように「AWS Region: Not found」と表示されることもあります。
このような表示になった際も、しばらく時間を置くとS3管理画面から表示が消えるので、結果整合性によるものと推測できます。
(参考)https://repost.aws/questions/QU0AtycsypSzCJzTON9mX1PA/s3-bucket-shows-aws-region-not-found-while-trying-to-deleteあ
結論にたどり着いた過程と今回の検証内容
実は今回、原因調査をする過程ですんなりこのre:Postの記事にたどり着けたわけではありません。
一通りの検証を行い、自分なりの答えが出た後、たまたま記事を発見し、答え合わせのような感覚で確認をしました。
結論は既に出ていますが、せっかく検証した経緯と結果があるので、以降紹介していきます。
※上記re:Postの「MAX72時間程度はリージョン間の整合性確保のためS3が正常に作成されないケースがある」という内容が公式からの正式なアナウンスであり、正となります。本検証結果はあくまで参考としてください。
【検証環境】
- Terraform実行環境:AWS Cloud9
- Region:
ap-northeast-1
- Instance type:
t2.micro
- Platform:
Amazon Linux 2023
- Region:
Apply失敗の現象を再現してみる
まず、現象を再現するために、発生当時と同様に以下の流れで作業を進めました。
【現象再現の流れ】
- Terraformソースコードの準備
- Terraformで定義したS3バケットをApply
- 2でApplyしたS3バケットをDestroy
- providerのリージョン設定のみを変更してS3バケットを再Apply
1. Terraformソースコードの準備
今回はTerraformでS3を作成するため、以下のようなソースコード(main.tf)を用意し、Cloud9に保存しました。
providerのリージョンはap-northeast-1
に設定しています。
terraform {
required_version = ">=1.6.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 5.22.0"
}
}
}
provider "aws" {
profile = ""
region = "ap-northeast-1"
}
// S3のbucketを作成する
resource "aws_s3_bucket" "this" {
bucket = "terraform-s3-test-20250108-12345"
}
resource "aws_s3_bucket_public_access_block" "this" {
bucket = aws_s3_bucket.this.bucket
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
2. Terraformで定義したS3バケットをApply
早速、main.tf
をApplyしてS3バケットを作成します。
terraform apply
Applyは数秒で完了し、問題なくS3バケットが作成されることを確認しました。
3. 2でApplyしたS3バケットをDestroy
後続の検証のために、2. Terraformで定義したS3のApplyで作成したS3バケットは、一旦このタイミングでDestroyします。
terraform destroy
DestroyもApply同様に数秒で完了し、S3バケットが削除されることを確認しました。
4. providerのリージョン設定のみを変更してS3バケットを再Apply
次に、main.tf
を編集し、providerのリージョンをus-east-1
に変更します。
provider "aws" {
profile = ""
region = "us-east-1"
}
その後、main.tf
を再Applyしますが、50分経ってもApplyが完了しません。当時の現象を再現することが出来ました。
現象の再現ができたため、一度[Ctrl]+[C]でApplyを中止します。
Apply失敗の原因調査
次に原因調査を行います。
調査1. S3バケット名を変更して再Applyしてみる
S3バケット名は、グローバルで固有である必要があります。S3バケットを作成する際、このバケット名の制約が原因でエラーが発生することも多いです。
この制約が影響を及ぼしているか確認するため、S3バケット名を一部変更(末尾に6を追加)し、リージョンはus-east-1
で再Applyしてみました。
provider "aws" {
profile = ""
region = "us-east-1"
}
resource "aws_s3_bucket" "this" {
bucket = "terraform-s3-test-20250108-123456"
}
すると、今度は問題なくApplyが完了しました。S3バケット名が異なる場合は、Applyが完了しない現象は起こらないようです。
調査2. 同じ名前のS3バケットを同一リージョンで再Applyしてみる
完全にS3バケット名だけの問題であれば、同じ名前のS3バケットを同一リージョンで再ApplyしてもApplyが完了しない現象が起こるはずなので、実際に試してみます。
調査1. S3バケット名を変更して再Applyしてみるで作成したS3バケットを1度Destroyし、providerのリージョンはus-east-1
のまま変更せずに再Applyします。
すると、このパターンではApplyが正常に完了し、S3バケットが作成されることが確認できました。
調査1、調査2の結果から、Applyが完了しない現象の発生条件としては以下の2点ということが分かりました。
- 1回目のApplyとは異なるリージョンにS3バケットを再Applyする
- 1回目のApplyと同じ名前のS3バケットを再Applyする
調査3. 直前のApply・Destroyから、時間をあけて異なるリージョンに同じ名前のS3バケットを再Applyしてみる
これまでの検証では、直前のDestroyが完了した後、1分以内に再Applyを実行していました。
上記の発生条件とApplyの実行間隔から、本事象の発生原因として、「AWS内部で、リージョン間のS3の情報同期にタイムラグがあり、同名のS3バケットを短期間で削除・作成するとS3バケット名の重複が発生して正常にApplyが完了しない」、という仮説を立て、調査を進めます。
上記の仮説を検証するために、今度は直前のApply、及びDestroyから、時間をあけて異なるリージョンに同じ名前のS3バケットを再Applyしてみました。
結果は以下の通りです。
1回目Destroyと2回目Applyの間隔 | Apply結果 |
---|---|
10分 | 失敗 |
30分 | 失敗 |
60分 | 成功 |
リージョン間の情報の同期のタイミングにも左右されるかと思いますが、私が検証した時は、1回目のApply・Destroyの後に大体60分程度時間を置くと、異なるリージョンに同じ名前のS3バケットを再Applyすることができました。
時間を置くことで正常にApplyできることが確認できたため、「AWS内部で、リージョン間のS3の情報同期にタイムラグがあり、同名のS3バケットを短期間で削除・作成するとS3バケット名の重複が発生して正常にApplyが完了しない」という仮説を立証する要素になるかと思います。
調査4. AWSマネジメントコンソールのS3管理画面での挙動を確認してみる
これまで、Terraformで現象の再現と原因調査を行ってきましたが、AWSマネジメントコンソール S3管理画面から同じ作業を行うとどうなるのか、念のため確認しました。
AWSマネジメントコンソール S3管理画面でS3バケットを一度作成・削除し、異なるリージョンで同じ名前のS3バケットを再度作成しようとすると、やはり下図の通りエラーが発生してS3バケットが作成できません。
このケースでも、60分程度間隔をあけて再度[Create bucket]ボタンを押下したところ、S3バケットが正常に作成されることを確認できました。
結論・考察
- S3バケットを一度作成・削除し、直後に同名のS3バケットを別リージョンで再作成しようとすると、結果整合性の影響を受けて失敗する。
- 公式としては最大72時間間隔を置くことが推奨されているが、手元での検証では、60分程度時間を置いた後に再作成すると問題なく作成が完了する。
- S3バケットを一度作成・削除し、直後に同名のS3バケットを同リージョンで再作成しようとすると、問題なく再作成される。
- 別リージョンへの再作成と、同リージョンへの再作成の違いについて:
S3バケットを削除した直後は、リージョン内にその履歴情報が残っており、「この名前のS3バケットは既に削除されている」ということがリージョン内の情報のみで判断できるため、同リージョンで再作成した際はApplyが問題なく完了する。(これはあくまで私の考察です)
さいごに
今回は、TerraformでS3バケットを作成・削除後、別リージョンで同じ名前のS3バケットを再作成するとApplyが終わらず作成が完了しない件について、原因と検証の結果をご紹介しました。
★追記:2025/03/25★
本ブログ記事を公開した後、TerraformでS3バケットを作成しようとした際にまた別の事象が2件発生したので、追記します。
事象1. S3バケットライフサイクルを定義している箇所で「filterの指定がない」と警告が出る。
内容
以下の通りS3バケットライフサイクルを定義し、Planを実行しました。
resource "aws_s3_bucket_lifecycle_configuration" "this" {
bucket = aws_s3_bucket.this.id
rule {
id = var.lifecycle_config_id
status = "Enabled"
expiration {
days = var.expiration_days
}
abort_incomplete_multipart_upload {
days_after_initiation = 7
}
}
depends_on = [aws_s3_bucket_versioning.this]
}
すると「filterの指定がない」という意図のWarningが確認されました。
Warning: Invalid Attribute Combination
with module.vpc_flow_logs_bucket.aws_s3_bucket_lifecycle_configuration.this,
on xxx/s3/main.tf line 44, in resource "aws_s3_bucket_lifecycle_configuration" "this":
44: rule {
No attribute specified when one (and only one) of [rule[0].prefix.<.filter]
is required
This will be an error in a future version of the provider
原因
AWSProviderのバージョンアップに伴う仕様変更により、Prefix属性がDepricatedになったことが原因と分かりました。
対応方法
現在の仕様では、Filter属性を指定しないとPrefix属性が使われ、自動的にDepricatedな状態になってしまうため、明示的にFilterの指定する必要があります。
そこで、以下の通りブランクのFilter属性を指定します。
resource "aws_s3_bucket_lifecycle_configuration" "this" {
bucket = aws_s3_bucket.this.id
rule {
id = var.lifecycle_config_id
status = "Enabled"
filter {}
expiration {
days = var.expiration_days
}
abort_incomplete_multipart_upload {
days_after_initiation = 7
}
}
depends_on = [aws_s3_bucket_versioning.this]
}
しかし、上記コードでも別のWarningが発生します。
Warning: Invalid Attribute Combination
with module.ssm_bastion_logs_bucket.aws_s3_bucket_lifecycle_configuration.this,
on xxx/modules/s3/main.tf line 53, in resource "aws_s3_bucket_lifecycle_configuration" "this":
53: filter {}
No attribute specified when one (and only one) of [rule[0].filter[0].prefix.<.object_size_greater_than,rule[0].filter[0].prefix.<.object_size_less_than,rule[0].filter[0].prefix.<.and,rule[0].filter[0].prefix.<.tag] is required
This will be an error in a future version of the provider
このWarningについては、AWSProvider5.90のバージョンアップに伴うバグである可能性が出ています。
(参考)
そのため、今現在ユーザー側で対応できることは無く、開発コミュニティにて対応されることを待つ状況となっています。
事象2. S3バケットライフサイクルを定義している箇所でエラーが発生し、Applyが止まることがある
内容
事象1と同様のソースコードを利用し、Applyを実行しました。
resource "aws_s3_bucket_lifecycle_configuration" "this" {
bucket = aws_s3_bucket.this.id
rule {
id = var.lifecycle_config_id
status = "Enabled"
expiration {
days = var.expiration_days
}
abort_incomplete_multipart_upload {
days_after_initiation = 7
}
}
depends_on = [aws_s3_bucket_versioning.this]
}
すると「リソースが見つからない」という意図のErrorが発生し、Applyが失敗することが確認されました。これは毎回発生するわけではなく、発生した場合でも、もう1度Applyを実行するとリソースの作成は成功します。
Error: creating S3 Bucket (xxx) Lifecycle Configuration
with module.vpc_front_flow_logs_bucket.aws_s3_bucket_lifecycle_configuration.this,
on xxx/modules/s3/main.tf line 42, in resource "aws_s3_bucket_lifecycle_configuration" "this":
42: resource "aws_s3_bucket_lifecycle_configuration" "this" {
couldn't find resource
原因
AWSProvider5.86のバージョンアップに伴うバグである可能性が出ています。
対応方法
既にGitHub上にIssueとして上がっており、PullRequestが3/11に作られているため、近日中に対応がなされると推測します。
そのため、こちらも今現在ユーザー側で対応できることは無く、開発コミュニティにて対応されることを待つ状況となっています。
新規に見つかった事象は2件ともTerraformのバグである可能性が高く、いま私たちにできることは少ないため、コミュニティにて早急に対応されることを願います。
本記事が、だれかの一助になれば幸いです。
Accenture Japan - ICE (有志) により固定
Cloudのキャリア・採用情報 | アクセンチュア
女性が活躍する職場|採用情報 | アクセンチュア
Discussion