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

如何从Terraform VNet/子网模块嵌套映射提取子网名称与ID

解决Terraform模块中提取子网名称与subnet_id的问题

先明确模块输出结构

假设你的modules.network模块输出的子网数据结构类似以下两种常见形式:

形式1:直接输出子网map

output "subnets" {
  type = map(object({
    id   = string
    name = string
    # 其他属性如地址前缀等
  }))
  value = aws_subnet.this
}

形式2:嵌套在VNet输出中

output "vnet_details" {
  type = object({
    vnet_id = string
    subnets = map(object({
      id   = string
      name = string
    }))
  })
  value = {
    vnet_id = aws_vpc.this.id
    subnets = aws_subnet.this
  }
}

提取子网名称与subnet_id的实操方法

1. 直接遍历子网map

如果模块输出是map类型的子网集合(键为子网名称或自定义标识),直接用for_each遍历即可:

# 为每个子网创建路由表
resource "azurerm_route_table" "subnet_rt" {
  for_each = module.network.subnets
  name                = "${each.value.name}-rt"
  location            = module.network.vnet_location
  resource_group_name = module.network.resource_group_name

  # 按需添加路由规则
  route {
    name                   = "default-route"
    address_prefix         = "0.0.0.0/0"
    next_hop_type          = "Internet"
  }
}

# 关联路由表到对应子网
resource "azurerm_subnet_route_table_association" "rt_link" {
  for_each = module.network.subnets
  subnet_id      = each.value.id
  route_table_id = azurerm_route_table.subnet_rt[each.key].id
}

这里each.value.name是子网名称,each.value.id就是你需要的subnet_id;如果map的键本身就是子网名称,也可以用each.key替代each.value.name。

2. 处理嵌套输出的情况

如果子网数据嵌套在VNet输出里,先通过本地值提取子网集合再遍历:

locals {
  subnets_collection = module.network.vnet_details.subnets
}

# 为每个子网创建NSG
resource "azurerm_network_security_group" "subnet_nsg" {
  for_each = local.subnets_collection
  name                = "${each.value.name}-nsg"
  location            = module.network.location
  resource_group_name = module.network.resource_group_name

  # 按需添加NSG规则
  security_rule {
    name                       = "allow-ssh"
    priority                   = 100
    direction                  = "Inbound"
    access                     = "Allow"
    protocol                   = "Tcp"
    source_port_range          = "*"
    destination_port_range     = "22"
    source_address_prefix      = "*"
    destination_address_prefix = "*"
  }
}

# 关联NSG到对应子网
resource "azurerm_subnet_network_security_group_association" "nsg_link" {
  for_each = local.subnets_collection
  subnet_id                 = each.value.id
  network_security_group_id = azurerm_network_security_group.subnet_nsg[each.key].id
}

常见报错排查

  • 报错:each.value无法使用:检查模块输出是否为map(object)类型,如果是list(object),先转成map:
    locals {
      subnets_map = { for subnet in module.network.subnets : subnet.name => subnet }
    }
    
    之后用local.subnets_map进行遍历。
  • 报错:模块无subnets输出:确认modules.network的输出定义中,确实有包含子网详情的输出项,名称是否和你引用的一致(比如有些模块可能叫subnet_details而非subnets)。
  • 报错:找不到id属性:检查模块输出的object结构,确保子网资源的id字段已被正确输出。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 00:48:18