You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Terraform的for_each基于嵌套变量生成Azure LB NAT规则

解决Terraform遍历嵌套变量创建Azure LB NAT规则的问题

方案一:基于原有嵌套变量结构处理

如果想保留现有var.test的嵌套结构(map包含t1/t2,每个条目下有top数组),可以通过flatten函数将嵌套结构转为一维列表,再用for_each遍历生成资源。

1. 变量定义(保持原有结构)

variable "test" {
  type = map(object({
    top = list(object({
      port = number
      name = string
    }))
  }))
  default = {
    t1 = {
      top = [
        { port = 12, name = "port12" },
        { port = 123, name = "port123" }
      ]
    },
    t2 = {
      top = [
        { port = 12, name = "port12" },
        { port = 123, name = "port123" }
      ]
    }
  }
}

2. 生成扁平规则列表

通过flatten把嵌套的map+list结构转为一维,确保每个NAT规则对应一个独立的元素:

locals {
  nat_rules_flat = flatten([
    for prefix, group in var.test : [
      for item in group.top : {
        unique_key = "${prefix}-${item.name}"
        prefix     = prefix
        port       = item.port
        name_part  = item.name
      }
    ]
  ])
}

3. 创建NAT规则资源

用for_each遍历扁平后的列表,生成符合要求的资源:

resource "azurerm_lb_nat_rule" "example" {
  for_each = { for rule in local.nat_rules_flat : rule.unique_key => rule }

  name                   = "ELB-${upper(each.value.prefix)}-${each.value.name_part}"
  loadbalancer_id        = azurerm_lb.example.id # 替换为你的负载均衡器ID
  frontend_ip_configuration_id = azurerm_lb.example.frontend_ip_configuration[0].id # 替换为你的前端IP配置ID
  protocol               = "Tcp"
  frontend_port          = each.value.port
  backend_port           = each.value.port
}

方案二:调整变量为扁平结构(更易维护)

如果可以调整变量结构,直接定义成一维列表会更简洁,避免嵌套遍历的复杂度:

1. 调整后的变量定义

variable "nat_rules" {
  type = list(object({
    prefix       = string # 对应原有的t1/t2
    port         = number
    name_suffix  = string # 对应原有的port12/port123
  }))
  default = [
    { prefix = "T1", port = 12, name_suffix = "port12" },
    { prefix = "T2", port = 12, name_suffix = "port12" },
    { prefix = "T1", port = 123, name_suffix = "port123" },
    { prefix = "T2", port = 123, name_suffix = "port123" }
  ]
}

2. 直接创建NAT规则资源

resource "azurerm_lb_nat_rule" "example" {
  for_each = { for rule in var.nat_rules : "${rule.prefix}-${rule.name_suffix}" => rule }

  name                   = "ELB-${each.value.prefix}-${each.value.name_suffix}"
  loadbalancer_id        = azurerm_lb.example.id
  frontend_ip_configuration_id = azurerm_lb.example.frontend_ip_configuration[0].id
  protocol               = "Tcp"
  frontend_port          = each.value.port
  backend_port           = each.value.port
}

关键说明

  • 两种方案都会生成符合要求的NAT规则名称:ELB-T1-port12、ELB-T2-port12等
  • for_each使用唯一键(如T1-port12)确保资源实例唯一,避免Terraform重复创建或报错
  • frontend_port和backend_port直接引用变量中的端口值,满足需求

内容的提问来源于stack exchange,提问作者Wanexa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 17:57:25