Distribuire più istanze di una risorsa o di una proprietà nei modelli di Azure Resource ManagerDeploy multiple instances of a resource or property in Azure Resource Manager templates

Questo argomento illustra come eseguire un'iterazione del modello di Azure Resource Manager per creare più istanze di una risorsa o più istanze di una proprietà in una risorsa.This topic shows you how to iterate in your Azure Resource Manager template to create multiple instances of a resource, or multiple instances of a property on a resource.

Se è necessario aggiungere una logica al modello per poter specificare se una risorsa è stata distribuita, vedere Distribuire una risorsa in modo condizionale.If you need to add logic to your template that enables you to specify whether a resource is deployed, see Conditionally deploy resource.

Per un esempio di creazione di più elementi in una variabile di matrice, vedere Variabili.For an example of creating multiple elements in an array variable, see Variables.

Iterazione delle risorseResource iteration

Per creare più istanze di un tipo di risorsa, aggiungere un elemento copy al tipo di risorsa.To create multiple instances of a resource type, add a copy element to the resource type. Nell'elemento copy si specifica il numero di iterazioni e un nome per questo ciclo.In the copy element, you specify the number of iterations and a name for this loop. Il valore del conteggio deve essere un numero intero positivo e non può essere maggiore di 800.The count value must be a positive integer and cannot exceed 800. Resource Manager crea le risorse in parallelo.Resource Manager creates the resources in parallel. Pertanto l'ordine di creazione non è garantito.Therefore, the order in which they are created is not guaranteed. Per creare risorse iterate in sequenza, vedere Copia seriale.To create iterated resources in sequence, see Serial copy.

La risorsa da ricreare più volte assume il formato seguente:The resource to create multiple times takes the following format:

{
    "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "resources": [
        {
            "apiVersion": "2016-01-01",
            "type": "Microsoft.Storage/storageAccounts",
            "name": "[concat(copyIndex(),'storage', uniqueString(resourceGroup().id))]",
            "location": "[resourceGroup().location]",
            "sku": {
                "name": "Standard_LRS"
            },
            "kind": "Storage",
            "properties": {},
            "copy": {
                "name": "storagecopy",
                "count": 3
            }
        }
    ],
    "outputs": {}
}

Si noti che il nome di ogni risorsa include la funzione copyIndex() che restituisce l'iterazione corrente nel ciclo.Notice that the name of each resource includes the copyIndex() function, which returns the current iteration in the loop. copyIndex() è in base zero.copyIndex() is zero-based. Quindi l'esempio seguente:So, the following example:

"name": "[concat('storage', copyIndex())]",

Crea questi nomi:Creates these names:

  • storage0storage0
  • storage1storage1
  • storage2storage2.

Per eseguire l'offset del valore di indice, è possibile passare un valore nella funzione copyIndex().To offset the index value, you can pass a value in the copyIndex() function. Il numero di iterazioni da eseguire viene comunque specificato nell'elemento copia, ma il valore di copyIndex è compensato dal valore specificato.The number of iterations to perform is still specified in the copy element, but the value of copyIndex is offset by the specified value. Quindi l'esempio seguente:So, the following example:

"name": "[concat('storage', copyIndex(1))]",

Crea questi nomi:Creates these names:

  • storage1storage1
  • storage2storage2
  • storage3storage3

L'operazione di copia è utile quando si lavora con le matrici in quanto è possibile iterare ogni elemento della matrice.The copy operation is helpful when working with arrays because you can iterate through each element in the array. Usare la funzione length nella matrice per specificare il conteggio per le iterazioni e copyIndex per recuperare l'indice corrente nella matrice.Use the length function on the array to specify the count for iterations, and copyIndex to retrieve the current index in the array. Quindi l'esempio seguente:So, the following example:

"parameters": { 
  "org": { 
     "type": "array", 
     "defaultValue": [ 
         "contoso", 
         "fabrikam", 
         "coho" 
      ] 
  }
}, 
"resources": [ 
  { 
      "name": "[concat('storage', parameters('org')[copyIndex()])]", 
      "copy": { 
         "name": "storagecopy", 
         "count": "[length(parameters('org'))]" 
      }, 
      ...
  } 
]

Crea questi nomi:Creates these names:

  • storagecontosostoragecontoso
  • storagefabrikamstoragefabrikam
  • storagecohostoragecoho

Copia serialeSerial copy

Quando si usa l'elemento di copia per creare più istanze di un tipo di risorsa, Resource Manager distribuisce queste istanze in parallelo per impostazione predefinita.When you use the copy element to create multiple instances of a resource type, Resource Manager, by default, deploys those instances in parallel. Tuttavia è consigliabile specificare che le risorse vengano distribuite in sequenza.However, you may want to specify that the resources are deployed in sequence. Ad esempio, quando si aggiorna un ambiente di produzione, è consigliabile sfalsare gli aggiornamenti per aggiornarne solo un determinato numero in un dato momento.For example, when updating a production environment, you may want to stagger the updates so only a certain number are updated at any one time.

Resource Manager fornisce proprietà sull'elemento di copia che consentono di distribuire più istanze in modo seriale.Resource Manager provides properties on the copy element that enable you to serially deploy multiple instances. Nell'elemento di copia impostare mode su serial e batchSize sul numero di istanze da distribuire contemporaneamente.In the copy element, set mode to serial and batchSize to the number of instances to deploy at a time. Con la modalità seriale, Resource Manager crea una dipendenza da istanze precedenti nel ciclo in modo un batch venga avviato solo dopo il completamento del batch precedente.With serial mode, Resource Manager creates a dependency on earlier instances in the loop, so it does not start one batch until the previous batch completes.

"copy": {
    "name": "iterator",
    "count": "[parameters('numberToDeploy')]",
    "mode": "serial",
    "batchSize": 2
},

La proprietà mode accetta anche parallel, che è il valore predefinito.The mode property also accepts parallel, which is the default value.

Per testare la copia seriale senza creare risorse effettive, usare il modello seguente che distribuisce i modelli annidati vuoti:To test serial copy without creating actual resources, use the following template that deploys empty nested templates:

{
  "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "numberToDeploy": {
      "type": "int",
      "minValue": 2,
      "defaultValue": 5
    }
  },
  "resources": [
    {
      "apiVersion": "2015-01-01",
      "type": "Microsoft.Resources/deployments",
      "name": "[concat('loop-', copyIndex())]",
      "copy": {
        "name": "iterator",
        "count": "[parameters('numberToDeploy')]",
        "mode": "serial",
        "batchSize": 1
      },
      "properties": {
        "mode": "Incremental",
        "template": {
          "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
          "contentVersion": "1.0.0.0",
          "parameters": {},
          "variables": {},
          "resources": [],
          "outputs": {
          }
        }
      }
    }
  ],
  "outputs": {
  }
}

Nella cronologia di distribuzione notare che le distribuzioni annidate vengono elaborate in sequenza.In the deployment history, notice that the nested deployments are processed in sequence.

distribuzione seriale

Per uno scenario più realistico, l'esempio seguente consente di distribuire due istanze alla volta di una VM Linux da un modello annidato:For a more realistic scenario, the following example deploys two instances at a time of a Linux VM from a nested template:

{
    "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "adminUsername": {
            "type": "string",
            "metadata": {
                "description": "User name for the Virtual Machine."
            }
        },
        "adminPassword": {
            "type": "securestring",
            "metadata": {
                "description": "Password for the Virtual Machine."
            }
        },
        "dnsLabelPrefix": {
            "type": "string",
            "metadata": {
                "description": "Unique DNS Name for the Public IP used to access the Virtual Machine."
            }
        },
        "ubuntuOSVersion": {
            "type": "string",
            "defaultValue": "16.04.0-LTS",
            "allowedValues": [
                "12.04.5-LTS",
                "14.04.5-LTS",
                "15.10",
                "16.04.0-LTS"
            ],
            "metadata": {
                "description": "The Ubuntu version for the VM. This will pick a fully patched image of this given Ubuntu version."
            }
        }
    },
    "variables": {
        "templatelink": "https://raw.githubusercontent.com/rjmax/Build2017/master/Act1.TemplateEnhancements/Chapter03.LinuxVM.json"
    },
    "resources": [
        {
            "apiVersion": "2015-01-01",
            "name": "[concat('nestedDeployment',copyIndex())]",
            "type": "Microsoft.Resources/deployments",
            "copy": {
                "name": "myCopySet",
                "count": 4,
                "mode": "serial",
                "batchSize": 2
            },
            "properties": {
                "mode": "Incremental",
                "templateLink": {
                    "uri": "[variables('templatelink')]",
                    "contentVersion": "1.0.0.0"
                },
                "parameters": {
                    "adminUsername": {
                        "value": "[parameters('adminUsername')]"
                    },
                    "adminPassword": {
                        "value": "[parameters('adminPassword')]"
                    },
                    "dnsLabelPrefix": {
                        "value": "[parameters('dnsLabelPrefix')]"
                    },
                    "ubuntuOSVersion": {
                        "value": "[parameters('ubuntuOSVersion')]"
                    },
                    "index":{
                        "value": "[copyIndex()]"
                    }
                }
            }
        }
    ]
}

Iterazione delle proprietàProperty iteration

Per creare più valori per una proprietà in una risorsa, aggiungere una matrice copy nell'elemento properties.To create multiple values for a property on a resource, add a copy array in the properties element. Questa matrice contiene oggetti ai quali sono associate le proprietà riportate di seguito.This array contains objects, and each object has the following properties:

  • name: il nome della proprietà per la quale creare più valoriname - the name of the property to create multiple values for
  • count: il numero di valori da crearecount - the number of values to create
  • input: un oggetto che contiene i valori da assegnare alla proprietàinput - an object that contains the values to assign to the property

Nell'esempio seguente viene illustrato come applicare copy alla proprietà dataDisks in una macchina virtuale:The following example shows how to apply copy to the dataDisks property on a virtual machine:

{
  "name": "examplevm",
  "type": "Microsoft.Compute/virtualMachines",
  "apiVersion": "2017-03-30",
  "properties": {
    "storageProfile": {
      "copy": [{
          "name": "dataDisks",
          "count": 3,
          "input": {
              "lun": "[copyIndex('dataDisks')]",
              "createOption": "Empty",
              "diskSizeGB": "1023"
          }
      }],
      ...

Si noti che quando si usa copyIndex all'interno di un'iterazione di proprietà, è necessario specificare il nome dell'iterazione.Notice that when using copyIndex inside a property iteration, you must provide the name of the iteration. Non è necessario specificarlo quando l'elemento viene usato con un'iterazione di risorse.You do not have to provide the name when used with resource iteration.

Resource Manager espande la matrice copy durante la distribuzione.Resource Manager expands the copy array during deployment. Il nome della matrice diventa il nome della proprietà.The name of the array becomes the name of the property. I valori di input diventano le proprietà dell'oggetto.The input values become the object properties. Il modello distribuito diventa:The deployed template becomes:

{
  "name": "examplevm",
  "type": "Microsoft.Compute/virtualMachines",
  "apiVersion": "2017-03-30",
  "properties": {
    "storageProfile": {
      "dataDisks": [
          {
              "lun": 0,
              "createOption": "Empty",
              "diskSizeGB": "1023"
          },
          {
              "lun": 1,
              "createOption": "Empty",
              "diskSizeGB": "1023"
          },
          {
              "lun": 2,
              "createOption": "Empty",
              "diskSizeGB": "1023"
          }
      }],
      ...

È possibile usare l'iterazione di risorse e di proprietà contemporaneamente.You can use resource and property iteration together. Fare riferimento all'iterazione di proprietà con il nome.Reference the property iteration by name.

{
    "type": "Microsoft.Network/virtualNetworks",
    "name": "[concat(parameters('vnetname'), copyIndex())]",
    "apiVersion": "2016-06-01",
    "copy":{
        "count": 2,
        "name": "vnetloop"
    },
    "location": "[resourceGroup().location]",
    "properties": {
        "addressSpace": {
            "addressPrefixes": [
                "[parameters('addressPrefix')]"
            ]
        },
        "copy": [
            {
                "name": "subnets",
                "count": 2,
                "input": {
                    "name": "[concat('subnet-', copyIndex('subnets'))]",
                    "properties": {
                        "addressPrefix": "[variables('subnetAddressPrefix')[copyIndex('subnets')]]"
                    }
                }
            }
        ]
    }
}

Per ogni risorsa è possibile includere nelle proprietà un solo elemento copy.You can only include one copy element in the properties for each resource. Per specificare un ciclo di iterazione per più proprietà, definire più oggetti nella matrice di copia.To specify an iteration loop for more than one property, define multiple objects in the copy array. Ogni oggetto viene iterato separatamente.Each object is iterated separately. Ad esempio, per creare più istanze di entrambe le proprietà frontendIPConfigurations e loadBalancingRules in un bilanciamento del carico, definire entrambi gli oggetti in un singolo elemento copy:For example, to create multiple instances of both the frontendIPConfigurations property and the loadBalancingRules property on a load balancer, define both objects in a single copy element:

{
    "name": "[variables('loadBalancerName')]",
    "type": "Microsoft.Network/loadBalancers",
    "properties": {
        "copy": [
          {
              "name": "frontendIPConfigurations",
              "count": 2,
              "input": {
                  "name": "[concat('loadBalancerFrontEnd', copyIndex('frontendIPConfigurations', 1))]",
                  "properties": {
                      "publicIPAddress": {
                          "id": "[variables(concat('publicIPAddressID', copyIndex('frontendIPConfigurations', 1)))]"
                      }
                  }
              }
          },
          {
              "name": "loadBalancingRules",
              "count": 2,
              "input": {
                  "name": "[concat('LBRuleForVIP', copyIndex('loadBalancingRules', 1))]",
                  "properties": {
                      "frontendIPConfiguration": {
                          "id": "[variables(concat('frontEndIPConfigID', copyIndex('loadBalancingRules', 1)))]"
                      },
                      "backendAddressPool": {
                          "id": "[variables('lbBackendPoolID')]"
                      },
                      "protocol": "tcp",
                      "frontendPort": "[variables(concat('frontEndPort' copyIndex('loadBalancingRules', 1))]",
                      "backendPort": "[variables(concat('backEndPort' copyIndex('loadBalancingRules', 1))]",
                      "probe": {
                          "id": "[variables('lbProbeID')]"
                      }
                  }
              }
          }
        ],
        ...
    }
}

In base alle risorse in un cicloDepend on resources in a loop

L'elemento dependsOn consente di specificare che una risorsa sia distribuita dopo un'altra.You specify that a resource is deployed after another resource by using the dependsOn element. Per distribuire una risorsa che dipende dalla raccolta di risorse in un ciclo, usare il nome del ciclo di copia nell'elemento dependsOn.To deploy a resource that depends on the collection of resources in a loop, provide the name of the copy loop in the dependsOn element. L'esempio seguente illustra come distribuire tre account di archiviazione prima di distribuire la macchina virtuale.The following example shows how to deploy three storage accounts before deploying the Virtual Machine. La definizione completa di macchina virtuale non viene visualizzata.The full Virtual Machine definition is not shown. Si noti che la copia ha la proprietà name impostata su storagecopy e l'elemento dependsOn per le macchine virtuali impostato su storagecopy.Notice that the copy element has name set to storagecopy and the dependsOn element for the Virtual Machines is also set to storagecopy.

{
    "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {},
    "resources": [
        {
            "apiVersion": "2016-01-01",
            "type": "Microsoft.Storage/storageAccounts",
            "name": "[concat(copyIndex(),'storage', uniqueString(resourceGroup().id))]",
            "location": "[resourceGroup().location]",
            "sku": {
                "name": "Standard_LRS"
            },
            "kind": "Storage",
            "properties": {},
            "copy": {
                "name": "storagecopy",
                "count": 3
            }
        },
        {
            "apiVersion": "2015-06-15", 
            "type": "Microsoft.Compute/virtualMachines", 
            "name": "[concat('VM', uniqueString(resourceGroup().id))]",  
            "dependsOn": ["storagecopy"],
            ...
        }
    ],
    "outputs": {}
}

Creare più istanze di una risorsa figlioCreate multiple instances of a child resource

Non è possibile usare un ciclo di copia per una risorsa figlio.You cannot use a copy loop for a child resource. Per creare più istanze di una risorsa cosiddetta "annidata" all'interno di un'altra risorsa, è invece necessario creare tale risorsa come una risorsa di livello superiore.To create multiple instances of a resource that you typically define as nested within another resource, you must instead create that resource as a top-level resource. La relazione con la risorsa padre si definisce con le proprietà type e name.You define the relationship with the parent resource through the type and name properties.

Si supponga, ad esempio, di definire in genere un set di dati come una risorsa figlio all'interno di una data factory.For example, suppose you typically define a dataset as a child resource within a data factory.

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

Per creare più istanze di un set di dati, spostarlo all'esterno della data factory.To create multiple instances of data sets, move it outside of the data factory. Il set di dati deve essere sullo stesso livello della data factory, di cui è comunque una risorsa figlio.The dataset must be at the same level as the data factory, but it is still a child resource of the data factory. La relazione fra set di dati e data factory viene mantenuta con le proprietà type e name.You preserve the relationship between data set and data factory through the type and name properties. Poiché non è possibile dedurre il tipo dalla sua posizione nel modello, è necessario specificarne il nome completo nel formato: {resource-provider-namespace}/{parent-resource-type}/{child-resource-type}.Since type can no longer be inferred from its position in the template, you must provide the fully qualified type in the format: {resource-provider-namespace}/{parent-resource-type}/{child-resource-type}.

Per stabilire una relazione padre/figlio con un'istanza della data factory, specificare il nome del set di dati che include il nome della risorsa padre.To establish a parent/child relationship with an instance of the data factory, provide a name for the data set that includes the parent resource name. Usare il formato: {parent-resource-name}/{child-resource-name}.Use the format: {parent-resource-name}/{child-resource-name}.

Nell'esempio seguente viene descritta l'implementazione:The following example shows the implementation:

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

Distribuire una risorsa in modo condizionaleConditionally deploy resource

Per specificare se una risorsa è stata distribuita, usare l'elemento condition.To specify whether a resource is deployed, use the condition element. Il valore di questo elemento restituisce true o false.The value for this element resolves to true or false. Quando il valore è true, la risorsa viene distribuita.When the value is true, the resource is deployed. Quando il valore è false, la risorsa non viene distribuita.When the value is false, the resource is not deployed. Per indicare, ad esempio, se viene distribuito un nuovo account di archiviazione o se ne viene usato uno esistente, specificare:For example, to specify whether a new storage account is deployed or an existing storage account is used, use:

{
    "condition": "[equals(parameters('newOrExisting'),'new')]",
    "type": "Microsoft.Storage/storageAccounts",
    "name": "[variables('storageAccountName')]",
    "apiVersion": "2017-06-01",
    "location": "[resourceGroup().location]",
    "sku": {
        "name": "[variables('storageAccountType')]"
    },
    "kind": "Storage",
    "properties": {}
}

Per un esempio di utilizzo di una risorsa nuova o esistente, vedere Modello di condizione nuovo o esistente.For an example of using a new or existing resource, see New or existing condition template.

Per un esempio di utilizzo di una password o di una chiave SSH per la distribuzione di una macchina virtuale, vedere Modello di condizione basato su nome utente o SSH.For an example of using a password or SSH key to deploy virtual machine, see Username or SSH condition template.

Passaggi successiviNext steps