Creare più istanze di risorse usando l'elemento copy

Completato

Finora le risorse sono state dichiarate in un elenco di risorse in un modello. Durante la distribuzione si finisce per avere un'istanza di ogni elemento specificato nell'elenco delle risorse. Potrebbe essere necessario creare più di un'istanza di una risorsa specifica. Ad esempio nel caso in cui si vogliano avere più subnet in una rete virtuale.

Prendere in considerazione le domande e i punti seguenti quando si progettano la creazione di molte istanze e l'iterazione dei costrutti:

  • È necessaria più di una copia: per scenari più semplici, non è possibile. Negli scenari più avanzati, ad esempio le subnet o le macchine virtuali, potrebbe essere opportuno considerare se è necessario avere più di una copia di una risorsa.
  • Dipende da una risorsa: In genere Azure Resource Manager è utile per capire cosa deve essere costruito in quale ordine, in modo che i riferimenti all'interno del modello di Azure Resource Manager funzionino. In alcune situazioni, tuttavia, potrebbe essere necessario specificare l'ordine.
  • Definire uno schema di denominazione: assegnare nomi significativi alle risorse. Per questo motivo, ci si affida ai parametri passati in fase di distribuzione. Quando si hanno più copie, potrebbe essere necessario effettuare un controllo più granulare e basare la denominazione sull'iterazione attualmente in corso nella sequenza di copia.
  • Configurare e controllare la creazione di risorse: è possibile limitare il numero di risorse create in un ambiente di produzione. È possibile eseguire questa operazione configurando la creazione delle risorse come seriale o parallela.
  • Copiare altri tipi: le risorse non sono l'unica cosa che è possibile creare più copie di e scorrere. In realtà, le stesse operazioni si possono eseguire con proprietà, variabili e output.
  • Padre-figlio: potrebbe essere necessario configurare le relazioni padre-figlio nelle risorse.

Creare più istanze

È possibile usare i costrutti di ciclo per ridurre la digitazione. Se l'elemento necessario si ripete molte volte, con nomi e tipi abbastanza simili, e le differenze sono minime, si potrebbe trarre vantaggio dall'uso dell'elemento copy.

L'elemento copy è una parte di JSON che può essere usata in molti tipi di costrutti, ad esempio risorse, proprietà, variabili e output. La sintassi per l'elemento copy è costituita dalla chiave copy e da una matrice come valore. Ad esempio: "copy": [].

La matrice accetta un numero di elementi e ogni elemento è un oggetto {} costituito da un set di proprietà. Le caratteristiche delle proprietà dipendono dal tipo di costrutto in cui vengono usate. In genere, tutti i costrutti con l'elemento copy hanno una proprietà in comune: count. Questa proprietà decide il numero di istanze da usare per un determinato tipo di costrutto. La maggior parte dei costrutti consente anche l'uso di una proprietà name, che offre un riferimento che può essere usato in altre parti del codice. Altre proprietà usate sono specifiche del costrutto.

Che cosa scegliere

Si potrebbe chiedere: "Se posso usare l'elemento copy in molti tipi di costrutti, quale scegliere e quando e posso usare più di un tipo in un modello?"

Dipende tutto dal caso d'uso. Un'iterazione della risorsa consente di creare molte copie di una risorsa e può essere utile usarla se ad esempio sono necessari molti account di archiviazione. Un'iterazione delle proprietà, d'altra parte, consente di creare molte proprietà all'interno della stessa risorsa. In questo modo si riduce la digitazione e si risparmia tempo ed è più facile sapere dove sono le parti ripetute nel modello.

È possibile usare l'elemento copy in molte posizioni nel modello. È possibile usare un elemento copy per creare molte risorse, ma anche per creare molte variabili simili all'interno dello stesso modello.

Funzionamento

L'elemento copy funziona con la valutazione e la sostituzione dell'istruzione copy. La sostituzione è il risultato di ciò che si definisce all'interno dell'istruzione copy ripetuta quante volte è stato indicato nel copy campo.

Nell'esempio seguente viene illustrato il possibile aspetto di una definizione che usa copy:

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

Si noti la voce count: 2. Il valore 2 significa che si vuole espandere l'espressione sopra riportata a due voci. Di seguito è riportato il risultato:

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

Si può notare che il valore della proprietà name è diventato il nome della proprietà e che il contenuto della proprietà input è diventato la parte ripetuta del codice JSON.

Nota

L'espressione copy e il relativo output variano in base al tipo di espressione usata. L'esempio precedente offre un'idea di cosa accade quando un'espressione viene trasformata in una serie di istruzioni ripetute.

Esistono limiti alla quantità di elementi che possono essere copiati. Attualmente il limite è 800 voci.

Importante

Per altre informazioni sulle limitazioni esatte, vedere Iterazione delle risorse nei modelli di ARM.

Controllare l'iterazione

Sono disponibili funzioni helper che consentono di fare riferimento a indici specifici nella matrice. La funzione copyIndex() restituisce l'indice corrente. Per la terza voce ripetuta, ad esempio, copyIndex() restituisce il valore 2. La sintassi di copyIndex() ha un aspetto simile al seguente:

copyIndex(loopName, offset)

La funzione copyIndex() ha due parametri di input diversi, loopName e offset. Il parametro offset è sempre facoltativo e viene usato per l'offset dall'indice corrente. Qualsiasi elemento aggiunto come valore offset viene aggiunto all'indice corrente. Se l'indice corrente restituisce 2 e si specifica 1 come offset, la funzione copyIndex() restituisce 3.

Il parametro loopName è facoltativo o obbligatorio a seconda della posizione in cui viene usato. È obbligatorio se usato all'interno di un costrutto properties e facoltativo se usato in una matrice resources. Di seguito è riportato un esempio in cui è obbligatorio:

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

Si noti il modo in cui l'elemento copy viene usato all'interno di un costrutto properties e per copyIndex()loopName è specificato come copyIndex('dataDisks').

Ecco un esempio in cui loopName non è obbligatorio:

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

Mostra una risorsa dichiarata e copyIndex() viene chiamato senza parametri, perché viene usato nel contesto di una risorsa.

Configurare la distribuzione

Quando si usa l'elemento copy per le risorse, si finisce per creare numerose risorse simili tra loro.

In alcuni casi può essere utile stabilire come vengono create le risorse e in quale ordine. Può essere opportuno decidere un ordine per i seguenti motivi:

  • Limitazioni dell'ambiente. A seconda dell'ambiente in cui si esegue la distribuzione, potrebbe essere necessario limitare l'impatto della distribuzione sull'ambiente. In un ambiente di produzione è opportuno limitare il numero di risorse interessate in un momento specifico. È possibile configurare una modalità di distribuzione per controllare il numero di risorse distribuite simultaneamente.
  • Dipendenze. Si potrebbe dipendere dall'esistenza di un elemento per poter creare la risorsa necessaria. Per esprimere tale dipendenza, esiste un costrutto denominato dependsOn.

Modalità di distribuzione e copy

Potrebbe essere necessario verificare che un set di risorse creato dal costrutto copy venga creato prima di qualcos'altro. In questo caso è necessario esprimere questa situazione. Si ricordi che a questo punto entra in gioco la modalità di distribuzione usata da Resource Manager. Sono supportate due modalità:

  • Seriale. L'impostazione di una risorsa su questa modalità di distribuzione significa che le risorse verranno create una dopo l'altra. In questa modalità è inoltre prevista l'impostazione della proprietà batchSize per determinare il numero di risorse distribuite usando la modalità. Non è possibile avviare un nuovo batch prima di averne completato uno precedente. Potrebbe essere necessario limitare le cose in questo modo in un ambiente di produzione, ad esempio nel caso in cui potrebbe essere importante limitare il numero di risorse interessate in un determinato momento.
  • Parallela. Questa modalità è la modalità di distribuzione predefinita. Il vantaggio è una velocità effettiva elevata, quindi il modello viene elaborato più velocemente. Lo svantaggio è il fatto che non è possibile garantire un ordine e questa potrebbe non essere la condizione migliore per un ambiente di produzione.

Dipendenze

Nel contesto dell'elemento copy è necessario indicare alla risorsa con la dipendenza la sezione di cui è in attesa. Per ottenere questa dipendenza, fare riferimento alla stessa usando il nome con il codice JSON seguente:

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

Si noti che l'elemento copy ha una proprietà name con il valore storagecopy. La risorsa dipendente, un account di archiviazione, è in attesa del completamento dell'operazione dell'elemento copy. Questa operazione è espressa da "dependsOn": ["storagecopy"].

Il modello di ARM passa quindi a una modalità di distribuzione in sequenza tra queste due risorse. Potrebbe influire sulla velocità effettiva della distribuzione, ma è stata espressa l'intenzione di seguire un determinato ordine di distribuzione e questo ora ha la precedenza.