Definir a ordem de implementação dos recursos nos modelos do ARM

Ao implementar recursos, poderá ter de se certificar de que existem alguns recursos antes de outros recursos. Por exemplo, precisa de um SERVIDOR SQL lógico antes de implementar uma base de dados. Esta relação é estabelecida ao marcar um recurso como dependente do outro recurso. Utilize o dependsOn elemento para definir uma dependência explícita. Utilize as funções de referência ou lista para definir uma dependência implícita.

O Azure Resource Manager avalia as dependências entre recursos e implementa-as na respetiva ordem dependente. Quando os recursos não são dependentes entre si, o Resource Manager implementa-os em paralelo. Só precisa de definir dependências para recursos implementados no mesmo modelo.

Dica

Recomendamos o Bicep porque oferece as mesmas capacidades que os modelos do ARM e a sintaxe é mais fácil de utilizar. Para saber mais, veja Dependências de recursos.

dependsOn

No modelo de Resource Manager do Azure (modelo arm), o dependsOn elemento permite-lhe definir um recurso como dependente de um ou mais recursos. O valor é uma matriz JSON (JavaScript Object Notation) de cadeias, cada uma das quais é um nome de recurso ou ID. A matriz pode incluir recursos que são implementados condicionalmente. Quando um recurso condicional não é implementado, o Azure Resource Manager remove-o automaticamente das dependências necessárias.

O exemplo seguinte mostra uma interface de rede que depende de uma rede virtual, grupo de segurança de rede e endereço IP público. Para obter o modelo completo, veja o modelo de início rápido de uma VM do 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'))]"
  ],
  ...
}

Com languageVersion 2.0, utilize o nome simbólico do recurso em dependsOn matrizes. Por exemplo:

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

Embora possa estar inclinado a utilizar dependsOn para mapear relações entre os seus recursos, é importante compreender por que motivo o está a fazer. Por exemplo, para documentar a forma como os recursos estão interligados, dependsOn não é a abordagem certa. Após a implementação, o recurso não retém dependências de implementação nas respetivas propriedades, pelo que não existem comandos ou operações que lhe permitam ver dependências. Definir dependências desnecessárias atrasa o tempo de implementação porque Resource Manager não conseguem implementar esses recursos em paralelo.

Recursos subordinados

Uma dependência de implementação implícita não é criada automaticamente entre um recurso subordinado e o recurso principal. Se precisar de implementar o recurso subordinado após o recurso principal, defina a dependsOn propriedade.

O exemplo seguinte mostra um SERVIDOR SQL lógico e uma base de dados. Repare que é definida uma dependência explícita entre a base de dados e o servidor, mesmo que a base de dados seja um subordinado do servidor.

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

Para obter o modelo completo, veja o modelo de início rápido para SQL do Azure Base de Dados.

funções de referência e lista

A função de referência permite que uma expressão deriva o respetivo valor a partir de outros pares de nomes JSON e de valores ou recursos de runtime. As funções list* devolvem valores para um recurso de uma operação de lista.

As expressões de referência e lista declaram implicitamente que um recurso depende de outro. Sempre que possível, utilize uma referência implícita para evitar adicionar uma dependência desnecessária.

Para impor uma dependência implícita, veja o recurso por nome e não o ID do recurso. Se transmitir o ID do recurso para as funções de referência ou lista, não será criada uma referência implícita.

O formato geral da reference função é:

reference('resourceName').propertyPath

O formato geral da listKeys função é:

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

No exemplo seguinte, um ponto final da CDN depende explicitamente do perfil da CDN e depende implicitamente de uma aplicação Web.

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

Para saber mais, veja função de referência.

Depender de recursos num ciclo

Para implementar recursos que dependem de recursos num ciclo de cópia, tem duas opções. Pode definir uma dependência em recursos individuais no ciclo ou em todo o ciclo.

Nota

Para a maioria dos cenários, deve definir a dependência de recursos individuais no ciclo de cópia. Só depende de todo o ciclo quando precisar que todos os recursos no ciclo existam antes de criar o recurso seguinte. Definir a dependência em todo o ciclo faz com que o gráfico de dependências se expanda significativamente, especialmente se esses recursos em ciclo dependerem de outros recursos. As dependências expandidas dificultam a conclusão eficiente da implementação.

O exemplo seguinte mostra como implementar várias máquinas virtuais. O modelo cria o mesmo número de interfaces de rede. Cada máquina virtual depende de uma interface de rede, em vez de todo o 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"
          }
        }
      ]
    },
    ...
  }
}

O exemplo seguinte mostra como implementar três contas de armazenamento antes de implementar a máquina virtual. Tenha em atenção que o copy elemento está name definido como storagecopy e o dependsOn elemento da máquina virtual também está definido como 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"],
      ...
    }
  ]
}

Os nomes simbólicos podem ser utilizados em dependsOn matrizes. Se um nome simbólico for para um ciclo de cópia, todos os recursos no ciclo são adicionados como dependências. O exemplo anterior pode ser escrito como o seguinte JSON. No exemplo, myVM depende de todas as contas de armazenamento no 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"],
      ...
    }
  }
}

Dependências circulares

Resource Manager identifica dependências circulares durante a validação do modelo. Se receber um erro de uma dependência circular, avalie o modelo para ver se podem ser removidas dependências. Se a remoção de dependências não funcionar, pode evitar dependências circulares ao mover algumas operações de implementação para recursos subordinados. Implemente os recursos subordinados após os recursos que têm a dependência circular. Por exemplo, suponha que está a implementar duas máquinas virtuais, mas tem de definir propriedades em cada uma que se refira à outra. Pode implementá-los pela seguinte ordem:

  1. vm1
  2. vm2
  3. A extensão na vm1 depende da vm1 e da vm2. A extensão define os valores na vm1 que obtém da vm2.
  4. A extensão na vm2 depende da vm1 e da vm2. A extensão define os valores na vm2 que obtém da vm1.

Para obter informações sobre como avaliar a ordem de implementação e resolver erros de dependência, veja Resolver erros comuns de implementação do Azure com o Azure Resource Manager.

Passos seguintes