Definire l'ordine di distribuzione delle risorse nei modelli di ARM

Quando si distribuiscono le risorse, potrebbe essere necessario assicurarsi che alcune risorse esistano prima di altre risorse. Ad esempio, è necessario un server SQL logico prima di distribuire un database. Per definire questa relazione, si contrassegna una risorsa come dipendente dall'altra risorsa. Usare l'elemento dependsOn per definire una dipendenza esplicita. Usare le funzioni riferimento o elenco per definire una dipendenza implicita.

Azure Resource Manager valuta le dipendenze tra le risorse e le distribuisce in base all'ordine di dipendenza. Quando le risorse non sono interdipendenti, Resource Manager le distribuisce in parallelo. La definizione delle dipendenze è necessaria solo per le risorse distribuite nello stesso modello.

Suggerimento

È consigliabile Bicep perché offre le stesse funzionalità dei modelli di ARM e la sintassi è più semplice da usare. Per ulteriori informazioni, vedere dipendenze delle risorse.

dependsOn

All'interno del modello di Azure Resource Manager (modello di ARM), l'elemento dependsOn consente di definire una risorsa come dipendente da una o più risorse. Il valore è una matrice JSON (JavaScript Object Notation) di stringhe, ognuna delle quali è un nome di risorsa o un ID. La matrice può includere risorse che vengono distribuite in modo condizionale. Quando una risorsa condizionale non viene distribuita, Azure Resource Manager la rimuove automaticamente dalle dipendenze necessarie.

L'esempio seguente mostra un'interfaccia di rete che dipende da una rete virtuale, da un gruppo di sicurezza di rete e da un indirizzo IP pubblico. Per il modello completo, vedere il modello di avvio rapido per una macchina virtuale Linux.

{
  "type": "Microsoft.Network/networkInterfaces",
  "apiVersion": "2022-07-01",
  "name": "[variables('networkInterfaceName')]",
  "location": "[parameters('location')]",
  "dependsOn": [
    "[resourceId('Microsoft.Network/networkSecurityGroups/', parameters('networkSecurityGroupName'))]",
    "[resourceId('Microsoft.Network/virtualNetworks/', parameters('virtualNetworkName'))]",
    "[resourceId('Microsoft.Network/publicIpAddresses/', variables('publicIpAddressName'))]"
  ],
  ...
}

Con languageVersion 2.0, usare il nome simbolico della risorsa nelle matrici dependsOn . Ad esempio:

{
  "$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]"
    }
  },
  "resources": {
    "myStorage": {
      "type": "Microsoft.Storage/storageAccounts",
      "apiVersion": "2023-01-01",
      "name": "[format('storage{0}', uniqueString(resourceGroup().id))]",
      "location": "[parameters('location')]",
      "sku": {
        "name": "Standard_LRS"
      },
      "kind": "StorageV2"
    },
    "myVm": {
      "type": "Microsoft.Compute/virtualMachines",
      "apiVersion": "2023-03-01",
      "name": "[format('vm{0}', uniqueString(resourceGroup().id))]",
      "location": "[parameters('location')]",
      "dependsOn": [
        "myStorage"
      ],
      ...
    }
  }
}

Anche se si potrebbe essere propensi a usare dependsOn per mappare le relazioni tra le risorse, è importante comprendere il motivo per cui si esegue tale operazione. Per documentare come le risorse sono interconnesse, dependsOn non rappresenta l'approccio corretto. Dopo la distribuzione, la risorsa non mantiene le dipendenze di distribuzione nelle sue proprietà, quindi non esistono comandi o operazioni che consentano di visualizzare le dipendenze. Impostare dipendenze non necessarie rallenta il tempo di distribuzione perché Resource Manager non è in grado di distribuire tali risorse in parallelo.

Risorse figlio

Una dipendenza di distribuzione implicita non viene creata automaticamente tra una risorsa figlio e la risorsa padre. Se è necessario distribuire la risorsa figlio dopo la risorsa padre, impostare la proprietà dependsOn .

L'esempio seguente mostra un database e un server SQL logico. Si noti che una dipendenza esplicita viene definita tra il database e il server, anche se il database è un elemento figlio del server.

"resources": [
  {
    "type": "Microsoft.Sql/servers",
    "apiVersion": "2022-05-01-preview",
    "name": "[parameters('serverName')]",
    "location": "[parameters('location')]",
    "properties": {
      "administratorLogin": "[parameters('administratorLogin')]",
      "administratorLoginPassword": "[parameters('administratorLoginPassword')]"
    },
    "resources": [
      {
        "type": "databases",
        "apiVersion": "2022-05-01-preview",
        "name": "[parameters('sqlDBName')]",
        "location": "[parameters('location')]",
        "sku": {
          "name": "Standard",
          "tier": "Standard"
          },
        "dependsOn": [
          "[resourceId('Microsoft.Sql/servers', parameters('serverName'))]"
        ]
      }
    ]
  }
]

Per il modello completo, vedere il modello di avvio rapido per il database SQL di Azure.

funzioni reference e list

La funzione di riferimento consente un'espressione per derivare il valore da altri nomi JSON e coppie valore o risorse di runtime. Le funzioni list* restituiscono valori per una risorsa da un'operazione elenco.

Le espressioni di riferimento ed elenco dichiarano in modo implicito che una risorsa dipende da un’altra. Quando possibile, usare un riferimento implicito per evitare di aggiungere una dipendenza non necessaria.

Per implementare una dipendenza implicita, fare riferimento alla risorsa in base al nome, non all'ID risorsa. Se alla funzione reference o list viene passato l'ID risorsa, non viene creato alcun riferimento implicito.

Il formato generico della funzione reference è:

reference('resourceName').propertyPath

Il formato generico della funzione listKeys è:

listKeys('resourceName', 'yyyy-mm-dd')

Nell'esempio seguente, un endpoint della rete CDN dipende in modo esplicito dal profilo CDN e in modo implicito da un'app Web.

{
    "type": "endpoints",
    "apiVersion": "2021-06-01",
    "name": "[variables('endpointName')]",
    "location": "[resourceGroup().location]",
    "dependsOn": [
      "[variables('profileName')]"
    ],
    "properties": {
      "originHostHeader": "[reference(variables('webAppName')).hostNames[0]]",
      ...
    }
    ...
}

Per altre informazioni, vedere la funzione del riferimento.

In base alle risorse in un ciclo

Per distribuire le risorse che dipendono da risorse in un ciclo di copia, sono disponibili due opzioni. È possibile impostare una dipendenza da singole risorse nel ciclo o dall'intero ciclo.

Nota

Per la maggior parte degli scenari, è necessario impostare la dipendenza da singole risorse all'interno del ciclo di copia. Dipende solo dall'intero ciclo quando è necessario che tutte le risorse nel ciclo esistano prima di creare la risorsa successiva. Impostare la dipendenza dall'intero ciclo causa un’espansione significativa del grafico delle dipendenze, soprattutto se tali risorse cicliche dipendono da altre risorse. Le dipendenze espanse rendono difficile il completamento efficiente della distribuzione.

L'esempio seguente mostra come distribuire più macchine virtuali. Il modello crea lo stesso numero di interfacce di rete. Ogni macchina virtuale dipende da un'interfaccia di rete, anziché dall'intero ciclo.

{
  "type": "Microsoft.Network/networkInterfaces",
  "apiVersion": "2022-07-01",
  "name": "[format('{0}-{1}', variables('nicPrefix'), copyIndex())]",
  "location": "[parameters('location')]",
  "copy": {
    "name": "nicCopy",
    "count": "[parameters('vmCount')]"
  },
  ...
},
{
  "type": "Microsoft.Compute/virtualMachines",
  "apiVersion": "2022-11-01",
  "name": "[format('{0}{1}', variables('vmPrefix'), copyIndex())]",
  "location": "[parameters('location')]",
  "dependsOn": [
    "[resourceId('Microsoft.Network/networkInterfaces',format('{0}-{1}', variables('nicPrefix'),copyIndex()))]"
  ],
  "copy": {
    "name": "vmCopy",
    "count": "[parameters('vmCount')]"
  },
  "properties": {
    "networkProfile": {
      "networkInterfaces": [
        {
          "id": "[resourceId('Microsoft.Network/networkInterfaces',format('(0)-(1)', variables('nicPrefix'), copyIndex()))]",
          "properties": {
            "primary": "true"
          }
        }
      ]
    },
    ...
  }
}

L'esempio seguente illustra come distribuire tre account di archiviazione prima di distribuire la macchina virtuale. Si noti che l'elemento copy ha name impostato su storagecopy e anche l'elemento dependsOn per la macchina virtuale è impostato su storagecopy.

{
  "$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": [
    {
      "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",
      "copy": {
        "name": "storagecopy",
        "count": 3
      },
      "properties": {}
    },
    {
      "type": "Microsoft.Compute/virtualMachines",
      "apiVersion": "2022-11-01",
      "name": "[format('VM{0}', uniqueString(resourceGroup().id))]",
      "dependsOn": ["storagecopy"],
      ...
    }
  ]
}

I nomi simbolici possono essere usati nelle matrici dependsOn . Se un nome simbolico è per un ciclo di copia, tutte le risorse nel ciclo vengono aggiunte come dipendenze. L'esempio precedente può essere scritto come il JSON seguente. Nell'esempio, myVM dipende da tutti gli account di archiviazione nel ciclo myStorages .

{
  "$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]"
    }
  },
  "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",
      "copy": {
        "name": "storagecopy",
        "count": 3
      },
      "properties": {}
    },
    "myVM": {
      "type": "Microsoft.Compute/virtualMachines",
      "apiVersion": "2022-11-01",
      "name": "[format('VM{0}', uniqueString(resourceGroup().id))]",
      "dependsOn": ["myStorages"],
      ...
    }
  }
}

Dipendenze circolari

Resource Manager identifica le dipendenze circolari durante la convalida del modello. Se viene visualizzato un errore per una dipendenza circolare, valutare il modello per verificare se è possibile rimuovere eventuali dipendenze. Se la rimozione delle dipendenze non è applicabile, è possibile evitare dipendenze circolari spostando alcune operazioni di distribuzione in risorse figlio. Distribuire le risorse figlio dopo le risorse che hanno la dipendenza circolare. Si supponga, ad esempio, di distribuire due macchine virtuali e che sia necessario impostare in ognuna proprietà che fanno riferimento all'altra. È possibile eseguire la distribuzione nell'ordine seguente:

  1. vm1
  2. vm2
  3. L'estensione in VM 1 dipende da VM 1 e VM 2. L'estensione imposta in VM 1 valori ottenuti da VM 2.
  4. L'estensione in VM 2 dipende da VM 1 e VM 2. L'estensione imposta in VM 2 valori ottenuti da VM 1.

Per informazioni sulla valutazione dell'ordine di distribuzione e la risoluzione degli errori di dipendenza, vedere Risolvere errori comuni durante la distribuzione di risorse in Azure con Azure Resource Manager.

Passaggi successivi