Criar várias instâncias de recursos através do elemento copy

Concluído

Até agora, declarou os recursos numa lista de recursos num modelo. Durante a implementação, acaba por ter uma instância de cada item especificado na lista de recursos. Recomendamos que crie mais do que uma instância de um recurso específico. Por exemplo, pode querer ter várias sub-redes numa rede virtual.

Considere as perguntas e os pontos seguintes quando estiver a pensar em criar várias instâncias e iterar pelas construções:

  • Preciso de mais de uma cópia: para cenários mais simples, talvez não. Em cenários mais avançados, como sub-redes ou máquinas virtuais, talvez tenha de considerar se precisa de mais do que uma cópia de algo.
  • Sou dependente de um recurso: normalmente o Azure Resource Manager é bom em descobrir o que precisa ser construído em que ordem, para que as referências no modelo do Azure Resource Manager funcionem. Há situações, no entanto, em que você pode precisar especificar a ordem.
  • Defina um esquema de nomenclatura: você deseja dar nomes significativos aos seus recursos. Por esse motivo, depende de parâmetros transmitidos no momento da implementação. Quando tem várias cópias, talvez queira ter um controlo mais granular e basear a nomenclatura na iteração da sequência de cópia em que se encontra atualmente.
  • Configurar e controlar a criação de recursos: talvez você queira limitar quantos recursos estão sendo criados em um ambiente de produção. Poderá fazê-lo ao configurar a criação de recursos como em série ou paralela.
  • Copiar outros tipos: os recursos não são a única coisa que você pode criar várias cópias e repetir. Na realidade, pode fazer o mesmo com propriedades, variáveis e saídas.
  • Pai-filho: talvez seja necessário configurar relações pai-filho em seus recursos.

Criar múltiplas instâncias

Pode utilizar construções em ciclo para não ter de premir tantas teclas. Se aquilo de que precisa se repete várias vezes, com nomes e tipos bastantes semelhantes, e há apenas pequenas diferenças, poderá beneficiar da utilização do elemento copy.

O elemento copy é um fragmento de JSON que pode utilizar em muitos tipos de construções, como recursos, propriedades, variáveis e saídas. A sintaxe do elemento copy consiste na chave copy e tem uma matriz como valor. Por exemplo: "copy": [].

A matriz utiliza vários elementos e cada elemento é um objeto {} que consiste em propriedades definidas. Estas propriedades dependem do tipo de construção em que são utilizadas. Normalmente, todas as construções do elemento copy têm uma propriedade em comum: count. Esta propriedade decide quantas instâncias quer de um determinado tipo de construção. A maioria das construções também permite uma propriedade name, que proporciona uma referência que pode utilizar noutras partes do seu código. As restantes propriedades utilizadas são específicas da construção.

O que escolher

Você pode perguntar: "Se eu posso usar o copy elemento em muitos tipos de construções, qual devo escolher e quando, e posso usar mais de um tipo em um modelo?"

Tudo depende do seu caso de utilização. Uma iteração de recursos permite criar várias cópias de um recurso e faz sentido utilizá-la se precisar, por exemplo, de muitas contas de armazenamento. Uma iteração de propriedades, por outro lado, permite-lhe criar muitas propriedades num recurso. Desta forma, não tem de premir tantas teclas, poupa tempo e sabe com maior exatidão quando tem partes repetidas no seu modelo.

Pode utilizar o elemento copy em muitos locais no seu modelo. Pode utilizar um elemento copy para criar muitos recursos, mas também para criar muitas variáveis semelhantes no mesmo modelo.

Como funciona

O elemento copy funciona ao avaliar e substituir a sua instrução copy. A substituição é o resultado do que você define dentro da instrução repetida copy quantas vezes você instruiu no copy campo.

O exemplo seguinte mostra o aspeto que uma definição a utilizar copy pode ter:

"copy": [
  {
    "name": "dataDisks",
    "count": 2,
    "input": {
      "diskSizeGB": 1023,
      "lun": "[copyIndex('dataDisks')]",
      "createOption": "Empty"
    }
  }
]

Tenha em atenção a entrada count: 2. O valor2 significa que pretende que a expressão acima se expanda para duas entradas. O resultado é o seguinte:

"dataDisks": [
{
  "lun": 0,
  "createOption": "Empty",
  "diskSizeGB": 1023
},
{
  "lun": 1,
  "createOption": "Empty",
  "diskSizeGB": 1023
}

Pode ver que o valor da propriedade name se tornou o nome da propriedade e os conteúdos da propriedade input se tornaram a parte do JSON que é repetida.

Nota

A expressão copy e a respetiva saída são diferentes consoante o tipo de expressão utilizado. O exemplo anterior dá uma boa ideia do que acontece quando uma expressão é transformada numa série de instruções repetidas.

Há limites para o quanto pode ser copiado. Atualmente, o limite é de 800 entradas.

Importante

Para obter mais informações sobre as limitações exatas, veja Iteração de recursos em modelos do ARM.

Controlar a iteração

Há funções auxiliares que ajudam a fazer referência a índices específicos na matriz. A função copyIndex() devolve o índice atual. Por exemplo, para a terceira entrada repetida, copyIndex() devolve o valor 2. A sintaxe de copyIndex() tem o seguinte aspeto:

copyIndex(loopName, offset)

A função copyIndex() tem dois parâmetros de entrada diferentes, loopName e offset. O parâmetro offset é sempre opcional e é utilizado para deslocamento do índice atual. O que adicionar como valor de offset é adicionado ao índice atual. Se o índice atual devolver 2 e especificar 1 como deslocamento, a função copyIndex() devolve 3.

O parâmetro loopName é opcional ou obrigatório, consoante o local onde o utiliza. É obrigatório se for utilizado numa construção de properties e opcional se for utilizado numa matriz de resources. Segue-se um exemplo em que é obrigatório:

"properties": {
    "storageProfile": {
      "copy": [
        {
          "name": "dataDisks",
          "count": "[parameters('numberOfDataDisks')]",
          "input": {
            "diskSizeGB": 1023,
            "lun": "[copyIndex('dataDisks')]",
            "createOption": "Empty"
          }
        }
      ]
    }
}

Observe como o elemento copy é utilizado dentro de uma construção de properties e copyIndex() tem o loopName especificado como copyIndex('dataDisks').

Segue-se um exemplo em que loopName não é obrigatório:

{
  "type": "Microsoft.Network/virtualNetworks",
  "apiVersion": "2018-04-01",
  "name": "[concat(parameters('vnetname'), copyIndex())]",
}

Mostra a declaração de um recurso e copyIndex() é chamado sem parâmetros, uma vez que está a ser utilizado no contexto de um recurso.

Configurar a implementação

Ao utilizar o elemento copy para os recursos, acaba por criar vários recursos semelhantes.

Por vezes, pode querer controlar como os recursos são criados e em que ordem. Os motivos para controlar a ordem podem ser:

  • Limitações do ambiente. Dependendo do ambiente no qual está a implementar, talvez queira limitar em que medida este ambiente é afetado por uma implementação. Num ambiente de produção, faz sentido limitar quantos recursos são afetados em cada momento. Pode configurar um modo de implementação para controlar o número de recursos implementados em simultâneo.
  • Dependências. Pode depender de algo que já exista antes de avançar com a criação do recurso necessário. Para expressar essa dependência, existe uma construção chamada dependsOn.

Modos de implantação e copy

É recomendável garantir que um conjunto de recursos criado pela construção copy esteja a ser criado antes de tudo o resto. Se for esse o caso, precisará de expressar esta situação. Tenha presente que o que interessa é o modo de implementação utilizado pelo Resource Manager. Há dois modos suportados:

  • Série. Definir um recurso para este modo de implementação significa que os recursos serão criados uns após os outros. Neste modo, também deve definir a propriedade batchSize para determinar quantos recursos são implementados ao utilizar este modo. Um novo lote não pode ser iniciado antes que um anterior tenha sido concluído. É recomendável limitar as coisas desta forma num ambiente de produção, por exemplo, onde pode ser importante limitar o número de recursos afetados em qualquer ponto.
  • Paralelo. Este é o modo de implementação predefinido. A vantagem é o alto débito, pelo que o modelo é processado mais rapidamente. As desvantagens são a incapacidade em garantir a ordem, que pode não ser a que pretende num ambiente de produção.

Dependências

No contexto do elemento copy, precisa de indicar ao recurso que tem a dependência qual é a secção da qual está à espera. Para executar esta dependência, deverá mencioná-la pelo nome com o seguinte JSON:

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

Tenha em atenção que o elemento copy tem uma propriedade name com o valor storagecopy. O recurso dependente, uma conta de armazenamento, aguarda pela conclusão da operação do elemento copy. Isto é expresso por "dependsOn": ["storagecopy"].

Assim, o modelo do ARM muda para um modo de implementação de série entre esses dois recursos. Pode afetar a velocidade do débito da implementação, mas expressou que se preocupa com uma determinada ordem de implementação, que agora terá precedência.