Terraform导入GCP Crypto Key后执行apply仍报已存在错误
Terraform导入GCP KMS密钥后执行apply报409错误的解决方法
问题场景
手动创建了GCP KMS CryptoKey,执行导入命令后显示成功:
$ terraform import google_kms_crypto_key.some-key some-gcp-project-id/us/some-keyring/some-key google_kms_crypto_key.some-key: Refreshing state... [id=projects/some-gcp-project-id/locations/us/keyRings/some-keyring/cryptoKeys/some-key] Import successful! The resources that were imported are shown above. These resources are now in your Terraform state and will henceforth be managed by Terraform.
但执行terraform apply时收到资源已存在的409错误:
Error: Error creating CryptoKey: googleapi: Error 409: CryptoKey projects/some-gcp-project-id/locations/us/keyRings/some-keyring/cryptoKeys/some-key already exists.
查看terraform plan输出,发现Terraform要销毁已导入的密钥实例,再创建新实例:
# google_kms_crypto_key.some-key[1] will be destroyed - resource "google_kms_crypto_key" "some-key" { - destroy_scheduled_duration = "86400s" -> null - id = "projects/some-gcp-project-id/locations/us/keyRings/some-keyring/cryptoKeys/some-key" -> null - import_only = false -> null - key_ring = "projects/some-gcp-project-id/locations/us/keyRings/some-keyring" -> null - labels = {} -> null - name = "some-key" -> null - purpose = "ENCRYPT_DECRYPT" -> null - rotation_period = "2592000s" -> null - skip_initial_version_creation = false -> null - timeouts {} - version_template { - algorithm = "GOOGLE_SYMMETRIC_ENCRYPTION" -> null - protection_level = "SOFTWARE" -> null } } # google_kms_crypto_key.some-key["some-key"] will be created + resource "google_kms_crypto_key" "some-key" { + destroy_scheduled_duration = (known after apply) + id = (known after apply) + import_only = (known after apply) + key_ring = "projects/some-gcp-project-id/locations/us/keyRings/some-keyring" + name = "some-key" + purpose = "ENCRYPT_DECRYPT" + rotation_period = "2592000s" + version_template { + algorithm = (known after apply) + protection_level = (known after apply) } }
原因分析
核心问题是导入时指定的资源实例标识和配置中的资源集合索引不匹配:
- 你的
google_kms_crypto_key.some-key是用for_each或count定义的集合资源(不是单个资源)。 - 导入时未指定集合的索引/键,Terraform默认给该实例分配了数字索引
[1],但你的配置中实际使用的是字符串键["some-key"](比如for_each = toset(["some-key"]))。 - Terraform将状态中的
[1]实例和配置中的["some-key"]实例判定为两个不同的资源,因此会尝试销毁旧实例、创建新实例,但两者对应同一个GCP KMS密钥,最终触发409冲突。
解决步骤
移除状态中索引错误的资源
terraform state rm 'google_kms_crypto_key.some-key[1]'使用配置中匹配的索引/键重新导入
- 如果是
for_each定义的字符串键:terraform import 'google_kms_crypto_key.some-key["some-key"]' some-gcp-project-id/us/some-keyring/some-key - 如果是
count定义的数字索引(比如count=1时索引为0):terraform import 'google_kms_crypto_key.some-key[0]' some-gcp-project-id/us/some-keyring/some-key
- 如果是
验证结果
执行terraform plan,此时Terraform应该会识别出资源配置与状态一致,不会再出现销毁和重建操作。
内容的提问来源于stack exchange,提问作者Tarun Gupta
相关产品推荐
相关产品推荐

