如何在Terraform中合并两个变量并用于for_each循环?
解决Terraform变量合并的问题
错误原因
Terraform变量的default字段仅支持静态值或直接引用其他变量,不允许在变量定义中调用函数(如merge、concat),这是语法层面的硬性限制,所以你之前的写法会触发报错。
正确方案:使用本地值(Locals)合并数据
应该通过locals块来处理变量的合并逻辑,而非定义新变量。同时需要注意:你的apps和acl两个Map的键并不直接对应,需要通过共同标识(比如apps.labels.name和acl.ingress字段)关联两者,确保每个应用匹配到对应的ACL规则。
步骤1:定义本地值合并数据
在配置文件中添加locals块,将apps与对应的acl条目合并:
locals { merged_vars = { for app_key, app_details in var.apps : app_key => merge( app_details, # 根据应用的labels.name匹配ACL的ingress字段,找到对应配置 lookup( var.acl, [for acl_key, acl_details in var.acl : acl_key if acl_details.ingress == app_details.labels.name][0], # 无匹配时返回空对象避免报错,可根据需求调整默认值 {} ) ) } }
步骤2:在资源中使用合并后的数据
修改kubernetes_network_policy资源的for_each,引用本地值:
resource "kubernetes_network_policy" "acl" { for_each = local.merged_vars metadata { name = format("%s-acl", each.value.acl_name) namespace = each.value.acl_name # 注意:可根据实际需求调整,比如改用应用名称而非ACL名称 } spec { policy_types = ["Ingress", "Egress"] pod_selector { match_labels = { tier = each.value.labels.tier } } ingress { from { namespace_selector { match_labels = { name = each.value.ingress } } } ports { port = each.value.port protocol = each.value.protocol } } egress { to { ip_block { cidr = each.value.egress } } } } }
额外修正:修复变量定义中的语法错误
你的apps变量存在多余闭合括号的语法问题,修正后如下:
variable "apps" { type = map(object({ app_name = string labels = map(string) annotations = map(string) image = string })) default = { "app1_name" = { app_name = "app1_name" labels = { "name" = "stream-frontend" "tier" = "web" "owner" = "product" } annotations = { "serviceClass" = "web-frontend" "loadBalancer/class" = "external" } image = "nginx" # 修正原拼写错误nxinx } "app2_name" = { app_name = "app2_name" labels = { "name" = "stream-frontend" "tier" = "web" "owner" = "product" } annotations = { "serviceClass" = "web-frontend" "loadBalancer/class" = "external" } image = "nginx" } "app3_name" = { app_name = "app3_name" labels = { "name" = "stream-database" "tier" = "shared" "owner" = "product" } annotations = { "serviceClass" = "disabled" "loadBalancer/class" = "disabled" } image = "Mongo" } } }
说明
locals是Terraform处理动态计算逻辑的标准位置,支持调用所有Terraform函数。- 合并逻辑通过
for表达式遍历应用,再通过lookup匹配对应ACL规则,确保每个应用能获取到端口、协议等配置。 - 若存在应用无匹配ACL规则的情况,
lookup的默认空对象可避免报错,你也可以添加校验逻辑(如assert)强制要求匹配。
内容的提问来源于stack exchange,提问作者zolo
相关产品推荐
相关产品推荐

