ARM 模板中的资源迭代

本文介绍如何在 Azure 资源管理器模板(ARM 模板)中创建多个资源实例。 通过将复制循环添加到模板的资源部分,可以动态设置要部署的资源数。 还可以避免重复模板语法。

还可以将复制循环与 属性变量输出配合使用。

如果您需要指定资源是否已部署,请参阅 condition 元素

提示

我们建议使用 Bicep,因为它提供与 ARM 模板相同的功能,并且该语法更易于使用。 若要了解详细信息,请参阅 循环

语法

copy 元素添加到模板的资源部分,以部署资源的多个实例。 该 copy 元素具有以下常规格式:

"copy": {
  "name": "<name-of-loop>",
  "count": <number-of-iterations>,
  "mode": "serial" <or> "parallel",
  "batchSize": <number-to-deploy-serially>
}

name 属性是标识循环的任何值。 该 count 属性指定要用于资源类型的迭代数。

使用mode属性和batchSize属性来指定资源是并行部署还是按顺序部署。 这些属性在 串行或并行中介绍。

复制限制

计数不能超过 800。

计数不能为负数。 如果使用最新版本的 Azure CLI、PowerShell 或 REST API 部署模板,则为零。 具体而言,必须使用:

  • Azure PowerShell 2.6 或更高版本
  • Azure CLI 2.0.74 或更高版本
  • REST API 版本 2019-05-10 或更高版本
  • 链接部署的部署资源类型必须使用 API 版本 2019-05-10或更高版本

早期版本的 PowerShell、CLI 和 REST API 不支持将零作为有效计数。

完整模式部署与 copy 循环一起使用时要小心。 如果使用完全模式重新部署到资源组,解析复制循环后将删除未在模板中指定的任何资源。

资源迭代

以下示例创建参数中指定的 storageCount 存储帐户数。

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "location": {
      "type": "string",
      "defaultValue": "[resourceGroup().location]"
    },
    "storageCount": {
      "type": "int",
      "defaultValue": 3
    }
  },
  "resources": [
    {
      "copy": {
        "name": "storagecopy",
        "count": "[length(range(0, parameters('storageCount')))]"
      },
      "type": "Microsoft.Storage/storageAccounts",
      "apiVersion": "2022-09-01",
      "name": "[format('{0}storage{1}', range(0, parameters('storageCount'))[copyIndex()], uniqueString(resourceGroup().id))]",
      "location": "[parameters('location')]",
      "sku": {
        "name": "Standard_LRS"
      },
      "kind": "Storage",
      "properties": {}
    }
  ]
}

请注意,每个资源的名称都包含函数 copyIndex() ,该函数在循环中返回当前迭代。 copyIndex() 将从零开始。 因此,以下示例:

"name": "[format('storage{0}', copyIndex())]",

将创建以下名称:

  • storage0
  • 存储1
  • 存储2

若要偏移索引值,可以在 copyIndex() 函数中传递一个值。 迭代次数仍在复制元素中指定,但copyIndex的值会被指定的值进行偏移。 因此,以下示例:

"name": "[format('storage{0}', copyIndex(1))]",

将创建以下名称:

  • 存储1
  • 存储2
  • storage3

在处理数组时,复制操作非常有用,因为你可以遍历数组中的每个元素。 使用 length 数组上的函数指定迭代计数,并 copyIndex 检索数组中的当前索引。

以下示例为参数中提供的每个名称创建一个存储帐户。

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "storageNames": {
      "type": "array",
      "defaultValue": [
        "contoso",
        "fabrikam",
        "coho"
      ]
    },
    "location": {
      "type": "string",
      "defaultValue": "[resourceGroup().location]"
    }
  },
  "resources": [
    {
      "copy": {
        "name": "storagecopy",
        "count": "[length(parameters('storageNames'))]"
      },
      "type": "Microsoft.Storage/storageAccounts",
      "apiVersion": "2022-09-01",
      "name": "[format('{0}{1}', parameters('storageNames')[copyIndex()], uniqueString(resourceGroup().id))]",
      "location": "[parameters('location')]",
      "sku": {
        "name": "Standard_LRS"
      },
      "kind": "Storage",
      "properties": {}
    }
  ]
}

如果要从已部署的资源返回值,可以使用 输出部分中的副本

使用符号名称

符号名称将分配给资源复制循环。 循环索引从零开始。 在以下示例中, myStorages[1] 引用资源循环中的第二个资源。

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "languageVersion": "2.0",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "location": {
      "type": "string",
      "defaultValue": "[resourceGroup().location]"
    },
    "storageCount": {
      "type": "int",
      "defaultValue": 2
    }
  },
  "resources": {
    "myStorages": {
      "type": "Microsoft.Storage/storageAccounts",
      "apiVersion": "2022-09-01",
      "name": "[format('{0}storage{1}', copyIndex(), uniqueString(resourceGroup().id))]",
      "location": "[parameters('location')]",
      "sku": {
        "name": "Standard_LRS"
      },
      "kind": "Storage",
      "properties": {},
      "copy": {
        "name": "storagecopy",
        "count": "[parameters('storageCount')]"
      }
    }
  },
  "outputs": {
    "storageEndpoint":{
      "type": "object",
      "value": "[reference('myStorages[1]').primaryEndpoints]"
    }
  }
}

如果索引是运行时值,请自行设置引用的格式。 例如:

"outputs": {
  "storageEndpoint":{
    "type": "object",
    "value": "[reference(format('myStorages[{0}]', variables('runtimeIndex'))).primaryEndpoints]"
  }
}

符号名称可用于 dependsOn 数组。 如果符号名称用于复制循环,则循环中的所有资源将添加为依赖项。 有关详细信息,请参阅 “依赖于循环中的资源”。

串行或并行

默认情况下,资源管理器并行创建资源。 它对并行部署的资源数量没有限制,除了模板中的资源总数限制为800个外。 无法保证它们的创建顺序。

但是,你可能想要指定按顺序部署资源。 例如,在更新生产环境时,可能需要错开更新,使任何一次仅更新一定数量。

若要串行部署资源的多个实例,请将mode设置为串行,并将batchSize设置为一次要部署的实例数。 使用串行模式时,资源管理器会在循环中的早期实例上创建依赖项,因此在上一批完成之前不会启动一个批处理。

batchSize的值不能超过 copy 元素中的值count

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "location": {
      "type": "string",
      "defaultValue": "[resourceGroup().location]"
    }
  },
  "resources": [
    {
      "copy": {
        "name": "storagecopy",
        "count": 4,
        "mode": "serial",
        "batchSize": 2
      },
      "type": "Microsoft.Storage/storageAccounts",
      "apiVersion": "2022-09-01",
      "name": "[format('{0}storage{1}', range(0, 4)[copyIndex()], uniqueString(resourceGroup().id))]",
      "location": "[parameters('location')]",
      "sku": {
        "name": "Standard_LRS"
      },
      "kind": "Storage",
      "properties": {}
    }
  ]
}

mode 属性还接受 并行,即默认值。

子资源的迭代

不能对子资源使用复制循环。 若要创建通常定义为嵌套在另一个资源中的资源的多个实例,必须改为将该资源创建为顶级资源。 通过类型和名称属性定义与父资源的关系。

例如,假设通常将数据集定义为数据工厂中的子资源。

{
  "resources": [
    {
      "type": "Microsoft.DataFactory/factories",
      "name": "exampleDataFactory",
      ...
      "resources": [
        {
          "type": "datasets",
          "name": "exampleDataSet",
          "dependsOn": [
            "exampleDataFactory"
          ],
          ...
        }
      ]
      ...
    }
  ]
}

若要创建多个数据集,请将数据集移到数据工厂之外。 数据集必须与数据工厂位于同一级别,但它仍然是数据工厂的子资源。 通过类型和名称属性保留数据集和数据工厂之间的关系。 由于无法再从模板中的位置推断类型,因此必须以以下格式提供完全限定的类型: {resource-provider-namespace}/{parent-resource-type}/{child-resource-type}

若要与数据工厂实例建立父/子关系,请提供包含父资源名称的数据集的名称。 使用以下格式: {parent-resource-name}/{child-resource-name}

以下示例演示了实现。

"resources": [
{
  "type": "Microsoft.DataFactory/factories",
  "name": "exampleDataFactory",
  ...
},
{
  "type": "Microsoft.DataFactory/factories/datasets",
  "name": "[format('exampleDataFactory/exampleDataSet{0}', copyIndex())]",
  "dependsOn": [
    "exampleDataFactory"
  ],
  "copy": {
    "name": "datasetcopy",
    "count": "3"
  },
  ...
}]

示例模板

以下示例演示了创建资源或属性的多个实例的常见方案。

模板 DESCRIPTION
复制存储 部署多个带有名称索引号的存储帐户。
串行复制存储 一次部署多个存储帐户。 该名称包括索引号。
使用数组复制存储 部署多个存储帐户。 该名称包括数组中的值。
复制资源组 部署多个资源组。

后续步骤