如何通过Azapi Network Group Static Members为静态组添加多个成员?
问题描述
我正在学习Terraform,要在Azure中搭建Hub and Spoke网络,同时配置Network Manager,要求使用包含Static Members的Network Group。之前用for_each批量创建Spoke VNet并加入网络组,但现在手动创建了两个独立的VNet(vm-spoke-vnet和aks-spoke-vnet)及子网,不知道怎么把这两个VNet加入同一个静态组。看了微软的基础模板后还是没头绪,以为独立资源没法用for_each(可能这个判断错了),想过加多个Resource ID但不确定是否可行,求最佳实现方法。
基础模板
resource "azapi_resource" "symbolicname" { type = "Microsoft.Network/networkManagers/networkGroups/staticMembers@2022-07-01" name = "string" parent_id = "string" body = jsonencode({ properties = { resourceId = "string" } }) }
旧代码(使用for_each批量创建VNet并加入组)
resource "azurerm_virtual_network" "spokes" { for_each = local.spoke_subnets name = each.key resource_group_name = azurerm_resource_group.test.name location = azurerm_resource_group.test.location address_space = each.value.address_space } resource "azapi_resource" "network_manager" { type = "Microsoft.Network/networkManagers@2022-07-01" name = "networkmanager" parent_id = azurerm_resource_group.test.id location = azurerm_resource_group.test.location body = jsonencode({ properties = { networkManagerScopeAccesses = [ "Connectivity", "SecurityAdmin" ] networkManagerScopes = { subscriptions = [ data.azurerm_subscription.current.id ] } } }) } resource "azapi_resource" "spoke_group" { type = "Microsoft.Network/networkManagers/networkGroups@2022-07-01" name = "spokes" parent_id = azapi_resource.network_manager.id body = jsonencode({ properties = { memberType = "VirtualNetwork" } }) } resource "azapi_resource" "spoke_group_members" { type = "Microsoft.Network/networkManagers/networkGroups/staticMembers@2022-07-01" for_each = azurerm_virtual_network.spokes name = each.value.name parent_id = azapi_resource.spoke_group.id body = jsonencode({ properties = { resourceId = each.value.id } }) }
新代码(手动创建独立VNet,需完善组成员配置)
resource "azurerm_virtual_network" "vm-spoke-vnet" { name = "ty-vm-spoke-vnet" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name address_space = ["10.1.0.0/16"] tags = { environment = "hub-spoke" } } #VNet for AKS Spoke - Not sure if correct resource "azurerm_virtual_network" "aks-spoke-vnet" { name = "ty-aks-spoke-vnet" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name address_space = ["10.2.0.0/16"] tags = { environment = "hub-spoke" } } #Subnet for VMs resource "azurerm_subnet" "vm-spoke-subnet" { name = "ty-vm-subnet" resource_group_name = azurerm_resource_group.test.name virtual_network_name = azurerm_virtual_network.vm-spoke-vnet.name address_prefixes = ["10.1.0.64/27"] } #Subnet for AKS - Not sure if correct resource "azurerm_subnet" "aks-spoke-subnet" { name = "ty-aks-subnet" resource_group_name = azurerm_resource_group.test.name virtual_network_name = azurerm_virtual_network.aks-spoke-vnet.name address_prefixes = ["10.2.0.64/27"] } resource "azapi_resource" "network_manager" { type = "Microsoft.Network/networkManagers@2022-07-01" name = "networkmanager" parent_id = azurerm_resource_group.test.id location = azurerm_resource_group.test.location body = jsonencode({ properties = { networkManagerScopeAccesses = [ "Connectivity", "SecurityAdmin" ] networkManagerScopes = { subscriptions = [ data.azurerm_subscription.current.id ] } } }) } #Group for all of the Spoke Networks resource "azapi_resource" "spoke_group" { type = "Microsoft.Network/networkManagers/networkGroups@2022-07-01" name = "spokes" parent_id = azapi_resource.network_manager.id body = jsonencode({ properties = { memberType = "VirtualNetwork" } }) } resource "azapi_resource" "spoke_group_members" { type = "Microsoft.Network/networkManagers/networkGroups/staticMembers@2022-07-01" for_each = azurerm_virtual_network.spokes name = each.value.name parent_id = azapi_resource.spoke_group.id body = jsonencode({ properties = { resourceId = each.value.id } }) }
解决方案
方法1:用for_each遍历手动创建的VNet集合
你完全可以继续用for_each,只要把两个独立的VNet放到一个集合里即可。在代码中添加一个本地值,把两个VNet的ID和名称映射进去,然后用for_each遍历这个集合:
# 定义本地集合,包含所有需要加入组的Spoke VNet locals { spoke_vnets = { vm_spoke = { name = azurerm_virtual_network.vm-spoke-vnet.name id = azurerm_virtual_network.vm-spoke-vnet.id } aks_spoke = { name = azurerm_virtual_network.aks-spoke-vnet.name id = azurerm_virtual_network.aks-spoke-vnet.id } } } # 替换原来的spoke_group_members资源 resource "azapi_resource" "spoke_group_members" { type = "Microsoft.Network/networkManagers/networkGroups/staticMembers@2022-07-01" for_each = local.spoke_vnets name = each.value.name parent_id = azapi_resource.spoke_group.id body = jsonencode({ properties = { resourceId = each.value.id } }) }
这种方法保留了for_each的优势,后续新增VNet时只需要在local.spoke_vnets里添加条目即可,不需要重复编写资源块。
方法2:手动创建两个静态成员资源
如果不想用for_each,也可以直接创建两个独立的azapi_resource资源,分别对应两个VNet:
# 加入VM Spoke VNet resource "azapi_resource" "vm_spoke_static_member" { type = "Microsoft.Network/networkManagers/networkGroups/staticMembers@2022-07-01" name = azurerm_virtual_network.vm-spoke-vnet.name parent_id = azapi_resource.spoke_group.id body = jsonencode({ properties = { resourceId = azurerm_virtual_network.vm-spoke-vnet.id } }) } # 加入AKS Spoke VNet resource "azapi_resource" "aks_spoke_static_member" { type = "Microsoft.Network/networkManagers/networkGroups/staticMembers@2022-07-01" name = azurerm_virtual_network.aks-spoke-vnet.name parent_id = azapi_resource.spoke_group.id body = jsonencode({ properties = { resourceId = azurerm_virtual_network.aks-spoke-vnet.id } }) }
这种方法更直观,但VNet数量多的时候会产生重复代码,维护成本较高。
推荐方案
优先选择方法1,它兼顾了代码简洁性和可维护性,符合Terraform的基础设施即代码最佳实践。
内容的提问来源于stack exchange,提问作者Code_Rookie
相关产品推荐
相关产品推荐

