使用for_each创建Azure子网后,如何正确引用子网ID?
我在AzureRM环境中使用for_each创建子网,其中var.client_name的值为["client1","client2"],创建子网的代码如下:
resource "azurerm_subnet" "subnets" { for_each = var.subnet_map_large resource_group_name = var.resource_group_name virtual_network_name = var.virtual_network_name name = "${var.client_name}-${each.key}" address_prefixes = [format("%s.%s", "${var.address_prefix}", each.value["subnet_postfix"])] }
子网创建过程正常,但当我尝试通过以下代码获取指定子网的ID时,出现报错:
gateway_ip_configuration { name = "gateway-ip-config" subnet_id = azurerm_subnet.subnets["${var.client_name}-AppGatewaySubnet"].id }
报错信息如下:
subnet_id = azurerm_subnet.subnets["${var.client_name}-AppGatewaySubnet"].id │ ├──────────────── │ │ azurerm_subnet.subnets is object with 8 attributes
我对此感到困惑:用terraform state show查看子网资源时,它包含的属性远多于8个;同时作为Terraform新手,我不知道该如何正确引用目标子网的ID。以下是terraform state show的输出结果:
module.client_network["client3"].azurerm_subnet.subnets["API"]: resource "azurerm_subnet" "subnets" { address_prefixes = [ "10.3.64.0/18", ] enforce_private_link_endpoint_network_policies = false enforce_private_link_service_network_policies = false id = "/subscriptions/747c7dd9-3d75-4dab-abce-c12b580afd12/resourceGroups/RG-AG-4/providers/Microsoft.Network/virtualNetworks/app-network/subnets/client3-API" name = "client3-API" private_endpoint_network_policies_enabled = true private_link_service_network_policies_enabled = true resource_group_name = "RG-AG-4" service_endpoint_policy_ids = [] service_endpoints = [] virtual_network_name = "app-network" }
核心问题
你搞错了for_each资源集合的索引方式:azurerm_subnet.subnets的索引键是var.subnet_map_large中的键,而不是子网的完整名称(即${var.client_name}-${each.key})。报错里提到的"object with 8 attributes",指的是这个资源集合包含8个实例,对应var.subnet_map_large里的8个键,和单个子网资源的属性数量无关。
正确引用方式
要获取AppGatewaySubnet对应的子网ID,直接用var.subnet_map_large中的键"AppGatewaySubnet"索引资源集合即可,不需要加上var.client_name前缀:
gateway_ip_configuration { name = "gateway-ip-config" subnet_id = azurerm_subnet.subnets["AppGatewaySubnet"].id }
补充说明
如果你的子网是在通过for_each实例化的模块中创建的(比如module.client_network["client3"]),那么引用时需要带上对应的客户端标识,示例如下:
subnet_id = module.client_network[var.client_name].azurerm_subnet.subnets["AppGatewaySubnet"].id
注意:如果var.client_name是列表类型,需要根据实际场景选择具体的元素(比如var.client_name[0])。
内容的提问来源于stack exchange,提问作者Wolfgang

