Definiowanie kolejności wdrażania zasobów w szablonach usługi ARM

Podczas wdrażania zasobów może być konieczne upewnienie się, że niektóre zasoby istnieją przed innymi zasobami. Na przykład potrzebny jest logiczny serwer SQL przed wdrożeniem bazy danych. Ta relacja jest ustanawiana przez oznaczenie jednego zasobu jako zależnego od drugiego zasobu. dependsOn Użyj elementu , aby zdefiniować jawną zależność. Użyj funkcji odwołania lub listy , aby zdefiniować niejawną zależność.

Usługa Azure Resource Manager ocenia zależności między zasobami i wdraża je w kolejności zależnej. Gdy zasoby nie zależą od siebie nawzajem, usługa Resource Manager wdraża je równolegle. Wystarczy zdefiniować zależności dla zasobów wdrożonych w tym samym szablonie.

Porada

Zalecamy Bicep , ponieważ oferuje te same możliwości co szablony usługi ARM, a składnia jest łatwiejsza w użyciu. Aby dowiedzieć się więcej, zobacz zależności zasobów.

dependsOn

W szablonie usługi Azure Resource Manager (szablon arm) dependsOn element umożliwia zdefiniowanie jednego zasobu jako zależnego od jednego lub większej liczby zasobów. Jego wartością jest tablica ciągów w formacie JavaScript Object Notation (JSON), z których każda jest nazwą zasobu lub identyfikatorem. Tablica może zawierać zasoby, które są wdrażane warunkowo. Gdy zasób warunkowy nie zostanie wdrożony, usługa Azure Resource Manager automatycznie usunie go z wymaganych zależności.

W poniższym przykładzie przedstawiono interfejs sieciowy, który zależy od sieci wirtualnej, sieciowej grupy zabezpieczeń i publicznego adresu IP. Pełny szablon można znaleźć w szablonie Szybkiego startu dla maszyny wirtualnej z systemem 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'))]"
  ],
  ...
}

W wersji languageVersion 2.0 użyj nazwy symbolicznej zasobu w dependsOn tablicach. Na przykład:

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

Chociaż możesz użyć dependsOn metody mapowania relacji między zasobami, ważne jest, aby zrozumieć, dlaczego to robisz. Aby na przykład udokumentować sposób łączenia zasobów, dependsOn nie jest właściwym podejściem. Po wdrożeniu zasób nie zachowuje zależności wdrożenia we właściwościach, więc nie ma poleceń ani operacji, które umożliwiają wyświetlanie zależności. Ustawienie niepotrzebnych zależności spowalnia czas wdrażania, ponieważ Resource Manager nie można wdrożyć tych zasobów równolegle.

Zasoby podrzędne

Niejawna zależność wdrożenia nie jest automatycznie tworzona między zasobem podrzędnym a zasobem nadrzędnym. Jeśli musisz wdrożyć zasób podrzędny po zasobie nadrzędnym, ustaw dependsOn właściwość .

W poniższym przykładzie przedstawiono logiczny serwer SQL i bazę danych. Zwróć uwagę, że jawna zależność jest definiowana między bazą danych a serwerem, mimo że baza danych jest elementem podrzędnym serwera.

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

Aby zapoznać się z pełnym szablonem, zobacz szablon szybkiego startu dla bazy danych Azure SQL.

funkcje odwołania i listy

Funkcja referencyjna umożliwia wyrażeniem uzyskiwanie wartości z innych par nazw i wartości JSON lub zasobów środowiska uruchomieniowego. Funkcje listy* zwracają wartości zasobu z operacji listy.

Odwołania i wyrażenia listy niejawnie deklarują, że jeden zasób zależy od innego. Jeśli to możliwe, użyj niejawnego odwołania, aby uniknąć dodawania niepotrzebnej zależności.

Aby wymusić niejawną zależność, zapoznaj się z zasobem według nazwy, a nie identyfikatorem zasobu. Jeśli identyfikator zasobu zostanie przekazany do funkcji odwołania lub listy, nie zostanie utworzone niejawne odwołanie.

Ogólny format reference funkcji to:

reference('resourceName').propertyPath

Ogólny format listKeys funkcji to:

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

W poniższym przykładzie punkt końcowy usługi CDN jawnie zależy od profilu usługi CDN i niejawnie zależy od aplikacji internetowej.

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

Aby dowiedzieć się więcej, zobacz funkcja referencyjna.

Zależy od zasobów w pętli

Aby wdrożyć zasoby zależne od zasobów w pętli kopiowania, dostępne są dwie opcje. Możesz ustawić zależność od poszczególnych zasobów w pętli lub w całej pętli.

Uwaga

W przypadku większości scenariuszy należy ustawić zależność od poszczególnych zasobów w pętli kopiowania. Przed utworzeniem następnego zasobu zależy tylko od całej pętli, gdy potrzebne są wszystkie zasoby w pętli. Ustawienie zależności od całej pętli powoduje znaczne rozszerzenie wykresu zależności, zwłaszcza jeśli te zapętlone zasoby zależą od innych zasobów. Rozwinięte zależności utrudniają efektywne ukończenie wdrożenia.

W poniższym przykładzie pokazano, jak wdrożyć wiele maszyn wirtualnych. Szablon tworzy tę samą liczbę interfejsów sieciowych. Każda maszyna wirtualna jest zależna od jednego interfejsu sieciowego, a nie całej pętli.

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

W poniższym przykładzie pokazano, jak wdrożyć trzy konta magazynu przed wdrożeniem maszyny wirtualnej. Zwróć uwagę, że copy element ma name ustawioną wartość storagecopy , a dependsOn element maszyny wirtualnej jest również ustawiony na storagecopywartość .

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

Nazwy symboliczne mogą być używane w dependsOn tablicach. Jeśli nazwa symboliczna jest przeznaczona dla pętli kopiowania, wszystkie zasoby w pętli są dodawane jako zależności. Powyższy przykład można napisać jako następujący kod JSON. W przykładzie maszyna wirtualna myVM zależy od wszystkich kont magazynu w pętli 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"],
      ...
    }
  }
}

Zależności cykliczne

Resource Manager identyfikuje zależności cykliczne podczas walidacji szablonu. Jeśli wystąpi błąd zależności cyklicznej, oceń szablon, aby sprawdzić, czy można usunąć jakiekolwiek zależności. Jeśli usuwanie zależności nie działa, można uniknąć zależności cyklicznego, przenosząc niektóre operacje wdrażania do zasobów podrzędnych. Wdróż zasoby podrzędne po zasobach, które mają zależność cykliczną. Załóżmy na przykład, że wdrażasz dwie maszyny wirtualne, ale musisz ustawić właściwości na każdym z nich, które odwołują się do drugiego. Można je wdrożyć w następującej kolejności:

  1. vm1
  2. vm2
  3. Rozszerzenie na maszynie vm1 zależy od maszyny wirtualnej vm1 i vm2. Rozszerzenie ustawia wartości na maszynie wirtualnej vm1, które pobiera z maszyny vm2.
  4. Rozszerzenie na maszynie wirtualnej vm2 zależy od maszyny wirtualnej vm1 i vm2. Rozszerzenie ustawia wartości na maszynie wirtualnej vm2, które pobiera z maszyny vm1.

Aby uzyskać informacje na temat oceny kolejności wdrażania i rozwiązywania błędów zależności, zobacz Rozwiązywanie typowych błędów wdrażania platformy Azure przy użyciu usługi Azure Resource Manager.

Następne kroki