概要
- 今回は、terraform を使用して、aws_s3_bucket_notification (S3のイベント通知)を設定した際にハマってしまった事例を紹介します。
- シチュエーションとしては、既存に、S3 バケットおよびLambda、S3 のイベント通知が設定されている環境があるとします。こちらの既存環境は、terraform で管理されていません。この環境に、terraform を使用し、追加でLambda、S3 のイベント通知を設定します。目指すべき姿は、1つのS3 バケットに、2つのイベント通知が設定されている状態でした。しかし、aws_s3_bucket_notification は、既存のS3イベント通知を上書きしてしまいました。
前提条件
- 今回検証に使用した環境は、以下のTerraform を使用しています。
$ terraform providers -version Terraform v1.7.5 on linux_amd64 + provider registry.terraform.io/hashicorp/archive v2.4.2 + provider registry.terraform.io/hashicorp/aws v5.44.0
変更前
- 変更前は、既存のLambda(例: niikawa-tf-lambda-1)のトリガにS3 が設定されていることが分かります。

- S3 バケットにも既存のイベント通知が 1件設定されています。(フィルターにprefixの test1/ 設定され、送信先にniikawa-tf-lambda-1 が設定されている)

terraform が既存のS3イベント通知を上書きする流れ
- それでは、terraform を使用し、S3のイベント通知を設定します。S3のイベント通知に関するコードのサンプルを以下に記載します。設定対象のS3 バケット名は、”niikawa-tf-test” とします。
resource "aws_s3_bucket_notification" "resources_1" {
bucket = "niikawa-tf-test"
eventbridge = false
lambda_function {
events = ["s3:ObjectCreated:Put"]
filter_prefix = "test2/"
filter_suffix = null
lambda_function_arn = "arn:aws:lambda:ap-northeast-1:111111111111:function:niikawa-tf-lambda-2"
}
}- terraform apply を実行します。今回は説明の便宜上、aws_s3_bucket_notification のみ実行しています。
- terraform apply の実行は成功、結果は「Resources: 1 added, 0 changed, 0 destroyed.」となりました。1つのリソースが追加されただけで、特に変更や削除は発生していないように見受けられます。
Terraform will perform the following actions:
# aws_s3_bucket_notification.resources_1 will be created
+ resource "aws_s3_bucket_notification" "resources_1" {
+ bucket = "niikawa-tf-test"
+ eventbridge = false
+ id = (known after apply)
+ lambda_function {
+ events = [
+ "s3:ObjectCreated:Put",
]
+ filter_prefix = "test2/"
+ id = (known after apply)
+ lambda_function_arn = "arn:aws:lambda:ap-northeast-1:111111111111:function:niikawa-tf-lambda-2"
}
}
Plan: 1 to add, 0 to change, 0 to destroy.
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_s3_bucket_notification.resources_1: Creating...
aws_s3_bucket_notification.resources_1: Creation complete after 1s [id=niikawa-tf-test]
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
- それでは、AWS コンソールから対象のリソースを確認します。
- 期待と異なり、変更前は存在した既存のLambda(例: niikawa-tf-lambda-1)のトリガが削除されてしまいました。

- S3 バケットを確認します。イベント通知は 2件設定されている状態を期待しましたが、既存の設定は削除され、新規の1件のみが設定されています。(フィルターにprefixの test2/ 設定され、送信先にniikawa-tf-lambda-2 が設定されている)

なぜ既存のイベント通知設定が消えた?
- S3 のイベント通知は、S3 の仕様で単一の構成のみサポートされているようです。複数の通知を設定する場合は、1つのリソース内に複数の通知を定義する必要があります。
- つまり、aws_s3_bucket_notification (S3のイベント通知)は、上書きする前提でコードを作成する必要があるわけです。
S3 Buckets only support a single notification configuration. Declaring multiple aws_s3_bucket_notification resources to the same S3 Bucket will cause a perpetual difference in configuration. See the example “Trigger multiple Lambda functions” for an option.
(出典:https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_notification)
- せめて、terraform plan、terraform apply の実行結果で、changed, destroyed の表示があれば、回避できたかもしれません。AWSサービスの仕様を正しく理解する必要がありますね。
回避策
- 公式のサンプルを参考に、tf コードを修正します。
- 1つのaws_s3_bucket_notificationリソース内に複数のLambda 関数を指定します。
resource "aws_s3_bucket_notification" "resources_1" {
bucket = "niikawa-tf-test"
eventbridge = false
lambda_function {
events = ["s3:ObjectCreated:Put"]
filter_prefix = "test1/"
filter_suffix = null
lambda_function_arn = "arn:aws:lambda:ap-northeast-1:111111111111:function:niikawa-tf-lambda-1"
}
lambda_function {
events = ["s3:ObjectCreated:Put"]
filter_prefix = "test2/"
filter_suffix = null
lambda_function_arn = "arn:aws:lambda:ap-northeast-1:111111111111:function:niikawa-tf-lambda-2"
}
}
- terraform apply を実行します。
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the
following symbols:
+ create
Terraform will perform the following actions:
# aws_s3_bucket_notification.resources_1 will be created
+ resource "aws_s3_bucket_notification" "resources_1" {
+ bucket = "niikawa-tf-test"
+ eventbridge = false
+ id = (known after apply)
+ lambda_function {
+ events = [
+ "s3:ObjectCreated:Put",
]
+ filter_prefix = "test1/"
+ id = (known after apply)
+ lambda_function_arn = "arn:aws:lambda:ap-northeast-1:111111111111:function:niikawa-tf-lambda-1"
}
+ lambda_function {
+ events = [
+ "s3:ObjectCreated:Put",
]
+ filter_prefix = "test2/"
+ id = (known after apply)
+ lambda_function_arn = "arn:aws:lambda:ap-northeast-1:111111111111:function:niikawa-tf-lambda-2"
}
}
Plan: 1 to add, 0 to change, 0 to destroy.
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_s3_bucket_notification.resources_1: Creating...
aws_s3_bucket_notification.resources_1: Creation complete after 1s [id=niikawa-tf-test]
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
- S3 バケットを確認します。イベント通知は期待通り、2件設定されています。(既存の設定が保持されたわけではなく、上書きです)

- 今回は手動でtf コードを修正していますが、状況に応じてTerraform import ブロックを使用する方法もあります。Terraform import ブロックの使い方は、こちらの記事を参考ください。