はじめに
Terraformを使ってAWSリソースを管理していると、for_each のキー順がズレてしまい、リソースが destroy → create されてしまうことがあります。
特に ALBとWAFの関連付け (aws_wafv2_web_acl_association) などは一瞬でも外れるとサービス影響が出るため、再作成は避けたいところです。
この記事では、実際に遭遇したケースと、terraform state mv を使った回避方法を紹介します。
問題の状況
Terraformのplan結果を見ると、同じALB/WAFの組み合わせにも関わらず、
- ["4"] が destroy
- ["3"] が create
と判定されていました。
# module.waf.aws_wafv2_web_acl_association.this["3"] will be created
+ resource "aws_wafv2_web_acl_association" "this" {
+ id = (known after apply)
+ region = "ap-northeast-1"
+ resource_arn = "arn:aws:elasticloadbalancing:...:loadbalancer/app/example-alb-b/xxxx"
+ web_acl_arn = "arn:aws:wafv2:...:webacl/example-waf/xxxx"
}
# module.waf.aws_wafv2_web_acl_association.this["4"] will be destroyed
- resource "aws_wafv2_web_acl_association" "this" {
- id = "arn:aws:wafv2:...,arn:aws:elasticloadbalancing:...:loadbalancer/app/example-alb-b/xxxx" -> null
- region = "ap-northeast-1" -> null
- resource_arn = "arn:aws:elasticloadbalancing:...:loadbalancer/app/example-alb-b/xxxx" -> null
- web_acl_arn = "arn:aws:wafv2:...:webacl/example-waf/xxxx" -> null
}
原因は for_each のキーが “4” → “3” にズレた ためです。
中身は同じなのにTerraformは「別リソース」と判断してしまいます。
状態遷移のイメージ図
キーのズレによる再作成を図で表すと、以下のようなイメージです。
Before (stateファイル)
├─ this["3"] → ALB-A
└─ this["4"] → ALB-B
After (新しいfor_eachの判定)
├─ this["3"] → ALB-B
└─ this["4"] → (なし)
Terraformの判断
- this["4"] destroy
+ this["3"] create
実際には同じALB/WAFの組み合わせなのに「入れ替わっただけ」として認識されず、
destroy → create が発生してしまいます。
解決策:terraform state mvでキーを入れ替える
再作成を防ぐには、Terraformのstateファイル上でキーを入れ替えればOKです。
1. バックアップを取る
まずは安全のため、現在のstateをバックアップします。
terraform state pull > backup-$(date +%Y%m%d-%H%M%S).tfstate
ls -lh backup-*.tfstate
例:
-rw-r--r-- 1 user staff 805K 9 12 16:10 backup-20250912-161039.tfstate
2.stateの入れ替え手順
# 1) 既存の ["3"] (ALB-A) を一時キーに退避
terraform state mv \
'module.waf.aws_wafv2_web_acl_association.this["3"]' \
'module.waf.aws_wafv2_web_acl_association.this["__tmp__3"]'
# 2) ["4"] (ALB-B) → ["3"] へ移動
terraform state mv \
'module.waf.aws_wafv2_web_acl_association.this["4"]' \
'module.waf.aws_wafv2_web_acl_association.this["3"]'
# 3) 退避していた ALB-A を ["4"] に戻す
terraform state mv \
'module.waf.aws_wafv2_web_acl_association.this["__tmp__3"]' \
'module.waf.aws_wafv2_web_acl_association.this["4"]'
3.planで確認
terraform plan
リソースが再作成されず、差分なしになれば成功です。
まとめ
- for_each のキー順が変わると、Terraformは「destroy → create」と誤認識する
- ALBとWAFの関連付けのように 一瞬でも外れると影響が出るリソースは要注意
- terraform state mv を使ってキーを入れ替えることで、安全に回避できる
おわりに
ポイントは 作業前に必ずstateのバックアップを取ることです。
Terraformのstate操作は強力ですが、その分リスクもあるので慎重に進めましょう。
参考
Terraform関連記事