Terraformで構築したリソースが消えない問題を解決する手順 (Google Cloud)
はじめに
こんにちは!クラウドエース SRE部所属の喜村と申します。
今回は、Terraform で環境構築をしている際に起こった不思議な出来事を紹介したいと思います。
概要
コードで該当部分を削除し apply
コマンドを実行しても、destroy
コマンドでも消えないサブネットがあったので、stateファイルから削除して、コンソールから削除したら消えました。
前提
- stateファイルは Cloud Storage (GCS)に保管
- 実行環境:Windows
事象
テスト用に作成していた不要なサブネットを削除しようとしたところ、 terraform apply
や terraform destroy
を何度実行しても削除できないという問題が発生しました。
terraform plan
を実行しても削除対象として表示されるだけで、実際には削除されませんでした。
手順
state ファイルから削除したい設定が消えず、state ファイルを編集することは出来るのかと探すと下記のやり方で、特定の設定値を削除することが出来ました。
今回はその手順について、ご紹介します。
状態確認
-
まずは tfstate で管理しているリソースのリストを確認します。
terraform state list
上記のコマンドで、モジュールを含むすべてのリソースを一覧表示出来るので、確認します。
参考: 公式ドキュメント
-
一覧結果から削除したいサブネットを見つけます。
google_dns_record_set.default["private.googleapis.com."] module.example-subnet["fujimi-subnet"].google_compute_subnetwork.subnet ★ module.example-subnet["test-subnet"].google_compute_subnetwork.subnet module.cloud_armor.google_compute_security_policy.policy ~省略~
★:削除したいサブネット
-
サブネットの設定を確認します。
terraform state show module.be-subnet["fujimi_subnet"].google_compute_subnetwork.subnet
上記コマンドを実行すると以下のようなエラーが出て怒られました。
Error parsing instance address: module.be-subnet[fujimi_subnet].google_compute_subnetwork.subnet This command requires that the address references one specific instance. To view the available instances, use "terraform state list". Please modify the address to reference a specific instance.
どうやら PowerShell で Terraform を実行するには、指定のやり方があるようです。公式ドキュメント
特殊文字をエスケープして、コマンドを実行します。terraform state show 'module.be-subnet[/"fujimi_subnet/"].google_compute_subnetwork.subnet'
設定が確認出来ました!
module.be-subnet["fujimi_subnet"].google_compute_subnetwork.subnet: resource "google_compute_subnetwork" "subnet" { creation_timestamp = "2024-03-14T19:39:48.085-07:00" gateway_address = "10.10.0.1" id = "XXX" ip_cidr_range = "10.10.0.0/16" name = "fujimi_subnet" network = "XXX" private_ip_google_access = true private_ipv6_google_access = "DISABLE_GOOGLE_ACCESS" project = "XXX" purpose = "PRIVATE" region = "asia-northeast1" secondary_ip_range = [] self_link = "XXX" stack_type = "IPV4_ONLY" }
stateファイルから削除
-
stateファイルからサブネットを削除します。
terraform state rm 'module.be-subnet[\"fujimi_subnet\"].google_compute_subnetwork.subnet'
Removed module.be-subnet["fujimi_subnet"].google_compute_subnetwork.subnet Successfully removed 1 resource instance(s).
よしよし、削除されたようですね。
削除後の確認
- サブネットが削除されたか確認します。
terraform state show 'module.be-subnet[\"fujimi_subnet\"].google_compute_subnetwork.subnet'
上記のようにエラーが出ると思いますので、改めて下記のコマンドでサブネットが正しく削除されたことを確認します。No instance found for the given address! This command requires that the address references one specific instance. To view the available instances, use "terraform state list". Please modify the address to reference a specific instance.
terraform state list
消えました!google_dns_record_set.default["private.googleapis.com."] module.example-subnet["test-subnet"].google_compute_subnetwork.subnet module.cloud_armor.google_compute_security_policy.policy ~省略~
これでstateファイル上では削除されました。
コンソール上からサブネットを削除
最後に、コンソール上からサブネットを削除して終わりになります。
おわりに
今回は、Terraformでの環境構築中に発生した、サブネットの削除ができないという問題とその解決方法について解説しました。
Terraformは便利なツールであり、私たちの仕事を大いに助けてくれますが、同時に複雑な問題を引き起こすこともあります。
今後も、遭遇した問題や解決策を共有していきますので、お楽しみに!
Discussion
もったいない。state rm して手動削除は最後の手段がいいでしょう。
この記事にかかれているのは解決方法ではなく対処療法に過ぎません。
事象に書かれていることが本当なら、terraform でログを出力してみて、削除されなかった理由を明確にするのが先決です。
ちなみに、google cloud の VPC(やサブネット)は、関連リソースがある場合にプログラム的に削除に失敗する例が多くあります(AWSでも似たようなことは起きます)
こういうのです
削除対象のリソースが削除できないケースには大抵ちゃんとした理由があり、デバッグでだいたい把握できるはずです(不思議で片付けてはいけません)。
対象のリソースが何かを特定できれば、関連情報としてissueに追加できたかもしれませんし、同様の事象にはまる人の助けになるかもしれません。