Azure ARM模板(DependsOn)

17

寻求有关dependsOn的指导和解释。

我在模板中看到了两种提供依赖项的方法。一种方法是提供resourceId,另一种方法是使用concat提供字符串值。我试图理解两者之间的区别。

示例:

[concat('Microsoft.Network/networkInterfaces/', variables('networkInterfaceName'))]

有些示例还会使用resourceId来引用此内容:

[resourceId('Microsoft.Compute/virtualMachines', parameters('virtualMachineName'))]

我希望了解何时应使用concat来引用依赖关系以及何时可以使用resourceID,并了解它们之间的区别。

我希望理解何时应使用concat来引用依赖关系以及何时可以使用resourceID
3个回答

15

在dependsOn中使用resourceId和不使用的真正区别是:你所依赖的资源是否在同一个模板中?如果是的话,你可以只使用名称。例如,这是一个负载均衡器,它依赖于在同一个模板中创建的公共IP地址和vNet:

  "apiVersion": "[variables('lbApiVersion')]",
  "type": "Microsoft.Network/loadBalancers",
  "name": "[variables('lbName1')]",
  "location": "[variables('computeLocation')]",
  "dependsOn": [
    "[variables('lbIPName1')]",
    "[variables('virtualNetworkName')]"
  ],
  "properties": {
    "frontendIPConfigurations": [
      {
        "name": "LoadBalancerIPConfig",
        "properties": {
          "publicIPAddress": {
            "id": "[resourceId('Microsoft.Network/publicIPAddresses', variables('lbIPName1'))]"
          }

如果您引用模板外的资源,则需要使用resourceId。在dependsOn中不需要这样做,因为您只能依赖于同一模板中的资源。在我的示例中需要它的地方是publicIPAddress id。此属性需要完整的资源ID,这就是resourceId函数提供的内容。因此问题变成了,该属性是否需要完整的资源ID?


谢谢。使用嵌套模板时,我遇到了错误“abc...不依赖于父资源abc... ...请使用'dependsOn'语法显式添加依赖关系...”。虽然虚拟机是在同一个模板中创建的,但为了解决问题,我尝试了完全限定资源的方式,实际上我需要减少限定。我所需要做的就是用“[variables('vmName']”替换“[resourceId('Microsoft.Compute/virtualMachines/', variables('vmName'))]”。 - woter324
1
这不是真的,或者说不完全正确。如果您在同一部署中有两个同名的资源,那么这将无法正常工作。 - 4c74356b41
这真的是这样吗?当尝试使用resourceId引用模板外部的任何资源时,我会收到The resource 'XXXXX' is not defined in the template的错误提示。 - Cocowalla
没有亲身尝试过,我不太确定。而且我已经有几年没有使用ARM模板了。没有看到你的模板和rg等等,可能有各种各样的原因。它可能是一个错误的名称,也可能是它在不同的资源组中,所以你需要更多的限定符等等......但我向你保证,在写这篇文章时,这肯定是正确的。 - Edward Rixon
resourceId 的文档解释得很清楚,可以参考这个链接:https://learn.microsoft.com/zh-cn/azure/azure-resource-manager/templates/template-functions-resource#resourceid - Edward Rixon

8
这个帖子里的另一个回答至少是误导性的。
实际上,你采取哪种方式来向模板的dependsOn属性(或任何其他属性)提供值都不重要。你甚至可以在那里放一个字符串。
"dependsOn" [
    "/subscription/GUID/resourceGroups/rgName/provider/providerName/resource/resourceName"
]

显然,这是个不好的想法,但它阐明了重点。你只需要返回一个有效的资源标识符,可以以任何方式构造它(或者在脚本配置时将其作为变量传递)。

有时候当使用嵌套资源时resourceId无法工作,所以你需要连接3个变量,在这种情况下,concat可以帮助你。

而且,没有什么能阻止你把一个资源嵌套到另一个资源中:

"[concat(resourceId('Microsoft.Compute/virtualMachines', parameters('virtualMachineName'), 'SOME TEXT'))]

TLDR,您可以使用任何方法返回有效的资源标识符。
附:一个“损坏”的 resourceId 的示例,通常会正常工作:
{
    "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "resources": [
        {
            "type": "Microsoft.Resources/deployments",
            "apiVersion": "2017-05-10",
            "name": "nestedTemplate",
            "resourceGroup": "xxx",
            "properties": {
                "mode": "Incremental",
                "template": {
                    "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
                    "contentVersion": "1.0.0.0",
                    "resources": [
                        {
                            "type": "Microsoft.Storage/storageAccounts",
                            "apiVersion": "2017-06-01",
                            "name": "egw4y35hthrh35h24tz1",
                            "location": "eastus",
                            "sku": {
                                "name": "Standard_LRS"
                            },
                            "tags": {
                                "test": "[resourceId('Microsoft.Storage/storageAccounts', 'test')]"
                            },
                            "kind": "Storage",
                            "properties": {}
                        }
                    ]
                }
            }
        }
    ]
}

这必须是订阅级别的部署。


明白了。是否可以在答案中添加一个示例或链接,说明不能使用resourceId()来获取资源的resourceId?这将清楚地区分两个函数的用例。 - stackoverflowusrone
这个答案是错误的。有两种不同类型的依赖关系;一种使用资源 ID(无论如何定义),另一种使用在同一个 ARM 模板中部署资源的名称。在资源 ID 的情况下,所有被检查的只是资源是否存在;而在资源名称的情况下,在继续处理依赖资源之前,它会完成创建/更新资源。这在使用新属性更新现有资源时会产生真正的差异。 - Vince Bowdren
你不能依赖于已经存在的资源,这毫无意义,你如何使用它来生成依赖关系图呢?dependsOn与更新资源无关。答案没有问题,使用resourceId而不是资源名称的唯一真正原因是 - 你可以有两种不同类型的资源具有相同的名称,那么名称引用将无法工作。 - 4c74356b41

1

区别:

concat: 将多个字符串值合并并返回合并后的字符串。

resourceId: 返回资源的唯一标识符。

示例 "[concat('Microsoft.Network/networkInterfaces/', variables('networkInterfaceName'))]"

结果: Microsoft.Network/networkInterfaces/{networkInterfaceName}

示例: [resourceId('Microsoft.Compute/virtualMachines', parameters('virtualMachineName'))]",

结果: /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/{Microsoft.Compute/virtualMachines}/{networkInterfaceName}/

ARM模板中更多函数,请参阅document


1
谢谢您的发布。但我正在尝试理解为什么在某些情况下我们在依赖项(Dependson)下使用Concat,而在某些情况下我们使用ResourceID?这是我的困惑。 - WS2012R2
我已经更新了答案。如果我们想要部署一个资源,那么我们需要提供resourceId,虽然我们可以拼接多个字符串,但是我们可以通过使用resourceId函数轻松获取它。 - Tom Sun - MSFT
谢谢。那么这是否意味着,如果我需要引用订阅外的对象,我必须使用资源 ID,而如果它是我的订阅中的资源,则可以使用 ResourceID 或 Concat?从我所看到的,Concat 没有订阅 ID / 资源组信息等,这意味着我认为它也必须在同一资源组中? - WS2012R2
Concat不用于引用资源,只是将多个字符串值组合在一起。如果我们想要部署资源,我们需要选择要部署到哪个订阅中。 - Tom Sun - MSFT

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接