Partilhar via


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

Ao implantar recursos, talvez seja necessário verificar se alguns recursos existem antes de outros recursos. Por exemplo, você precisa de um servidor SQL lógico antes de implantar um banco de dados. Você estabelece essa relação marcando um recurso como dependente do outro. Use o dependsOn elemento para definir uma dependência explícita. Use 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 as implanta em sua ordem dependente. Quando os recursos não são dependentes entre si, o Resource Manager implementa-os em paralelo. Você só precisa definir dependências para recursos que são implantados no mesmo modelo.

Gorjeta

Recomendamos o Bicep porque ele oferece os mesmos recursos que os modelos ARM e a sintaxe é mais fácil de usar. Para saber mais, consulte Dependências de recursos.

dependsOn

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

O exemplo a seguir 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, consulte o modelo de início rápido para uma máquina virtual 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, use 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 você possa estar inclinado a usar dependsOn para mapear relações entre seus recursos, é importante entender por que você está fazendo isso. Por exemplo, documentar como os recursos estão interligados dependsOn não é a abordagem correta. Após a implantação, o recurso não retém dependências de implantação em suas propriedades, portanto, não há comandos ou operações que permitam ver dependências. A definição de dependências desnecessárias diminui o tempo de implantação porque o Gerenciador de Recursos não pode implantar esses recursos em paralelo.

Recursos para crianças

Uma dependência de implantação implícita não é criada automaticamente entre um recurso filho e o recurso pai. Se você precisar implantar o recurso filho após o recurso pai, defina a dependsOn propriedade.

O exemplo a seguir mostra um servidor SQL lógico e um banco de dados. Observe que uma dependência explícita é definida entre o banco de dados e o servidor, mesmo que o banco de dados seja filho 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, consulte Modelo de início rápido para o Banco de Dados SQL do Azure.

funções de referência e lista

A função de referência permite que uma expressão derive seu valor de outros pares de nome e valor JSON ou recursos de tempo de execução. As funções list* retornam 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, use uma referência implícita para evitar adicionar uma dependência desnecessária.

Para impor uma dependência implícita, consulte o recurso pelo nome, não pela ID do recurso. Se você passar o ID do recurso para as funções de referência ou lista, uma referência implícita não será criada.

O formato geral da reference função é:

reference('resourceName').propertyPath

O formato geral da listKeys função é:

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

No exemplo a seguir, um ponto de extremidade CDN depende explicitamente do perfil CDN e, implicitamente, depende de um aplicativo 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, consulte Função de referência.

Dependa de recursos em um loop

Para implantar recursos que dependem de recursos em um loop de cópia, você tem duas opções. Você pode definir uma dependência de recursos individuais no loop ou em todo o loop.

Nota

Para a maioria dos cenários, você deve definir a dependência de recursos individuais dentro do loop de cópia. Dependa apenas de todo o loop quando você precisar que todos os recursos no loop existam antes de criar o próximo recurso. Definir a dependência em todo o loop faz com que o gráfico de dependências se expanda significativamente, especialmente se esses recursos em loop dependerem de outros recursos. As dependências expandidas dificultam a conclusão eficiente da implantação.

O exemplo a seguir mostra como implantar 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 loop.

{
  "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 a seguir mostra como implantar três contas de armazenamento antes de implantar a máquina virtual. Observe que o copy elemento foi name definido como storagecopy e o dependsOn elemento para a 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"],
      ...
    }
  ]
}

Nomes simbólicos podem ser usados em dependsOn matrizes. Se um nome simbólico for para um loop de cópia, todos os recursos no loop serã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 loop 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

O Resource Manager identifica dependências circulares durante a validação do modelo. Se você receber um erro para uma dependência circular, avalie seu modelo para ver se alguma dependência pode ser removida. Se a remoção de dependências não funcionar, você poderá evitar dependências circulares movendo algumas operações de implantação para recursos filho. Implante os recursos filho após os recursos que têm a dependência circular. Por exemplo, suponha que você esteja implantando duas máquinas virtuais, mas deve definir propriedades em cada uma que se referem à outra. Você pode implantá-los na seguinte ordem:

  1. vm1
  2. vm2
  3. A extensão em vm1 depende de vm1 e vm2. A extensão define valores em vm1 que obtém de vm2.
  4. A extensão em vm2 depende de vm1 e vm2. A extensão define valores em vm2 que obtém de vm1.

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

Próximos passos