Terraform遍历对象Map生成子网NSG报错求助
解决Terraform中为每个子网创建NSG的问题
你的错误根源在于var.networks是一个Map类型,直接访问.subnet_names无效——Map的顶层键是network1、network2,需要先提取Map的所有值(每个值是包含subnet_names的对象),再扁平化所有子网列表。
正确实现方式
要得到合并后的一维子网列表,你可以用嵌套for表达式直接扁平化,或者结合flatten函数。两种方法都能生成你需要的nsgs_to_create列表,进而为每个子网创建独立的NSG。
方法1:嵌套for表达式(推荐,更直观)
直接遍历每个网络对象,再遍历其下的子网,收集所有子网名称:
resource "azurerm_network_security_group" "example" { # 生成包含所有子网名称的Set,避免重复 for_each = toset([ for network in var.networks : for subnet in network.subnet_names : subnet ]) name = "${each.key}-nsg" location = azurerm_resource_group.example.location resource_group_name = azurerm_resource_group.example.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 = "*" } }
方法2:结合flatten函数
先提取所有网络的subnet_names列表,再用flatten将二维列表转为一维:
resource "azurerm_network_security_group" "example" { for_each = toset(flatten([for network in var.networks : network.subnet_names])) name = "${each.key}-nsg" location = azurerm_resource_group.example.location resource_group_name = azurerm_resource_group.example.name # NSG配置... }
进阶:避免子网名称重复冲突
如果不同网络下存在同名子网,上述方法会因为Set去重导致只创建一个NSG。此时可以用复合键(网络名+子网名)作为for_each的键,确保唯一性:
resource "azurerm_network_security_group" "example" { for_each = { for network_name, network in var.networks : "${network_name}-${subnet}" => subnet for subnet in network.subnet_names } name = "${each.value}-nsg" location = azurerm_resource_group.example.location resource_group_name = azurerm_resource_group.example.name # NSG配置... }
这样生成的NSG会以network1-subnet-1、network2-subnet-1这种唯一标识作为键,彻底避免冲突。
内容的提问来源于stack exchange,提问作者Andrew Hodgson
相关产品推荐
相关产品推荐

