De volgorde voor het implementeren van resources in ARM-sjablonen definiëren

Bij het implementeren van resources moet u er mogelijk voor zorgen dat sommige resources vóór andere resources bestaan. U hebt bijvoorbeeld een logische SQL-server nodig voordat u een database implementeert. U brengt deze relatie tot stand door één resource te markeren als afhankelijk van de andere resource. Gebruik het dependsOn -element om een expliciete afhankelijkheid te definiëren. Gebruik de verwijzings- of lijstfuncties om een impliciete afhankelijkheid te definiëren.

Azure Resource Manager evalueert de afhankelijkheden tussen resources en implementeert deze in de afhankelijke volgorde. Als resources niet van elkaar afhankelijk zijn, worden deze door Resource Manager parallel geïmplementeerd. U hoeft alleen afhankelijkheden te definiëren voor resources die in dezelfde sjabloon zijn geïmplementeerd.

Tip

We raden Bicep aan omdat het dezelfde mogelijkheden biedt als ARM-sjablonen en de syntaxis eenvoudiger te gebruiken is. Zie resourceafhankelijkheden voor meer informatie.

dependsOn

Binnen uw ARM-sjabloon (Azure Resource Manager) kunt u met het dependsOn element één resource definiëren als afhankelijk van een of meer resources. De waarde ervan is een JSON-matrix (JavaScript Object Notation) met tekenreeksen, die elk een resourcenaam of id zijn. De matrix kan resources bevatten die voorwaardelijk zijn geïmplementeerd. Wanneer een voorwaardelijke resource niet wordt geïmplementeerd, verwijdert Azure Resource Manager deze automatisch uit de vereiste afhankelijkheden.

In het volgende voorbeeld ziet u een netwerkinterface die afhankelijk is van een virtueel netwerk, netwerkbeveiligingsgroep en openbaar IP-adres. Zie de quickstart-sjabloon voor een Linux-VM voor de volledige sjabloon.

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

Gebruik met languageVersion 2.0 de symbolische naam van de resource in dependsOn matrices. Bijvoorbeeld:

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

Hoewel u misschien geneigd bent om dependsOn relaties tussen uw resources toe te wijzen, is het belangrijk om te begrijpen waarom u dit doet. Het is bijvoorbeeld niet de juiste methode om vast te leggen hoe resources onderling zijn verbonden dependsOn . Na de implementatie behoudt de resource geen implementatieafhankelijkheden in de eigenschappen, dus er zijn geen opdrachten of bewerkingen waarmee u afhankelijkheden kunt zien. Het instellen van onnodige afhankelijkheden vertraagt de implementatietijd omdat Resource Manager deze resources niet parallel kunt implementeren.

Onderliggende resources

Er wordt niet automatisch een impliciete implementatieafhankelijkheid gemaakt tussen een onderliggende resource en de bovenliggende resource. Als u de onderliggende resource na de bovenliggende resource wilt implementeren, stelt u de dependsOn eigenschap in.

In het volgende voorbeeld ziet u een logische SQL-server en -database. U ziet dat er een expliciete afhankelijkheid is gedefinieerd tussen de database en de server, ook al is de database een onderliggend element van de 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'))]"
        ]
      }
    ]
  }
]

Zie Quickstart-sjabloon voor Azure SQL Database voor de volledige sjabloon.

verwijzings- en lijstfuncties

Met de verwijzingsfunctie kan een expressie de waarde afleiden van andere JSON-naam- en waardeparen of runtime-resources. De lijst*-functies retourneren waarden voor een resource uit een lijstbewerking.

Verwijzings- en lijstexpressies declareren impliciet dat één resource afhankelijk is van een andere resource. Gebruik indien mogelijk een impliciete verwijzing om onnodige afhankelijkheid te voorkomen.

Als u een impliciete afhankelijkheid wilt afdwingen, raadpleegt u de resource op naam, niet op resource-id. Als u de resource-id doorgeeft aan de verwijzings- of lijstfuncties, wordt er geen impliciete verwijzing gemaakt.

De algemene indeling van de reference functie is:

reference('resourceName').propertyPath

De algemene indeling van de listKeys functie is:

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

In het volgende voorbeeld is een CDN-eindpunt expliciet afhankelijk van het CDN-profiel en impliciet afhankelijk van een web-app.

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

Zie referentiefunctie voor meer informatie.

Afhankelijk van resources in een lus

Als u resources wilt implementeren die afhankelijk zijn van resources in een kopieerlus, hebt u twee opties. U kunt een afhankelijkheid instellen van afzonderlijke resources in de lus of van de hele lus.

Notitie

Voor de meeste scenario's moet u de afhankelijkheid van afzonderlijke resources binnen de kopieerlus instellen. Alleen afhankelijk van de hele lus wanneer u alle resources in de lus wilt laten bestaan voordat u de volgende resource maakt. Als u de afhankelijkheid van de hele lus instelt, wordt de grafiek met afhankelijkheden aanzienlijk uitgebreid, met name als deze resources met een lus afhankelijk zijn van andere resources. De uitgebreide afhankelijkheden maken het moeilijk om de implementatie efficiënt te voltooien.

In het volgende voorbeeld ziet u hoe u meerdere virtuele machines implementeert. Met de sjabloon wordt hetzelfde aantal netwerkinterfaces gemaakt. Elke virtuele machine is afhankelijk van één netwerkinterface in plaats van de hele lus.

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

In het volgende voorbeeld ziet u hoe u drie opslagaccounts implementeert voordat u de virtuele machine implementeert. U ziet dat het copy element is name ingesteld op storagecopy en dat het dependsOn element voor de virtuele machine ook is ingesteld op 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"],
      ...
    }
  ]
}

Symbolische namen kunnen worden gebruikt in dependsOn matrices. Als een symbolische naam voor een kopieerlus is, worden alle resources in de lus toegevoegd als afhankelijkheden. Het voorgaande voorbeeld kan worden geschreven als de volgende JSON. In het voorbeeld is myVM afhankelijk van alle opslagaccounts in de myStorages-lus .

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

Kringafhankelijkheden

Resource Manager identificeert kringafhankelijkheden tijdens sjabloonvalidatie. Als u een foutbericht ontvangt voor een kringafhankelijkheid, evalueert u de sjabloon om te zien of er afhankelijkheden kunnen worden verwijderd. Als het verwijderen van afhankelijkheden niet werkt, kunt u kringafhankelijkheden voorkomen door sommige implementatiebewerkingen naar onderliggende resources te verplaatsen. Implementeer de onderliggende resources na de resources die de kringafhankelijkheid hebben. Stel dat u twee virtuele machines implementeert, maar dat u eigenschappen moet instellen voor elke virtuele machine die naar de andere verwijst. U kunt ze in de volgende volgorde implementeren:

  1. vm1
  2. vm2
  3. De extensie op vm1 is afhankelijk van vm1 en vm2. De extensie stelt waarden in op vm1 die worden opgehaald uit vm2.
  4. De extensie op vm2 is afhankelijk van vm1 en vm2. De extensie stelt waarden in op vm2 die worden opgehaald van vm1.

Zie Veelvoorkomende azure-implementatiefouten oplossen met Azure Resource Manager voor informatie over het beoordelen van de implementatievolgorde en het oplossen van afhankelijkheidsfouten.

Volgende stappen