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

Terraform配置Azure负载均衡器:循环语法咨询与错误修复

Terraform Azure负载均衡器循环语法错误修复

问题背景

基于给定的locals配置,尝试通过Terraform批量创建Azure负载均衡器、后端地址池、探测及规则,但执行时遇到类型错误,同时对for/foreach/dynamic的正确用法存疑。

原始Locals配置

locals {
  tiers = {
    lbs = {
      app-lb = {
        lb_name         = "app-lb"
        fip_name        = "app-fip"
        subnet_id       = "*****"
        private_ip_type = "Dynamic"

        address_pool_name = "app-address-pool"

        lb_probes = {
          ssh_probe = {"Tcp", "22"}
        }
        lb_rules = {
          ssh_rule = {"22", "Tcp", "22", "22", true}
        }
      },
      db-lb = {
        lb_name         = "db-lb"
        fip_name        = "db-fip"
        subnet_id       = "*****"
        private_ip_type = "Dynamic"

        address_pool_name = "db-address-pool"

        lb_probes = {
          ssh_probe = {"Tcp", "22"}

        }
        lb_rules = {
          ssh_rule = {"22", "Tcp", "22", "22", false}
        }
      }

    }
  }
}

核心错误信息

╷
│ Error: Incorrect attribute value type
│
│   on lb.tf line 89, in resource "azurerm_lb_backend_address_pool" "bepool":
│   89:   loadbalancer_id = [for lb_id in azurerm_lb.lb : lb_id.id]
│     ├────────────────
│     │ azurerm_lb.lb is object with 2 attributes
│
│ Inappropriate value for attribute "loadbalancer_id": string required.

错误原因分析

  1. 类型不匹配:loadbalancer_id要求单个字符串(目标负载均衡器ID),但代码返回了列表,触发类型错误。
  2. 循环逻辑混乱:
    • azurerm_lb的dynamic frontend_ip_configuration错误遍历所有LB,未关联当前LB的配置
    • 探测、后端池、规则资源未正确绑定所属LB,循环范围和关联关系错误
  3. 语法与引用错误:存在each.value.[1]这类语法错误,且未正确嵌套遍历LB下的探测和规则。

修正后的完整代码

data "azurerm_resource_group" "rg" {
  name = "test-rg"
}

data "azurerm_virtual_network" "example" {
  name                = "test-vnet"
  resource_group_name = "test-rg"
}

data "azurerm_subnet" "example" {
  name                 = "app"
  virtual_network_name = data.azurerm_virtual_network.example.name
  resource_group_name  = data.azurerm_resource_group.rg.name
}

# 创建负载均衡器
resource "azurerm_lb" "lb" {
  for_each            = local.tiers.lbs
  name                = each.value.lb_name
  location            = data.azurerm_resource_group.rg.location
  resource_group_name = data.azurerm_resource_group.rg.name

  # 单个前端IP配置,无需dynamic循环(多前端场景再用dynamic遍历当前LB的前端列表)
  frontend_ip_configuration {
    name                          = each.value.fip_name
    subnet_id                     = each.value.subnet_id
    private_ip_address_allocation = each.value.private_ip_type
  }
}

# 扁平化LB与探测的关联映射,便于循环创建
locals {
  lb_probes_flat = merge([
    for lb_key, lb in local.tiers.lbs : {
      for probe_key, probe in lb.lb_probes : "${lb_key}-${probe_key}" => {
        lb_id     = azurerm_lb.lb[lb_key].id
        probe_key = probe_key
        protocol  = probe[0]
        port      = tonumber(probe[1])
      }
    }
  ]...)
}

# 创建负载均衡器探测
resource "azurerm_lb_probe" "probe" {
  for_each        = local.lb_probes_flat
  loadbalancer_id = each.value.lb_id
  name            = each.value.probe_key
  protocol        = each.value.protocol
  port            = each.value.port
}

# 创建后端地址池(每个LB对应一个池)
resource "azurerm_lb_backend_address_pool" "bepool" {
  for_each        = local.tiers.lbs
  loadbalancer_id = azurerm_lb.lb[each.key].id
  name            = each.value.address_pool_name
}

# 扁平化LB与规则的关联映射
locals {
  lb_rules_flat = merge([
    for lb_key, lb in local.tiers.lbs : {
      for rule_key, rule in lb.lb_rules : "${lb_key}-${rule_key}" => {
        lb_id                        = azurerm_lb.lb[lb_key].id
        rule_key                     = rule_key
        frontend_port                = tonumber(rule[0])
        protocol                     = rule[1]
        backend_port                 = tonumber(rule[2])
        frontend_ip_configuration_name = lb.fip_name
        probe_id                     = azurerm_lb_probe.probe["${lb_key}-ssh_probe"].id
        backend_address_pool_id      = azurerm_lb_backend_address_pool.bepool[lb_key].id
        enable_floating_ip           = rule[4]
      }
    }
  ]...)
}

# 创建负载均衡器规则
resource "azurerm_lb_rule" "rule" {
  for_each                       = local.lb_rules_flat
  loadbalancer_id                = each.value.lb_id
  name                           = each.value.rule_key
  protocol                       = each.value.protocol
  frontend_port                  = each.value.frontend_port
  backend_port                   = each.value.backend_port
  frontend_ip_configuration_name = each.value.frontend_ip_configuration_name
  probe_id                       = each.value.probe_id
  backend_address_pool_ids       = [each.value.backend_address_pool_id]
  enable_floating_ip             = each.value.enable_floating_ip
}

关键修正点说明

  1. 负载均衡器前端配置:移除错误的dynamic循环,单个前端直接用静态块配置;多前端场景需调整为遍历当前LB的前端列表。
  2. 后端地址池关联:通过for_each = local.tiers.lbs绑定每个LB,用azurerm_lb.lb[each.key].id返回单个字符串ID,解决类型不匹配问题。
  3. 探测与规则扁平化:通过嵌套循环将LB和其下的探测/规则合并为扁平化映射,确保每个资源能精准关联到所属LB,避免循环范围错误。
  4. 属性类型修正:用tonumber()将locals中的端口字符串转换为数字类型,匹配Terraform资源的属性要求,同时修正语法错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 15:45:56