ARM模板copy循环为NIC分配静态IP 多VM嵌套部署报错
问题原因
报错由多个配置错误共同导致,单实例场景下ARM模板校验逻辑宽松没有触发报错,多实例copy循环场景下会直接校验失败:
- 嵌套部署配置了
expressionEvaluationOptions.scope = inner,该配置下嵌套模板的表达式仅能识别嵌套模板内部定义的资源,无法感知外层模板创建的nic-<vmname>-0x网卡,直接在内嵌模板中调用reference()查询外层网卡时,ARM会在嵌套模板的资源列表中查找对应资源,自然找不到目标。 - 嵌套模板中定义的待更新网卡名称错误:外层创建的网卡命名规则为
nic-<vmname>-0<序号>,但嵌套模板里写的网卡名是assignstaticip<序号>,该名称对应的资源不存在,且逻辑上属于新建网卡而非更新原有网卡的IP配置。 - 跨作用域引用资源时未传入完整资源ID,仅拼接资源名称查询,不符合ARM嵌套部署inner作用域的引用规则。
- 外层传参时参数名大小写不匹配:外层传入的参数名为
SubnetRef(首字母大写),嵌套模板定义的参数名为subnetRef(首字母小写),该问题会在修复前述问题后触发参数缺失报错。
修复步骤
- 修正嵌套模板内的网卡名称,和外层已创建的网卡名称完全保持一致,确保增量部署时是更新原有网卡配置,而非新建资源。
- 统一外层传入参数和嵌套模板定义参数的大小写,同时把所有待更新网卡的完整resourceId作为数组参数传入嵌套模板,避免inner作用域下无法解析资源名称的问题。
- 更新网卡配置时补全原有网卡的所有配置项(比如加速网络开关),避免增量更新时覆盖原有配置导致异常。
reference()函数调用时显式指定网卡资源的API版本,使用传入的资源ID查询动态分配的IP地址。
修复后的嵌套部署核心代码如下:
{ "type": "Microsoft.Resources/deployments", "name": "StaticIP", "apiVersion": "2020-06-01", "dependsOn": [ "nicLoop", "virtualMachineLoop" ], "properties": { "mode": "Incremental", "expressionEvaluationOptions": { "scope": "inner" }, "parameters": { "subnetRef": { "value": "[variables('subnetRef')]" }, "virtualMachineCount": { "value": "[parameters('virtualMachineCount')]" }, "vm-name": { "value": "[parameters('vm-name')]" }, "nicIds": { "value": "[createArray(copyLoop('nicLoop', parameters('virtualMachineCount'), resourceId('Microsoft.Network/networkInterfaces', concat('nic-',parameters('vm-name'),'-0', copyIndex('nicLoop',1)))))]" } }, "template": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "1.0.0.0", "parameters": { "subnetRef": { "type": "string" }, "virtualMachineCount": { "type": "int" }, "vm-name": { "type": "string" }, "nicIds": { "type": "array" } }, "resources": [ { "type": "Microsoft.Network/networkInterfaces", "name": "[concat('nic-',parameters('vm-name'),'-0', copyIndex(1))]", "apiVersion": "2020-05-01", "location": "[resourceGroup().location]", "copy": { "name": "nicStaticIpLoop", "count": "[parameters('virtualMachineCount')]" }, "properties": { "enableAcceleratedNetworking": true, "ipConfigurations": [ { "name": "ipconfig1", "properties": { "privateIPAllocationMethod": "Static", "privateIPAddress": "[reference(parameters('nicIds')[copyIndex()], '2018-11-01').ipConfigurations[0].properties.privateIPAddress]", "subnet": { "id": "[parameters('subnetRef')]" } } } ] } } ] } } }
简化实现建议
如果不需要保留嵌套部署结构,完全可以去掉嵌套部署逻辑,直接在同一层模板里定义两次网卡资源:第一次创建动态IP的网卡,依赖虚拟网络;第二次创建同名静态IP的网卡,依赖虚拟机创建完成的循环,直接引用第一次创建的网卡的动态IP作为静态IP配置值,比嵌套部署逻辑更简单,也不会出现作用域引用错误。
内容的提问来源于stack exchange,提问作者Anonymouus
相关产品推荐
相关产品推荐

