在 ARM 模板中定义部署资源的顺序Define the order for deploying resources in ARM templates

部署资源时,可能需要确保某些资源在其他资源之前存在。When deploying resources, you may need to make sure some resources exist before other resources. 例如,在部署数据库之前,需要逻辑 SQL Server。For example, you need a logical SQL server before deploying a database. 可通过将一个资源标记为依赖于其他资源来建立此关系。You establish this relationship by marking one resource as dependent on the other resource. 使用 dependsOn 元素可以定义显式依赖关系。Use the dependsOn element to define an explicit dependency. 使用 reference 或 list 函数可以定义隐式依赖关系。Use the reference or list functions to define an implicit dependency.

Azure 资源管理器将评估资源之间的依赖关系,并根据其依赖顺序进行部署。Azure Resource Manager evaluates the dependencies between resources, and deploys them in their dependent order. 如果资源互不依赖,资源管理器将以并行方式部署资源。When resources aren't dependent on each other, Resource Manager deploys them in parallel. 只需为部署在同一模板中的资源定义依赖关系。You only need to define dependencies for resources that are deployed in the same template.

dependsOndependsOn

在 Azure 资源管理器模板(ARM 模板)中,dependsOn 元素可让你将一个资源定义为依赖于一个或多个资源。Within your Azure Resource Manager template (ARM template), the dependsOn element enables you to define one resource as a dependent on one or more resources. 其值是字符串的 JavaScript 对象表示法 (JSON) 数组,每个字符串都是一个资源名称或 ID。Its value is a JavaScript Object Notation (JSON) array of strings, each of which is a resource name or ID. 该数组可以包括有条件部署的资源。The array can include resources that are conditionally deployed. 条件资源未部署时,Azure 资源管理器会自动将其从所需依赖项中删除。When a conditional resource isn't deployed, Azure Resource Manager automatically removes it from the required dependencies.

以下示例显示了一个依赖于虚拟网络、网络安全组和公共 IP 地址的网络接口。The following example shows a network interface that depends on a virtual network, network security group, and public IP address. 有关完整的模板,请参阅适用于 Linux VM 的快速入门模板For the full template, see the quickstart template for a Linux VM.

{
    "type": "Microsoft.Network/networkInterfaces",
    "apiVersion": "2020-06-01",
    "name": "[variables('networkInterfaceName')]",
    "location": "[parameters('location')]",
    "dependsOn": [
      "[resourceId('Microsoft.Network/networkSecurityGroups/', parameters('networkSecurityGroupName'))]",
      "[resourceId('Microsoft.Network/virtualNetworks/', parameters('virtualNetworkName'))]",
      "[resourceId('Microsoft.Network/publicIpAddresses/', variables('publicIpAddressName'))]"
    ],
    ...
}

尽管你可能倾向于使用 dependsOn 来映射资源之间的关系,但请务必了解这么做的理由。While you may be inclined to use dependsOn to map relationships between your resources, it's important to understand why you're doing it. 例如,若要记录资源的互连方式,使用 dependsOn 并不是合适的方法。For example, to document how resources are interconnected, dependsOn isn't the right approach. 部署之后,你无法查询 dependsOn 元素中定义了哪些资源。You can't query which resources were defined in the dependsOn element after deployment. 设置不必要的依赖关系会减慢部署速度,因为资源管理器无法并行部署这些资源。Setting unnecessary dependencies slows deployment time because Resource Manager can't deploy those resources in parallel.

子资源Child resources

子资源和父资源之间不会自动创建隐式部署依赖关系。An implicit deployment dependency isn't automatically created between a child resource and the parent resource. 如果需要在父资源之后部署子资源,请设置 dependsOn 属性。If you need to deploy the child resource after the parent resource, set the dependsOn property.

以下示例显示了逻辑 SQL Server 和数据库。The following example shows a logical SQL server and database. 请注意,在数据库与服务器之间定义了显式依赖关系,尽管数据库是服务器的子级。Notice that an explicit dependency is defined between the database and the server, even though the database is a child of the server.

"resources": [
  {
    "type": "Microsoft.Sql/servers",
    "apiVersion": "2020-02-02-preview",
    "name": "[parameters('serverName')]",
    "location": "[parameters('location')]",
    "properties": {
      "administratorLogin": "[parameters('administratorLogin')]",
      "administratorLoginPassword": "[parameters('administratorLoginPassword')]"
    },
    "resources": [
      {
        "type": "databases",
        "apiVersion": "2020-08-01-preview",
        "name": "[parameters('sqlDBName')]",
        "location": "[parameters('location')]",
        "sku": {
          "name": "Standard",
          "tier": "Standard"
          },
        "dependsOn": [
          "[resourceId('Microsoft.Sql/servers', concat(parameters('serverName')))]"
        ]
      }
    ]
  }
]

有关完整的模板,请参阅适用于 Azure SQL 数据库的快速入门模板For the full template, see quickstart template for Azure SQL Database.

reference 和 list 函数reference and list functions

引用函数使表达式能够从其他 JSON 名值对或运行时资源中派生其值。The reference function enables an expression to derive its value from other JSON name and value pairs or runtime resources. list* 函数从列表操作返回资源的值。The list* functions return values for a resource from a list operation.

reference 和 list 表达式隐式声明一个资源依赖于另一个资源。Reference and list expressions implicitly declare that one resource depends on another. 只要可能,可使用隐式引用以避免添加不必要的依赖项。Whenever possible, use an implicit reference to avoid adding an unnecessary dependency.

若要强制实施隐式依赖关系,请按名称(而不是资源 ID)引用资源。To enforce an implicit dependency, refer to the resource by name, not resource ID. 如果将资源 ID 传入到 reference 或 list 函数中,则不会创建隐式引用。If you pass the resource ID into the reference or list functions, an implicit reference isn't created.

reference 函数的一般格式为:The general format of the reference function is:

reference('resourceName').propertyPath

listKeys 函数的一般格式为:The general format of the listKeys function is:

listKeys('resourceName', 'yyyy-mm-dd')

在以下示例中,CDN 终结点显式依赖于 CDN 配置文件,隐式依赖于 Web 应用。In the following example, a CDN endpoint explicitly depends on the CDN profile, and implicitly depends on a web app.

{
    "name": "[variables('endpointName')]",
    "apiVersion": "2016-04-02",
    "type": "endpoints",
    "location": "[resourceGroup().location]",
    "dependsOn": [
      "[variables('profileName')]"
    ],
    "properties": {
      "originHostHeader": "[reference(variables('webAppName')).hostNames[0]]",
      ...
    }

若要了解详细信息,请参阅引用函数To learn more, see reference function.

依赖于循环中的资源Depend on resources in a loop

若要部署依赖于复制循环中资源的资源,可以使用两个选项。To deploy resources that depend on resources in a copy loop, you have two options. 你可以设置对循环中的个别资源的依赖关系,也可以设置对整个循环的依赖关系。You can either set a dependency on individual resources in the loop or on the whole loop.

备注

在大多数情况下,应当设置对复制循环中的个别资源的依赖关系。For most scenarios, you should set the dependency on individual resources within the copy loop. 仅当循环中的所有资源都需要在创建下一个资源之前存在时,才依赖整个循环。Only depend on the whole loop when you need all of the resources in the loop to exist before creating the next resource. 设置对整个循环的依赖关系会导致依赖关系图显著扩展,特别是当那些循环的资源依赖于其他资源时。Setting the dependency on the whole loop causes the dependencies graph to expand significantly, especially if those looped resources depend on other resources. 扩展的依赖关系使得部署很难有效完成。The expanded dependencies make it difficult for the deployment to complete efficiently.

以下示例展示了如何部署多个虚拟机。The following example shows how to deploy multiple virtual machines. 该模板会创建相同数量的网络接口。The template creates the same number of network interfaces. 每个虚拟机都依赖于一个网络接口,而不是依赖于整个循环。Each virtual machine is dependent on one network interface, rather than the whole loop.

{
  "type": "Microsoft.Network/networkInterfaces",
  "apiVersion": "2020-05-01",
  "name": "[concat(variables('nicPrefix'),'-',copyIndex())]",
  "location": "[parameters('location')]",
  "copy": {
    "name": "nicCopy",
    "count": "[parameters('vmCount')]"
  },
  ...
},
{
  "type": "Microsoft.Compute/virtualMachines",
  "apiVersion": "2020-06-01",
  "name": "[concat(variables('vmPrefix'),copyIndex())]",
  "location": "[parameters('location')]",
  "dependsOn": [
    "[resourceId('Microsoft.Network/networkInterfaces',concat(variables('nicPrefix'),'-',copyIndex()))]"
  ],
  "copy": {
    "name": "vmCopy",
    "count": "[parameters('vmCount')]"
  },
  "properties": {
    "networkProfile": {
      "networkInterfaces": [
        {
          "id": "[resourceId('Microsoft.Network/networkInterfaces',concat(variables('nicPrefix'),'-',copyIndex()))]",
          "properties": {
            "primary": "true"
          }
        }
      ]
    },
    ...
  }
}

以下示例演示了如何在部署虚拟机之前部署三个存储帐户。The following example shows how to deploy three storage accounts before deploying the virtual machine. 请注意,copy 元素的 name 设置为 storagecopy,而虚拟机的 dependsOn 元素也设置为 storagecopyNotice that the copy element has name set to storagecopy and the dependsOn element for the virtual machine is also set to storagecopy.

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {},
  "resources": [
    {
      "type": "Microsoft.Storage/storageAccounts",
      "apiVersion": "2019-04-01",
      "name": "[concat(copyIndex(),'storage', uniqueString(resourceGroup().id))]",
      "location": "[resourceGroup().location]",
      "sku": {
        "name": "Standard_LRS"
      },
      "kind": "Storage",
      "copy": {
        "name": "storagecopy",
        "count": 3
      },
      "properties": {}
    },
    {
      "type": "Microsoft.Compute/virtualMachines",
      "apiVersion": "2015-06-15",
      "name": "[concat('VM', uniqueString(resourceGroup().id))]",
      "dependsOn": ["storagecopy"],
      ...
    }
  ],
  "outputs": {}
}

循环依赖项Circular dependencies

Resource Manager 可在模板验证过程中确定循环依赖项。Resource Manager identifies circular dependencies during template validation. 如果收到有关循环依赖关系的错误,请评估你的模板,了解是否存在可以删除的依赖关系。If you receive an error for a circular dependency, evaluate your template to see if any dependencies can be removed. 如果删除依赖关系不起作用,则可将一些部署操作移至子资源中来避免循环依赖关系。If removing dependencies doesn't work, you can avoid circular dependencies by moving some deployment operations into child resources. 请在具有循环依赖关系的资源之后部署子资源。Deploy the child resources after the resources that have the circular dependency. 例如,假设要部署两个虚拟机,但必须在每个虚拟机上设置引用另一虚拟机的属性。For example, suppose you're deploying two virtual machines but you must set properties on each one that refer to the other. 可以按下述顺序部署这两个虚拟机:You can deploy them in the following order:

  1. vm1vm1
  2. vm2vm2
  3. vm1 上的扩展依赖于 vm1 和 vm2。Extension on vm1 depends on vm1 and vm2. 扩展在 vm1 上设置的值是从 vm2 获取的。The extension sets values on vm1 that it gets from vm2.
  4. vm2 上的扩展依赖于 vm1 和 vm2。Extension on vm2 depends on vm1 and vm2. 扩展在 vm2 上设置的值是从 vm1 获取的。The extension sets values on vm2 that it gets from vm1.

有关评估部署顺序和解决依赖项错误的信息,请参阅排查使用 Azure 资源管理器时的常见 Azure 部署错误For information about assessing the deployment order and resolving dependency errors, see Troubleshoot common Azure deployment errors with Azure Resource Manager.

后续步骤Next steps