如何用Bicep模板为现有VNet子网分配NSG并解决循环依赖
解决Bicep模板中NSG分配给子网的循环依赖错误
尝试用Bicep模板将现有NSG分配给现有VNet子网时,部署验证出现循环依赖错误,原代码及错误信息如下:
原代码
@description('Name of nsg') param nsgName string @description('Name of vnet') param vnetName string @description('Name of subnet') param subnetName string resource nsg 'Microsoft.Network/networkSecurityGroups@2022-01-01' existing = { name: nsgName } resource subnet 'Microsoft.Network/virtualNetworks/subnets@2022-01-01' existing = { name: '${vnetName}/${subnetName}' } resource nsgAttachment 'Microsoft.Network/virtualNetworks/subnets@2022-01-01' = { name: '${vnetName}/${subnetName}' properties: { addressPrefix: subnet.properties.addressPrefix networkSecurityGroup: { id: nsg.id } } }
错误信息
{"code":"InvalidTemplate","message":"Deployment template validation failed: 'Circular dependency detected on resource: '/subscriptions/xxxxxxxxx-02eaf5d20f25/resourceGroups/bicepRG/providers/Microsoft.Network/virtualNetworks/myVnetName/subnets/api'. Please see https://aka.ms/arm-template/#resources for usage details.'."}
错误原因
你同时声明了两个指向同一子网的资源:一个existing类型的子网引用,另一个是同名的新子网资源。新子网资源依赖existing子网的addressPrefix,而existing子网又会被部署引擎判定为依赖新子网资源(因为名称完全相同),最终形成循环依赖。
解决方法及正确代码
方法一:使用update语法直接更新现有子网(推荐)
Bicep支持在existing资源上添加update块,仅修改需要更新的属性(无需重复指定子网地址前缀,原有属性会保留):
@description('Name of nsg') param nsgName string @description('Name of vnet') param vnetName string @description('Name of subnet') param subnetName string resource nsg 'Microsoft.Network/networkSecurityGroups@2022-01-01' existing = { name: nsgName } resource subnet 'Microsoft.Network/virtualNetworks/subnets@2022-01-01' existing = { name: '${vnetName}/${subnetName}' update: { properties: { networkSecurityGroup: { id: nsg.id } } } }
方法二:直接定义子网资源并指定地址前缀
如果无法使用update语法,可以直接定义子网资源,通过传入地址前缀参数或从VNet资源中获取前缀,避免引用existing子网资源:
传入地址前缀参数
@description('Name of nsg') param nsgName string @description('Name of vnet') param vnetName string @description('Name of subnet') param subnetName string @description('Subnet address prefix') param subnetAddressPrefix string resource nsg 'Microsoft.Network/networkSecurityGroups@2022-01-01' existing = { name: nsgName } resource subnet 'Microsoft.Network/virtualNetworks/subnets@2022-01-01' = { name: '${vnetName}/${subnetName}' properties: { addressPrefix: subnetAddressPrefix networkSecurityGroup: { id: nsg.id } } }
从现有VNet中获取子网地址前缀
@description('Name of nsg') param nsgName string @description('Name of vnet') param vnetName string @description('Name of subnet') param subnetName string resource nsg 'Microsoft.Network/networkSecurityGroups@2022-01-01' existing = { name: nsgName } resource vnet 'Microsoft.Network/virtualNetworks@2022-01-01' existing = { name: vnetName } // 从VNet子网列表中过滤目标子网的地址前缀 var targetSubnet = first(filter(vnet.properties.subnets, (s) => s.name == subnetName)) var subnetAddressPrefix = targetSubnet.addressPrefix resource subnet 'Microsoft.Network/virtualNetworks/subnets@2022-01-01' = { name: '${vnetName}/${subnetName}' properties: { addressPrefix: subnetAddressPrefix networkSecurityGroup: { id: nsg.id } } }
内容的提问来源于stack exchange,提问作者user346206
相关产品推荐
相关产品推荐

