Итерация ресурсов в шаблонах ARM

В этой статье показано, как создать несколько экземпляров ресурса в шаблоне Azure Resource Manager (шаблоне ARM). Добавив цикл копирования в раздел resources шаблона, можно динамически задать число развертываемых ресурсов. Кроме того, не нужно повторять синтаксис шаблона.

Можно также использовать цикл копирования для свойств, переменных и выходных данных.

Если вам нужно указать, развернут ли ресурс, см. описание элемента condition.

Совет

Мы рекомендуем использовать Bicep, так как он предоставляет те же возможности, что и шаблоны ARM, и имеет более простой синтаксис. Дополнительные сведения см. в статье о циклах.

Синтаксис

Добавьте элемент copy в раздел resources шаблона, чтобы развернуть несколько экземпляров ресурса. Элемент 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 не поддерживают нулевое значение числа.

Будьте внимательны при развертывании в полном режиме с помощью цикла копирования. При повторном развертывании в полном режиме в группе ресурсов все ресурсы, не указанные в шаблоне после завершения цикла копирования, удаляются.

Итерация ресурса

В следующем примере создается заданное в параметре 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;
  • storage1;
  • storage2;

Чтобы сместить значение индекса, можно передать нужное значение в функцию copyIndex(). Число выполняемых итераций по-прежнему указывается в элементе copy, но значение copyIndex сдвигается на указанное значение. См. приведенный ниже пример.

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

Он создает следующие имена:

  • storage1;
  • storage2;
  • 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": {}
    }
  ]
}

Если требуется возвращать значения из развернутых ресурсов, можно использовать операцию copy в разделе outputs.

Использовать символьные имена

Символьное имя будет присвоено циклам копирования ресурсов. Индекс цикла отсчитывается от нуля. В следующем примере 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. Если символьное имя используется для цикла копирования, все ресурсы в цикле добавляются в качестве зависимостей. Дополнительные сведения см. в разделе Зависит от ресурсов в цикле.

Последовательная или параллельная обработка

По умолчанию Resource Manager создает ресурсы параллельно. Он не ограничивает количество ресурсов, развертываемых параллельно, за исключением общего ограничения в 800 ресурсов в шаблоне. Порядок, в котором они создаются, не гарантируется.

Тем не менее можно настроить последовательное развертывание ресурсов. Например, при обновлении рабочей среды может потребоваться дифференцировать обновления, чтобы только определенное число элементов могло быть обновлено в любой момент времени.

Чтобы последовательно развернуть несколько экземпляров ресурса, задайте параметру mode значение serial, а в качестве значения batchSize введите число экземпляров, которое необходимо развернуть за раз. В последовательном режиме Resource Manager создает зависимость от предыдущих экземпляров в цикле, поэтому он не начинает выполнение следующего пакета до завершения предыдущего.

Значение параметра batchSize не может превышать значение count в элементе copy.

{
  "$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 также принимает значение parallel, которое является значением по умолчанию.

Итерация дочерних ресурсов

Нельзя включить дочерний ресурс в цикл копирования. Чтобы создать несколько экземпляров ресурса, которые определяются как вложенные в другой ресурс, необходимо создать его как ресурс верхнего уровня. Вы можете определить связь с родительским ресурсом с помощью свойств type и name.

Предположим, вы определяете набор данных как дочерний ресурс фабрики данных.

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

Чтобы создать несколько наборов данных, переместите его за пределы фабрики данных. Набор данных должен находиться на том же уровне, что и фабрика данных, но при этом он должен быть дочерним ресурсом фабрики данных. Вы можете сохранить связь между набором данных и фабрикой данных с помощью свойств type и name. Так как тип нельзя определить по положению в шаблоне, укажите полное имя типа в следующем формате: {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"
  },
  ...
}]

Образцы шаблонов

Ниже приведены примеры распространенных сценариев для создания нескольких экземпляров ресурса или свойства.

Шаблон Описание
Копирования хранилища Развертывает несколько учетных записей хранения с номером индекса в имени.
Последовательное копирование хранилища Последовательно развертывает несколько учетных записей хранения. Имя содержит номер индекса.
Копирования хранилища с массивом Развертывает несколько учетных записей хранения. Имя содержит значение из массива.
Копирование группы ресурсов Развертывает несколько групп ресурсов.

Дальнейшие действия