【问题标题】:Azure ARM Templates (DependsOn)Azure ARM 模板 (DependsOn)
【发布时间】:2017-03-09 01:47:05
【问题描述】:

希望获得有关dependsOn 的一些指导和解释。

我在模板中看到有两种方法可以在模板中提供依赖项。

一种方法是提供resourceId,另一种方法是使用concat 提供一个字符串值。我试图了解两者之间的区别。

例子

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

在一些例子中,这被resourceId引用:

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

我希望了解其中的区别,以及在哪些情况下我们应该使用concat 来引用依赖项以及我们可以在哪些情况下使用resourceID

【问题讨论】:

    标签: azure arm-template azure-template


    【解决方案1】:

    你是否使用resourceId(在dependsOn中)之间的真正区别是:你依赖的资源是否在同一个模板中?如果是这样,您只需拥有名称即可。例如,这是一个负载均衡器,它依赖于在同一模板中创建的公共 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' 语法显式添加依赖项...”。尽管虚拟机是在同一个模板中创建的,但为了解决这个问题,我试图完全限定资源,而我必须实际降低限定条件。我需要做的就是将“[resourceId('Microsoft.Compute/virtualMachines/', variables('vmName'))]”替换为“[variables('vmName']”。
    • 这不是真的,或者不完全是真的。如果您在同一部署中有 2 个具有相同名称的资源,这将不起作用
    • 真的是这样吗?当尝试使用 resourceId 从模板外部引用任何资源时,我得到 The resource 'XXXXX' is not defined in the template
    • 没有亲自尝试过,我不确定,而且我已经有几年没有使用过 arm 模板了。并且没有看到您的模板和 rg 等,可能有多种原因。它可能是一个错误的名称,也可能是它位于不同的资源组中,因此您需要更多的限定符等……但我在撰写本文时向您保证,这绝对是正确的。
    【解决方案2】:

    至少可以说,此线程中的另一个答案具有误导性。

    无论您采取哪条路线来实际将值提供给模板的 dependsOn(或任何其他属性)。见鬼,你可以在那里放一个字符串

    "dependsOn" [
        "/subscription/GUID/resourceGroups/rgName/provider/providerName/resource/resourceName"
    ]
    

    显然,这是一个坏主意,但它说明了这一点。您只需要返回一个有效的资源标识符,您可以以任何方式构造它(或者您可以在使用脚本进行配置时将其作为变量传递)。

    另外,当你使用嵌套资源时,有时resourceId 不能工作,所以你需要连接3个变量,在这种情况下concat可以提供帮助。

    没有什么能阻止你将一个嵌套在另一个里面:

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

    TLDR 你可以使用任何你喜欢的方式返回一个有效的资源标识符。

    ps:可以正常工作的“损坏”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 的答案?这将清楚地区分两种功能的用例。
    • 这个答案是错误的。有两种不同类型的依赖;一种使用资源 id(无论如何定义),另一种使用资源将被部署的名称在同一个 arm 模板中。在资源 id 的情况下,只检查资源是否存在;在资源名称的情况下,它在继续依赖资源之前完成资​​源的创建/更新。在使用新属性更新现有资源时,这会产生真正的不同。
    • 你不能依赖已经存在的资源,这没有任何意义,你将如何使用它来生成依赖关系图? dependsOn 与更新资源无关。答案没有任何问题,使用 resourceId 与资源名称的唯一真正原因 - 您可以拥有 2 种具有相同名称的不同资源类型,那么名称引用将不起作用
    【解决方案3】:

    区别:

    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

    【讨论】:

    • 感谢发帖。但我试图理解为什么在某些情况下我们在依赖项(Dependson)下使用 Concat 以及为什么我们在某些情况下使用 ResourceID ?这是我的困惑
    • 我已经更新了答案。如果我们要部署一个资源,那么我们需要提供resourceId,虽然我们可以连接多个字符串,但是我们可以通过resourceId函数很容易得到它
    • 谢谢。那么这是否意味着如果我需要引用订阅之外的对象,我必须使用 Resource ID 并且如果它是我订阅中的资源,我可以使用 ResourceID 或 Concat ?据我所知,Concat 没有订阅 ID/资源组信息等,这意味着我认为它也必须在同一个资源组中?
    • concat 不用于引用资源,只是组合多个字符串值。如果我们要部署资源,我们需要选择要部署的订阅。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-11
    • 1970-01-01
    • 2017-05-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多