如何通过Terraform for_each生成指定格式的Yandex IAM服务账号资源名?
问题核心
你用for_each循环创建Yandex IAM服务账号时,Terraform生成的资源地址是yandex_iam_service_account.loki["loki1"]这种带键索引的格式,但你需要的是yandex_iam_service_account.loki1这类独立资源名,以此匹配已存在的服务账号。同时你的vars.tf里存在一个明显错误:default映射中有重复的"loki2"键,这会导致Terraform解析失败,需要先修正为"loki1"和"loki2"。
原因说明
Terraform中,使用for_each或count创建的批量资源,其地址必然会带上索引(count是数字索引,for_each是映射键/集合元素),这是Terraform管理批量资源的标准规则,无法直接修改为独立资源名的格式。
解决方案
根据你的需求,有两种可行方案:
方案一:将现有服务账号导入到for_each实例中(推荐,保留批量管理能力)
这种方式不需要改变for_each的配置,只需把已存在的服务账号导入到Terraform的状态中,让Terraform识别这些实例属于yandex_iam_service_account.loki下的键实例。
- 修正vars.tf的重复键
修改后的vars.tf:
variable "loki_accounts" { description = "Map of Loki accounts to be created" type = map(object({ description = string bucket_name = string secret_name = string })) default = { "loki1" = { description = "loki 1", bucket_name = "loki1", secret_name = "secret-path-1" }, "loki2" = { description = "loki 2", bucket_name = "loki2", secret_name = "secret-path-2" } } }
- 执行导入命令关联现有资源
找到每个已存在服务账号的ID(可通过Yandex Cloud控制台或CLI获取),然后执行terraform import命令:
# 导入loki1服务账号,替换sa-xxxxxx为实际ID terraform import 'yandex_iam_service_account.loki["loki1"]' sa-xxxxxx # 导入loki2服务账号,替换sa-yyyyyy为实际ID terraform import 'yandex_iam_service_account.loki["loki2"]' sa-yyyyyy
导入完成后,执行terraform plan就会显示这些资源已存在,不会重新创建,后续可通过for_each批量管理。
方案二:放弃批量循环,逐个定义资源(适合账号数量少的场景)
如果不需要批量管理的灵活性,可以直接为每个服务账号单独定义资源块,这样资源地址就会是你需要的yandex_iam_service_account.loki1格式:
修改main.tf:
resource "yandex_iam_service_account" "loki1" { name = "loki1" description = "loki 1" } resource "yandex_iam_service_account" "loki2" { name = "loki2" description = "loki 2" }
这种方式无需导入,直接匹配已存在的资源地址,但账号数量较多时维护成本高。
内容的提问来源于stack exchange,提问作者poisoned_monkey

