Terraformで別リソースに関連付けられたリソースの再作成を行うための備忘録
はじめに
みなさん、こんにちは。良いタイトルが思いつかずリソースを連呼する人になりました。
本題ですが、Terraform でリソースを作成する際、以下のようなケースに直面することがあるのではないでしょうか(ありますよね…?
- リソース作成時、とあるArgument の値を間違えて作成してしまった(ちゃんと確認しましょう
- そのArgument の値を変更すると新しいリソースが強制的に作成されるとドキュメントに記載されている。
- terraform plan は通ったので実行すると、関連付けられたリソースがいるため、再作成できずエラーとなってしまう
- GUIで関連付けを解除してtfstate ファイルを直接変更するといった手法は取らず、Terraform 上で完結させたい
Terraform に慣れた方ならすぐ解法が浮かぶと思いますが、私は「どうしようかな」となったので、備忘も兼ねて記事を書いてみようと思います。
結論:一時的に別リソースを作成して対処しました
例として、以下のようなケースを考えます(今の案件がAzure のためAzure を例示しますが、AWS やGCP でも同様かと…
- Application Gateway (L7のロードバランサー)にWAFポリシーを関連付けて作成。
- 上記WAFポリシーの名前を間違えて作成したため、
terraform.tfvars
に記載された値を修正。 - plan を実行し、destroy とcreate により再作成が行われることを確認。
- apply 実行後、「WAFポリシーを削除できませんでした」というエラーが発生して終了。
なぜ起きるのか
これは例の3と4にあるとおりですが、リソース再作成の際にはTerraform がdestroy→create を行うため、削除に失敗するとcreate も出来ないというのが理由となります。
ではなぜ削除に失敗するかというと、1にあるロードバランサーがWAFを必須とするタイプのものであり、関連付けを行ったあとにWAFポリシーのみ削除することが出来ない、という仕様が原因でした。(このあたりは関連付けしているサービスの仕様を抑えないといけないなと感じました)
そのため、結論に書いたとおり、一時的に新しいWAFポリシーを作成し、ロードバランサーに関連付けを行うとともに、間違えて作成したWAFポリシーの名前を変更後、再度関連付けを行うという手法を取りました。最後に一時的に作成したリソースを削除して完了です。
具体的なイメージは以下のとおりです(途中のapplyはまとめることが出来ると思います)
1.初期状態:誤った名前で作成したWAFポリシー"CORRECT"の名前を変更したいが、関連付けによりWAFポリシー削除不可の状態
Application Gateway FIXED : WAFポリシー"CORRECT"が関連付けられた状態
WAFポリシー CORRECT : Application Gateway"FIXED"に関連付けられた状態
# WAF_v2 で作成したApplication Gateway
resource "azurerm_application_gateway" "FIXED" {
name = "NAME_FIXED"
# 1.WAFポリシー"CORRECT"と関連付け
firewall_policy_id = azurerm_web_application_firewall_policy.CORRECT.id
}
# 誤った名称で作成したWAFポリシー
resource "azurerm_web_application_firewall_policy" "CORRECT" {
# 1.誤った名称"NAME_WRONG"
name = "NAME_WRONG"
}
2.新しいWAFポリシー"TMP"を仮作成してapply
Application Gateway FIXED : WAFポリシー"CORRECT"が関連付けられた状態
WAFポリシー CORRECT : Application Gateway"FIXED"に関連付けられた状態
WAFポリシー TMP : 独立した状態
# WAF_v2 で作成したApplication Gateway
resource "azurerm_application_gateway" "FIXED" {
name = "NAME_FIXED"
firewall_policy_id = azurerm_web_application_firewall_policy.CORRECT.id
}
# 誤った名称で作成したWAFポリシー
resource "azurerm_web_application_firewall_policy" "CORRECT" {
name = "NAME_WRONG"
}
# 2.WAFポリシーを仮作成
resource "azurerm_web_application_firewall_policy" "TMP" {
name = "NAME_TMP"
}
3.仮作成したWAFポリシー"TMP"をApplication Gateway に関連付けてapply
Application Gateway FIXED : WAFポリシー"TMP"が関連付けられた状態
WAFポリシー CORRECT : 関連付けが外れて独立した状態
WAFポリシー TMP : Application Gateway"FIXED"に関連付けられた状態
# WAF_v2 で作成したApplication Gateway
resource "azurerm_application_gateway" "FIXED" {
name = "NAME_FIXED"
# 3.仮作成したWAFポリシー"TMP"と関連付け
firewall_policy_id = azurerm_web_application_firewall_policy.TMP.id
}
# 誤った名称で作成したWAFポリシー
resource "azurerm_web_application_firewall_policy" "CORRECT" {
name = "NAME_WRONG"
}
# WAFポリシーを仮作成
resource "azurerm_web_application_firewall_policy" "TMP" {
name = "NAME_TMP"
}
4.WAFポリシー"CORRECT"の名前を変更してapply(再作成)
Application Gateway FIXED : WAFポリシー"TMP"が関連付けられた状態
WAFポリシー CORRECT : name = "NAME_WRONG"
で作成されたWAFポリシーを削除(destroy)後、name="CORRECT"
のWAFポリシー"CORRECT"を再作成
WAFポリシー TMP : Application Gateway"FIXED"に関連付けられた状態
# WAF_v2 で作成したApplication Gateway
resource "azurerm_application_gateway" "FIXED" {
name = "NAME_FIXED"
firewall_policy_id = azurerm_web_application_firewall_policy.TMP.id
}
# 誤った名称で作成したWAFポリシー
resource "azurerm_web_application_firewall_policy" "CORRECT" {
# 4.この名前を変更してapplyすることでリソースが再作成(destroy→create)される
# name = "NAME_WRONG"
name = "NAME_CORRECT"
}
# WAFポリシーを仮作成
resource "azurerm_web_application_firewall_policy" "TMP" {
name = "NAME_TMP"
}
5.WAFポリシー"CORRECT"とApplication Gateway"FIXED" を関連付けしてapply
Application Gateway FIXED : WAFポリシー"CORRECT"が関連付けられた状態
WAFポリシー CORRECT : Application Gateway"FIXED"に関連付けられた状態
WAFポリシー TMP : 関連付けが外れて独立した状態
# WAF_v2 で作成したApplication Gateway
resource "azurerm_application_gateway" "FIXED" {
name = "NAME_FIXED"
# 5.WAFポリシー"CORRECT"と再度関連付けを行う
firewall_policy_id = azurerm_web_application_firewall_policy.CORRECT.id
}
# 誤った名称で作成したWAFポリシー
resource "azurerm_web_application_firewall_policy" "CORRECT" {
# この名前を変更することでリソースが再作成(destroy→create)される
# name = "NAME_WRONG"
name = "NAME_CORRECT"
}
# WAFポリシーを仮作成
resource "azurerm_web_application_firewall_policy" "TMP" {
name = "NAME_TMP"
}
6.仮作成したWAFポリシー"TMP"の記述を削除してapply
Application Gateway FIXED : WAFポリシー”CORRECT”が関連付けられた状態
WAFポリシー CORRECT : Application Gateway”FIXED”に関連付けられた状態
WAFポリシー TMP : 削除された状態
# WAF_v2 で作成したApplication Gateway
resource "azurerm_application_gateway" "FIXED" {
name = "NAME_FIXED"
firewall_policy_id = azurerm_web_application_firewall_policy.CORRECT.id
}
# 誤った名称で作成したWAFポリシー
resource "azurerm_web_application_firewall_policy" "CORRECT" {
# name = "NAME_WRONG"
name = "NAME_CORRECT"
}
# 6.仮作成のWAFポリシーは記述自体を削除(Terraform がdestory してくれる)
長くなりましたが、ここまで対応することで、誤った名称で作成したWAFポリシーの名称を変更し、元のロードバランサーに関連付けを行うことができました。
まとめ
今回はtfstate ファイルに手を加えたくない、そもそもAzure にそこまで明るくない()というのもあって、このような少し冗長な手法を取りました。一番はレビューでしっかりと確認することですが、どうしても抜け漏れは出てしまうと思います。そのような場合でも、Terraform の管理内でリソースを上手く更新していくために、色々なパターンに遭遇して知見を貯めておきたいな、と改めて感じました。
他にもっと良い方法をご存知の方がいらっしゃれば、ぜひコメントいただけたら幸いです。
最後までお読みいただき、ありがとうございました!
Discussion