Terraform创建AWS Secrets时的变量类型选择咨询
正确选择:
map(object) 类型 在Terraform中使用for_each遍历资源时,绝对不能用list(object)——Terraform明确禁止for_each直接接收列表类型,原因有两个:
- 列表是顺序依赖的,元素位置变化会触发资源的销毁重建,这通常不是你想要的
for_each要求集合中的元素具有唯一、可哈希的标识符,列表的索引是临时的,不符合这个要求
而map(object)是完全适配for_each的类型,下面是具体的实现方案:
1. 定义map(object)变量
直接在variables.tf中定义结构明确的map类型变量,每个键对应一个唯一的secret标识,值包含该secret的所有配置属性:
variable "aws_secrets" { type = map(object({ vault_path = string # Vault中存储该secret的路径 secret_name = string # AWS Secrets Manager中的secret名称 kms_key_id = optional(string) # 可选:加密用的KMS密钥ID })) description = "配置要创建的AWS Secrets,键为每个secret的唯一标识" default = {} }
2. 在资源中使用for_each
遍历这个map时,用each.key作为Terraform识别资源的唯一ID,each.value获取每个secret的配置:
# 从Vault拉取secret数据 data "vault_generic_secret" "source" { for_each = var.aws_secrets path = each.value.vault_path } # 创建AWS Secrets Manager secret本体 resource "aws_secretsmanager_secret" "main" { for_each = var.aws_secrets name = each.value.secret_name kms_key_id = each.value.kms_key_id != null ? each.value.kms_key_id : null } # 创建secret版本(写入Vault拉取的内容) resource "aws_secretsmanager_secret_version" "current" { for_each = var.aws_secrets secret_id = aws_secretsmanager_secret.main[each.key].id secret_string = data.vault_generic_secret.source[each.key].data_json }
3. 为什么map(object)是最佳选择
- 稳定的资源标识:每个secret的键是固定的,即使修改secret的名称或路径,Terraform只会更新资源,不会销毁重建
- 清晰的配置结构:map的键可以用语义化的标识(比如
prod_db_creds、api_auth_token),方便维护 - 符合Terraform最佳实践:官方文档明确推荐用
map或set(string)作为for_each的输入,避免列表带来的顺序依赖问题
注意事项
- 确保map的键是唯一且不会轻易修改的,不要用可能变化的字段(比如secret名称)作为键
- 如果你的输入源只能是列表,可以用
for表达式将列表转换为map:
然后在locals { aws_secrets_map = { for s in var.aws_secrets_list : s.unique_id => s } }for_each中引用local.aws_secrets_map
内容的提问来源于stack exchange,提问作者J H
相关产品推荐
相关产品推荐

