Iteração de recurso em modelos ARM

Este artigo mostra como criar mais de uma instância de um recurso no seu modelo do Azure Resource Manager (modelo do ARM). Ao adicionar o loop de cópia à seção de recursos do modelo, você pode definir dinamicamente o número de recursos que deseja implantar. Você também evita a repetição da sintaxe do modelo.

Você também pode usar o loop de cópia com propriedades, variáveise saídas

Caso precise especificar se um recurso é ou não implantado, confira Elemento condition.

Dica

Recomendamos o Bicep porque ele oferece as mesmas funcionalidades que os modelos do ARM e a sintaxe é mais fácil de usar. Para saber mais, confira loops.

Sintaxe

Adicione o elemento copy à seção de recursos do seu modelo para implantar várias instâncias do recurso. O elemento copy tem o seguinte formato geral:

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

A propriedade name é qualquer valor que identifique o loop. A propriedade count especifica o número de iterações que você deseja para o tipo de recurso.

Use as propriedades mode e batchSize para especificar se os recursos são implantados em paralelo ou em sequência. Essas propriedades são descritas em Serial ou Paralelo.

Limites de cópia

A contagem não pode exceder 800.

A contagem não pode ser um número negativo. Ela pode ser zero se você implantar o modelo com uma versão recente da CLI do Azure, do PowerShell ou da API REST. Especificamente, você deve usar:

  • Azure PowerShell 2.6 ou posterior
  • CLI do Azure 2.0.74 ou posterior
  • API REST versão 10-05-2019 ou posterior
  • As implantações vinculadas devem usar a versão de API 10-05-2019 ou posterior para o tipo de recurso de implantação

As versões anteriores do PowerShell, da CLI e da API REST não dão suporte a zero como contagem.

Tenha cuidado ao usar a implantação de modo completo com o loop de cópia. Se você reimplanta com o modo completo em um grupo de recursos, todos os recursos que não foram especificados no modelo após a resolução do loop de cópia são excluídos.

Iteração de recurso

O exemplo a seguir cria o número de contas de armazenamento especificado no parâmetro 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": {}
    }
  ]
}

Observe que o nome de cada recurso inclui a função copyIndex(), que retorna a iteração atual no loop. copyIndex()é baseado em zero. Assim, o seguinte exemplo:

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

Cria estes nomes:

  • storage0
  • storage1
  • storage2

Para deslocar o valor do índice, você pode passar um valor na função copyIndex(). O número de iterações ainda é especificado no elemento de cópia, mas o valor de copyIndex é deslocado pelo valor especificado. Assim, o seguinte exemplo:

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

Cria estes nomes:

  • storage1
  • storage2
  • storage3

A operação de cópia é útil ao trabalhar com matrizes porque você pode percorrer cada elemento da matriz. Use a função length na matriz para especificar a contagem de iterações e copyIndex para recuperar o índice atual na matriz.

O exemplo a seguir cria uma conta de armazenamento para cada nome fornecido no parâmetro.

{
  "$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": {}
    }
  ]
}

Você pode usar Copiar na seção de saídas se deseja retornar valores dos recursos implantados.

Use o nome simbólico

O nome simbólico será atribuído a loops de cópia de recurso. O índice de loop é baseado em zero. No exemplo a seguir, myStorages[1] faz referência ao segundo recurso no loop de recursos.

{
  "$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]"
    }
  }
}

Se o índice for um valor de runtime, formate a referência por conta própria. Por exemplo

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

Nomes simbólicos podem ser usados em matrizes dependsOn. Se um nome simbólico for para um loop de cópia, todos os recursos no loop serão adicionados como dependências. Para obter mais informações, consulte Depende de recursos em um loop.

Serial ou Paralelo

Por padrão, o Gerenciador de Recursos cria os recursos em paralelo. Ele não aplica limites ao número de recursos implantados em paralelo, com exceção do limite total de 800 recursos no modelo. A ordem em que eles são criados não é garantida.

No entanto, convém especificar que os recursos são implantados em sequência. Por exemplo, ao atualizar um ambiente de produção, convém balancear as atualizações para que apenas um determinado número seja atualizado por vez.

Para implantar em série mais de uma instância de um recurso, defina mode para mode e batchSize para o número de instâncias a serem implantadas de cada vez. Com o modo serial, o Resource Manager cria uma dependência em instâncias anteriores no loop de modo que não inicie um lote até que o lote anterior esteja concluído.

O valor de batchSize não pode exceder o valor de count no elemento de cópia.

{
  "$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": {}
    }
  ]
}

A propriedade mode também aceita mode, que é o valor padrão.

Iteração para um recurso filho

Você não pode usar um loop de cópia para um recurso filho. Para criar mais de uma instância de um recurso que você normalmente define como aninhado em outro recurso, você deve criar esse recurso como um recurso de nível superior. Você define a relação com o recurso pai por meio das propriedades de tipo e nome.

Por exemplo, suponha que você normalmente defina um conjunto de dados como um recurso filho em uma data factory.

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

Para criar mais de um conjunto de dados, mova-o para fora do data factory. O conjunto de dados deve estar no mesmo nível que a data factory, mas ainda é um recurso filho da data factory. Você preserva a relação entre um conjunto de dados e o data factory por meio das propriedades de tipo e nome. Como o tipo não pode ser inferido de sua posição no modelo, você deve fornecer o tipo totalmente qualificado no formato: {resource-provider-namespace}/{parent-resource-type}/{child-resource-type}.

Para estabelecer uma relação pai/filho com uma instância da data factory, forneça um nome para o conjunto de dados que inclui o nome do recurso pai. Use o formato: {parent-resource-name}/{child-resource-name}.

O exemplo a seguir mostra a implementação.

"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"
  },
  ...
}]

Modelos de exemplo

Os exemplos a seguir mostram cenários comuns para criar mais de uma instância de um recurso ou propriedade.

Modelo Descrição
Armazenamento de cópia Implanta a mais de uma conta de armazenamento com um número de índice no nome.
Armazenamento de cópia serial Implanta várias contas de armazenamento ao tempo. O nome inclui o número de índice.
Armazenamento de cópia com matriz Implanta várias contas de armazenamento. O nome inclui um valor de uma matriz.
Copiar grupo de recursos Implanta vários grupos de recursos.

Próximas etapas