Azure RM链接模板依赖配置异常:Web应用与服务总线部署顺序错误
你遇到的核心问题其实是ARM模板的函数解析时机导致的:listKeys这类资源查询函数会在模板部署的初始解析阶段就被执行,而不是等到dependsOn指定的依赖资源完成后再执行。所以哪怕你给Web应用部署设置了对Service Bus部署的依赖,ARM还是会提前尝试获取Service Bus的密钥,此时Service Bus还未创建,自然就抛出ParentResourceNotFound错误。
之前你尝试的几种依赖配置无效的原因:
- 直接写
myServiceBus或对应的resourceId:Service Bus是在链接模板里定义的,根模板没有直接声明这个资源,ARM在根模板上下文里找不到它,依赖关系不生效。 - 写
myServiceBusDeploy:虽然能确保Service Bus的部署操作标记为完成,但listKeys的解析早于实际资源创建,仍然会触发错误。
下面给你两种可靠的解决方案:
方案一:把连接字符串获取逻辑移到Web应用的链接模板中
这种方式让Web应用模板自己处理依赖和密钥查询,根模板只负责传递必要参数:
修改Web应用的链接模板(
webapp.azuredeploy.json):
添加Service Bus命名空间参数,同时给Web应用资源添加对Service Bus的依赖,在应用配置里直接查询密钥:{ "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", "contentVersion": "1.0.0.0", "parameters": { "name": { "type": "string" }, "serviceBusNamespaceName": { "type": "string" } }, "resources": [ { "name": "[parameters('name')]", "type": "Microsoft.Web/sites", "apiVersion": "2022-03-01", "location": "[resourceGroup().location]", "dependsOn": [ "[resourceId('Microsoft.ServiceBus/namespaces', parameters('serviceBusNamespaceName'))]" ], "properties": { /* 你的Web应用基础配置 */ }, "resources": [ { "name": "appsettings", "type": "config", "apiVersion": "2022-03-01", "dependsOn": ["[resourceId('Microsoft.Web/sites', parameters('name'))]"], "properties": { "serviceBusConnectionString": "[listKeys(resourceId('Microsoft.ServiceBus/namespaces/authorizationRules', parameters('serviceBusNamespaceName'), 'RootManageSharedAccessKey'), '2017-04-01').primaryConnectionString]" } } ] } ] }修改根模板中的Web应用部署配置:
移除原有的connectionStrings参数,改为传递Service Bus命名空间名称,并依赖Service Bus的部署资源:{ "name": "myWebAppDeploy", "apiVersion": "2017-05-10", "type": "Microsoft.Resources/deployments", "dependsOn": ["myServiceBusDeploy"], "properties": { "mode": "Incremental", "templateLink": { "uri": "link/to/webapp.azuredeploy.json", "contentVersion": "1.0.0.0" }, "parameters": { "name": { "value": "myWebApp" }, "serviceBusNamespaceName": { "value": "myServiceBus" } } } }
方案二:通过Service Bus链接模板的输出传递连接字符串
这种方式让Service Bus部署完成后主动输出连接字符串,Web应用部署直接引用这个输出值:
修改Service Bus的链接模板(
servicebus.azuredeploy.json):
添加输出节点,在Service Bus创建完成后输出连接字符串:{ "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", "contentVersion": "1.0.0.0", "parameters": { "name": { "type": "string" } }, "resources": [ { "name": "[parameters('name')]", "type": "Microsoft.ServiceBus/namespaces", "apiVersion": "2017-04-01", "location": "[resourceGroup().location]", "sku": { "name": "Standard" }, "properties": {} } ], "outputs": { "serviceBusConnectionString": { "type": "string", "value": "[listKeys(resourceId('Microsoft.ServiceBus/namespaces/authorizationRules', parameters('name'), 'RootManageSharedAccessKey'), '2017-04-01').primaryConnectionString]" } } }修改根模板中的Web应用部署配置:
依赖Service Bus部署资源,并引用其输出的连接字符串:{ "name": "myWebAppDeploy", "apiVersion": "2017-05-10", "type": "Microsoft.Resources/deployments", "dependsOn": ["myServiceBusDeploy"], "properties": { "mode": "Incremental", "templateLink": { "uri": "link/to/webapp.azuredeploy.json", "contentVersion": "1.0.0.0" }, "parameters": { "name": { "value": "myWebApp" }, "connectionStrings": { "value": { "serviceBusConnectionString": "[reference('myServiceBusDeploy').outputs.serviceBusConnectionString.value]" } } } } }
这两种方案都能确保listKeys函数在Service Bus资源完全创建后才执行,彻底解决提前解析导致的错误。
内容的提问来源于stack exchange,提问作者hosjay

