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.
错误原因分析
- 类型不匹配:
loadbalancer_id要求单个字符串(目标负载均衡器ID),但代码返回了列表,触发类型错误。 - 循环逻辑混乱:
azurerm_lb的dynamic frontend_ip_configuration错误遍历所有LB,未关联当前LB的配置- 探测、后端池、规则资源未正确绑定所属LB,循环范围和关联关系错误
- 语法与引用错误:存在
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 }
关键修正点说明
- 负载均衡器前端配置:移除错误的
dynamic循环,单个前端直接用静态块配置;多前端场景需调整为遍历当前LB的前端列表。 - 后端地址池关联:通过
for_each = local.tiers.lbs绑定每个LB,用azurerm_lb.lb[each.key].id返回单个字符串ID,解决类型不匹配问题。 - 探测与规则扁平化:通过嵌套循环将LB和其下的探测/规则合并为扁平化映射,确保每个资源能精准关联到所属LB,避免循环范围错误。
- 属性类型修正:用
tonumber()将locals中的端口字符串转换为数字类型,匹配Terraform资源的属性要求,同时修正语法错误。
内容的提问来源于stack exchange,提问作者Uday Kiran
相关产品推荐
相关产品推荐

