Gekoppelde en geneste sjablonen gebruiken bij het implementeren van Azure-resources

Als u complexe oplossingen wilt implementeren, kunt u uw Azure Resource Manager-sjabloon (ARM-sjabloon) opsplitsen in veel gerelateerde sjablonen en deze vervolgens samen implementeren via een hoofdsjabloon. De gerelateerde sjablonen kunnen afzonderlijke bestanden of sjabloonsyntaxis zijn die zijn ingesloten in de hoofdsjabloon. In dit artikel wordt de term gekoppelde sjabloon gebruikt om te verwijzen naar een afzonderlijk sjabloonbestand waarnaar wordt verwezen via een koppeling van de hoofdsjabloon. De term geneste sjabloon wordt gebruikt om te verwijzen naar de syntaxis van ingesloten sjablonen in de hoofdsjabloon.

Voor kleine tot middelgrote oplossingen is één sjabloon eenvoudiger te begrijpen en te onderhouden. U kunt alle resources en waarden in één bestand bekijken. Voor geavanceerde scenario's kunt u met gekoppelde sjablonen de oplossing opsplitsen in de beoogde onderdelen. U kunt deze sjablonen eenvoudig opnieuw gebruiken voor andere scenario's.

Zie Zelfstudie: Een gekoppelde sjabloon implementeren voor een zelfstudie.

Notitie

Voor gekoppelde of geneste sjablonen kunt u alleen de implementatiemodus instellen op Incrementeel. De hoofdsjabloon kan echter worden geïmplementeerd in de volledige modus. Als u de hoofdsjabloon in de volledige modus implementeert en de gekoppelde of geneste sjabloon is gericht op dezelfde resourcegroep, worden de resources die zijn geïmplementeerd in de gekoppelde of geneste sjabloon opgenomen in de evaluatie voor de implementatie van de volledige modus. De gecombineerde verzameling resources die zijn geïmplementeerd in de hoofdsjabloon en gekoppelde of geneste sjablonen, wordt vergeleken met de bestaande resources in de resourcegroep. Alle resources die niet in deze gecombineerde verzameling zijn opgenomen, worden verwijderd.

Als de gekoppelde of geneste sjabloon is gericht op een andere resourcegroep, gebruikt die implementatie incrementele modus. Zie Implementatiebereik voor meer informatie.

Tip

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

Geneste sjabloon

Als u een sjabloon wilt nesten, voegt u een implementatieresource toe aan uw hoofdsjabloon. Geef in de template eigenschap de syntaxis van de sjabloon op.

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {},
  "variables": {},
  "resources": [
    {
      "type": "Microsoft.Resources/deployments",
      "apiVersion": "2022-09-01",
      "name": "nestedTemplate1",
      "properties": {
        "mode": "Incremental",
        "template": {
          <nested-template-syntax>
        }
      }
    }
  ]
}

In het volgende voorbeeld wordt een opslagaccount geïmplementeerd via een geneste sjabloon.

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "storageAccountName": {
      "type": "string",
      "defaultValue": "[format('{0}{1}', 'store', uniqueString(resourceGroup().id))]"
    },
    "location": {
      "type": "string",
      "defaultValue": "[resourceGroup().location]"
    }
  },
  "resources": [
    {
      "type": "Microsoft.Resources/deployments",
      "apiVersion": "2022-09-01",
      "name": "nestedTemplate1",
      "properties": {
        "mode": "Incremental",
        "template": {
          "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
          "contentVersion": "1.0.0.0",
          "resources": [
            {
              "type": "Microsoft.Storage/storageAccounts",
              "apiVersion": "2022-09-01",
              "name": "[parameters('storageAccountName')]",
              "location": "[parameters('location')]",
              "sku": {
                "name": "Standard_LRS"
              },
              "kind": "StorageV2"
            }
          ]
        }
      }
    }
  ]
}

Geneste resources kunnen niet worden gebruikt in een symbolische naamsjabloon . In de volgende sjabloon kan de geneste opslagaccountresource geen symbolische naam gebruiken:

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "languageVersion": "2.0",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "storageAccountName": {
      "type": "string",
      "defaultValue": "[format('{0}{1}', 'storage', uniqueString(resourceGroup().id))]"

    },
    "location": {
      "type": "string",
      "defaultValue": "[resourceGroup().location]"
    }
  },
  "resources": {
    "mainStorage": {
      "type": "Microsoft.Storage/storageAccounts",
      "apiVersion": "2022-09-01",
      "name": "[parameters('storageAccountName')]",
      "location": "[parameters('location')]",
      "sku": {
        "name": "Standard_LRS"
      },
      "kind": "StorageV2"
    },
    "nestedResource": {
      "type": "Microsoft.Resources/deployments",
      "apiVersion": "2022-09-01",
      "name": "nestedTemplate1",
      "properties": {
        "mode": "Incremental",
        "template": {
          "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
          "contentVersion": "1.0.0.0",
          "resources": [
            {
              "type": "Microsoft.Storage/storageAccounts",
              "apiVersion": "2022-09-01",
              "name": "[format('{0}nested', parameters('storageAccountName'))]",
              "location": "[parameters('location')]",
              "sku": {
                "name": "Standard_LRS"
              },
              "kind": "StorageV2"
            }
          ]
        }
      }
    }
  }
}

Evaluatiebereik voor expressies in geneste sjablonen

Wanneer u een geneste sjabloon gebruikt, kunt u opgeven of sjabloonexpressies worden geëvalueerd binnen het bereik van de bovenliggende sjabloon of de geneste sjabloon. Het bereik bepaalt hoe parameters, variabelen en functies, zoals resourceGroup en abonnement , worden omgezet.

U stelt het bereik in via de expressionEvaluationOptions eigenschap. De eigenschap is standaard expressionEvaluationOptions ingesteld op outer, wat betekent dat deze gebruikmaakt van het bovenliggende sjabloonbereik. Stel de waarde in om inner te zorgen dat expressies worden geëvalueerd binnen het bereik van de geneste sjabloon.

Belangrijk

Voor languageVersion 2.0is de standaardwaarde voor de expressionEvaluationOptions eigenschap inner. De waarde outer wordt geblokkeerd.

{
  "type": "Microsoft.Resources/deployments",
  "apiVersion": "2022-09-01",
  "name": "nestedTemplate1",
  "properties": {
    "expressionEvaluationOptions": {
      "scope": "inner"
    },
  ...

Notitie

Wanneer het bereik is ingesteld outerop, kunt u de reference functie niet gebruiken in de uitvoersectie van een geneste sjabloon voor een resource die u hebt geïmplementeerd in de geneste sjabloon. Als u de waarden voor een geïmplementeerde resource in een geneste sjabloon wilt retourneren, gebruikt inner u het bereik of converteert u de geneste sjabloon naar een gekoppelde sjabloon.

In de volgende sjabloon ziet u hoe sjabloonexpressies worden omgezet volgens het bereik. Deze bevat een variabele met de naam exampleVar die is gedefinieerd in zowel de bovenliggende sjabloon als de geneste sjabloon. Hiermee wordt de waarde van de variabele geretourneerd.

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
  },
  "variables": {
    "exampleVar": "from parent template"
  },
  "resources": [
    {
      "type": "Microsoft.Resources/deployments",
      "apiVersion": "2022-09-01",
      "name": "nestedTemplate1",
      "properties": {
        "expressionEvaluationOptions": {
          "scope": "inner"
        },
        "mode": "Incremental",
        "template": {
          "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
          "contentVersion": "1.0.0.0",
          "variables": {
            "exampleVar": "from nested template"
          },
          "resources": [
          ],
          "outputs": {
            "testVar": {
              "type": "string",
              "value": "[variables('exampleVar')]"
            }
          }
        }
      }
    }
  ],
  "outputs": {
    "messageFromLinkedTemplate": {
      "type": "string",
      "value": "[reference('nestedTemplate1').outputs.testVar.value]"
    }
  }
}

De waarde van exampleVar wijzigingen, afhankelijk van de waarde van de scope eigenschap in expressionEvaluationOptions. In de volgende tabel ziet u de resultaten voor beide bereiken.

Evaluatiebereik Uitvoer
Innerlijke van geneste sjabloon
outer (of standaard) van bovenliggende sjabloon

In het volgende voorbeeld wordt een SQL-server geïmplementeerd en wordt een sleutelkluisgeheim opgehaald dat moet worden gebruikt voor het wachtwoord. Het bereik is ingesteld op inner omdat de sleutelkluis-id dynamisch wordt gemaakt (zie adminPassword.reference.keyVault in de buitenste sjablonen parameters) en deze als parameter doorgeeft aan de geneste sjabloon.

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "location": {
      "type": "string",
      "defaultValue": "[resourceGroup().location]",
      "metadata": {
        "description": "The location where the resources will be deployed."
      }
    },
    "vaultName": {
      "type": "string",
      "metadata": {
        "description": "The name of the keyvault that contains the secret."
      }
    },
    "secretName": {
      "type": "string",
      "metadata": {
        "description": "The name of the secret."
      }
    },
    "vaultResourceGroupName": {
      "type": "string",
      "metadata": {
        "description": "The name of the resource group that contains the keyvault."
      }
    },
    "vaultSubscription": {
      "type": "string",
      "defaultValue": "[subscription().subscriptionId]",
      "metadata": {
        "description": "The name of the subscription that contains the keyvault."
      }
    }
  },
  "resources": [
    {
      "type": "Microsoft.Resources/deployments",
      "apiVersion": "2022-09-01",
      "name": "dynamicSecret",
      "properties": {
        "mode": "Incremental",
        "expressionEvaluationOptions": {
          "scope": "inner"
        },
        "parameters": {
          "location": {
            "value": "[parameters('location')]"
          },
          "adminLogin": {
            "value": "ghuser"
          },
          "adminPassword": {
            "reference": {
              "keyVault": {
                "id": "[resourceId(parameters('vaultSubscription'), parameters('vaultResourceGroupName'), 'Microsoft.KeyVault/vaults', parameters('vaultName'))]"
              },
              "secretName": "[parameters('secretName')]"
            }
          }
        },
        "template": {
          "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
          "contentVersion": "1.0.0.0",
          "parameters": {
            "adminLogin": {
              "type": "string"
            },
            "adminPassword": {
              "type": "securestring"
            },
            "location": {
              "type": "string"
            }
          },
          "variables": {
            "sqlServerName": "[format('sql-{0}sql', uniqueString(resourceGroup().id, 'sql'))]"
          },
          "resources": [
            {
              "type": "Microsoft.Sql/servers",
              "apiVersion": "2022-05-01-preview",
              "name": "[variables('sqlServerName')]",
              "location": "[parameters('location')]",
              "properties": {
                "administratorLogin": "[parameters('adminLogin')]",
                "administratorLoginPassword": "[parameters('adminPassword')]"
              }
            }
          ],
          "outputs": {
            "sqlFQDN": {
              "type": "string",
              "value": "[reference(variables('sqlServerName')).fullyQualifiedDomainName]"
            }
          }
        }
      }
    }
  ],
  "outputs": {
  }
}

Wees voorzichtig bij het gebruik van beveiligde parameterwaarden in een geneste sjabloon. Als u het bereik instelt op buiten, worden de beveiligde waarden opgeslagen als tekst zonder opmaak in de implementatiegeschiedenis. Een gebruiker die de sjabloon in de implementatiegeschiedenis bekijkt, kan de beveiligde waarden zien. Gebruik in plaats daarvan het binnenste bereik of voeg deze toe aan de bovenliggende sjabloon de resources die veilige waarden nodig hebben.

In het volgende fragment ziet u welke waarden veilig zijn en welke niet veilig zijn.

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "adminUsername": {
      "type": "string",
      "metadata": {
        "description": "Username for the Virtual Machine."
      }
    },
    "adminPasswordOrKey": {
      "type": "securestring",
      "metadata": {
        "description": "SSH Key or password for the Virtual Machine. SSH key is recommended."
      }
    }
  },
  ...
  "resources": [
    {
      "type": "Microsoft.Compute/virtualMachines",
      "apiVersion": "2023-03-01",
      "name": "mainTemplate",
      "properties": {
        ...
        "osProfile": {
          "computerName": "mainTemplate",
          "adminUsername": "[parameters('adminUsername')]",
          "adminPassword": "[parameters('adminPasswordOrKey')]" // Yes, secure because resource is in parent template
        }
      }
    },
    {
      "name": "outer",
      "type": "Microsoft.Resources/deployments",
      "apiVersion": "2022-09-01",
      "properties": {
        "expressionEvaluationOptions": {
          "scope": "outer"
        },
        "mode": "Incremental",
        "template": {
          "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
          "contentVersion": "1.0.0.0",
          "resources": [
            {
              "type": "Microsoft.Compute/virtualMachines",
              "apiVersion": "2023-03-01",
              "name": "outer",
              "properties": {
                ...
                "osProfile": {
                  "computerName": "outer",
                  "adminUsername": "[parameters('adminUsername')]",
                  "adminPassword": "[parameters('adminPasswordOrKey')]" // No, not secure because resource is in nested template with outer scope
                }
              }
            }
          ]
        }
      }
    },
    {
      "name": "inner",
      "type": "Microsoft.Resources/deployments",
      "apiVersion": "2022-09-01",
      "properties": {
        "expressionEvaluationOptions": {
          "scope": "inner"
        },
        "mode": "Incremental",
        "parameters": {
          "adminPasswordOrKey": {
              "value": "[parameters('adminPasswordOrKey')]"
          },
          "adminUsername": {
              "value": "[parameters('adminUsername')]"
          }
        },
        "template": {
          "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
          "contentVersion": "1.0.0.0",
          "parameters": {
            "adminUsername": {
              "type": "string",
              "metadata": {
                "description": "Username for the Virtual Machine."
              }
            },
            "adminPasswordOrKey": {
              "type": "securestring",
              "metadata": {
                "description": "SSH Key or password for the Virtual Machine. SSH key is recommended."
              }
            }
          },
          "resources": [
            {
              "type": "Microsoft.Compute/virtualMachines",
              "apiVersion": "2023-03-01",
              "name": "inner",
              "properties": {
                ...
                "osProfile": {
                  "computerName": "inner",
                  "adminUsername": "[parameters('adminUsername')]",
                  "adminPassword": "[parameters('adminPasswordOrKey')]" // Yes, secure because resource is in nested template and scope is inner
                }
              }
            }
          ]
        }
      }
    }
  ]
}

Een gekoppelde sjabloon

Als u een sjabloon wilt koppelen, voegt u een implementatieresource toe aan uw hoofdsjabloon. Geef in de templateLink eigenschap de URI op van de sjabloon die u wilt opnemen. In het volgende voorbeeld wordt een sjabloon gekoppeld die zich in een opslagaccount bevindt.

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {},
  "variables": {},
  "resources": [
    {
      "type": "Microsoft.Resources/deployments",
      "apiVersion": "2022-09-01",
      "name": "linkedTemplate",
      "properties": {
        "mode": "Incremental",
        "templateLink": {
          "uri":"https://mystorageaccount.blob.core.windows.net/AzureTemplates/newStorageAccount.json",
          "contentVersion":"1.0.0.0"
        }
      }
    }
  ],
  "outputs": {
  }
}

Wanneer u naar een gekoppelde sjabloon verwijst, kan de waarde uri geen lokaal bestand zijn of een bestand dat alleen beschikbaar is in uw lokale netwerk. Azure Resource Manager moet toegang hebben tot de sjabloon. Geef een URI-waarde op die kan worden gedownload als HTTP of HTTPS.

U kunt verwijzen naar sjablonen met behulp van parameters die HTTP of HTTPS bevatten. Een veelvoorkomend patroon is bijvoorbeeld het gebruik van de _artifactsLocation parameter. U kunt de gekoppelde sjabloon instellen met een expressie zoals:

"uri": "[format('{0}/shared/os-disk-parts-md.json{1}', parameters('_artifactsLocation'), parameters('_artifactsLocationSasToken'))]"

Als u een koppeling naar een sjabloon in GitHub wilt maken, gebruikt u de onbewerkte URL. De koppeling heeft de volgende indeling: https://raw.githubusercontent.com/Azure/azure-docs-json-samples/master/get-started-with-templates/quickstart-template/azuredeploy.json. Als u de onbewerkte koppeling wilt ophalen, selecteert u Raw.

Screenshot of selecting raw URL in GitHub.

Notitie

Als u een sjabloon wilt implementeren of wilt verwijzen naar een gekoppelde sjabloon die is opgeslagen in een privé-GitHub-opslagplaats, raadpleegt u een aangepaste oplossing die wordt beschreven in het maken van een aangepaste en beveiligde Azure-portal-aanbieding. U kunt een Azure-functie maken waarmee het GitHub-token uit Azure Key Vault wordt opgehaald.

Voor gekoppelde sjablonen kunt u een implementatie van een niet-symbolische naam nesten in een sjabloon voor symbolische namen of een implementatie met symbolische naam nesten in een niet-symbolische sjabloon, of een implementatie met symbolische namen nesten in een andere sjabloon voor symbolische namen, of omgekeerd.

Parameters voor gekoppelde sjabloon

U kunt de parameters voor uw gekoppelde sjabloon opgeven in een extern bestand of inline. Wanneer u een extern parameterbestand opgeeft, gebruikt u de parametersLink eigenschap:

"resources": [
  {
    "type": "Microsoft.Resources/deployments",
    "apiVersion": "2022-09-01",
    "name": "linkedTemplate",
    "properties": {
      "mode": "Incremental",
      "templateLink": {
        "uri": "https://mystorageaccount.blob.core.windows.net/AzureTemplates/newStorageAccount.json",
        "contentVersion": "1.0.0.0"
      },
      "parametersLink": {
        "uri": "https://mystorageaccount.blob.core.windows.net/AzureTemplates/newStorageAccount.parameters.json",
        "contentVersion": "1.0.0.0"
      }
    }
  }
]

Als u parameterwaarden inline wilt doorgeven, gebruikt u de parameters eigenschap.

"resources": [
  {
    "type": "Microsoft.Resources/deployments",
    "apiVersion": "2022-09-01",
    "name": "linkedTemplate",
    "properties": {
      "mode": "Incremental",
      "templateLink": {
        "uri": "https://mystorageaccount.blob.core.windows.net/AzureTemplates/newStorageAccount.json",
        "contentVersion": "1.0.0.0"
      },
      "parameters": {
        "storageAccountName": {
          "value": "[parameters('storageAccountName')]"
        }
      }
    }
  }
]

U kunt zowel inlineparameters als een koppeling naar een parameterbestand niet gebruiken. De implementatie mislukt met een fout wanneer beide parametersLink en parameters zijn opgegeven.

Relatief pad gebruiken voor gekoppelde sjablonen

Met de relativePath eigenschap kunt Microsoft.Resources/deployments u eenvoudiger gekoppelde sjablonen maken. Deze eigenschap kan worden gebruikt om een externe gekoppelde sjabloon te implementeren op een locatie ten opzichte van het bovenliggende item. Voor deze functie moeten alle sjabloonbestanden worden gefaseerd en beschikbaar zijn op een externe URI, zoals GitHub of Een Azure-opslagaccount. Wanneer de hoofdsjabloon wordt aangeroepen met behulp van een URI van Azure PowerShell of Azure CLI, is de onderliggende implementatie-URI een combinatie van het bovenliggende en relatievePath.

Notitie

Bij het maken van een templateSpec worden alle sjablonen waarnaar wordt verwezen door de relativePath eigenschap verpakt in de templateSpec-resource door Azure PowerShell of Azure CLI. Het vereist niet dat de bestanden worden gefaseerd. Zie Een sjabloonspecificatie maken met gekoppelde sjablonen voor meer informatie.

Stel dat een mapstructuur er als volgt uitziet:

Diagram showing folder structure for Resource Manager linked template relative path.

In de volgende sjabloon ziet u hoe mainTemplate.json nestedChild.json geïmplementeerd in de vorige afbeelding.

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {},
  "functions": [],
  "variables": {},
  "resources": [
    {
      "type": "Microsoft.Resources/deployments",
      "apiVersion": "2022-09-01",
      "name": "childLinked",
      "properties": {
        "mode": "Incremental",
        "templateLink": {
          "relativePath": "children/nestedChild.json"
        }
      }
    }
  ],
  "outputs": {}
}

In de volgende implementatie is https://raw.githubusercontent.com/Azure/azure-docs-json-samples/master/linked-template-relpath/children/nestedChild.jsonde URI van de gekoppelde sjabloon in de voorgaande sjabloon.

New-AzResourceGroupDeployment `
  -Name linkedTemplateWithRelativePath `
  -ResourceGroupName "myResourceGroup" `
  -TemplateUri "https://raw.githubusercontent.com/Azure/azure-docs-json-samples/master/linked-template-relpath/mainTemplate.json"

Als u gekoppelde sjablonen wilt implementeren met een relatief pad dat is opgeslagen in een Azure-opslagaccount, gebruikt u de QueryString/query-string parameter om het SAS-token op te geven dat moet worden gebruikt met de parameter TemplateUri. Deze parameter wordt alleen ondersteund door Azure CLI versie 2.18 of hoger en Azure PowerShell versie 5.4 of hoger.

New-AzResourceGroupDeployment `
  -Name linkedTemplateWithRelativePath `
  -ResourceGroupName "myResourceGroup" `
  -TemplateUri "https://stage20210126.blob.core.windows.net/template-staging/mainTemplate.json" `
  -QueryString $sasToken

Zorg ervoor dat er geen voorlooptekens zijn in QueryString. De implementatie voegt er een toe bij het samenstellen van de URI voor de implementaties.

Sjabloonspecificaties

In plaats van uw gekoppelde sjablonen te onderhouden op een toegankelijk eindpunt, kunt u een sjabloonspecificatie maken waarmee de hoofdsjabloon en de gekoppelde sjablonen worden verpakt in één entiteit die u kunt implementeren. De sjabloonspecificatie is een resource in uw Azure-abonnement. Hiermee kunt u de sjabloon eenvoudig veilig delen met gebruikers in uw organisatie. U gebruikt op rollen gebaseerd toegangsbeheer van Azure (Azure RBAC) om toegang te verlenen tot de sjabloonspecificatie.

Zie voor meer informatie:

Afhankelijkheden

Net als bij andere resourcetypen kunt u afhankelijkheden instellen tussen de geneste/gekoppelde sjablonen. Als de resources in één geneste/gekoppelde sjabloon moeten worden geïmplementeerd voordat resources in een tweede geneste/gekoppelde sjabloon worden geïmplementeerd, stelt u de tweede sjabloon in die afhankelijk is van de eerste.

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {},
  "variables": {},
  "resources": [
    {
      "type": "Microsoft.Resources/deployments",
      "apiVersion": "2021-04-01",
      "name": "linkedTemplate1",
      "properties": {
        "mode": "Incremental",
        "templateLink": {
          "uri": "[uri(deployment().properties.templateLink.uri, 'firstresources.json')]",
          "contentVersion": "1.0.0.0"
        }
      }
    },
    {
      "type": "Microsoft.Resources/deployments",
      "apiVersion": "2021-04-01",
      "name": "linkedTemplate2",
      "dependsOn": [
        "[resourceId('Microsoft.Resources/deployments', 'linkedTemplate1')]"
      ],
      "properties": {
        "mode": "Incremental",
        "templateLink": {
          "uri": "[uri(deployment().properties.templateLink.uri, 'secondresources.json')]",
          "contentVersion": "1.0.0.0"
        }
      }
    }
  ]
}

contentVersion

U hoeft de contentVersion eigenschap niet op te geven voor de templateLink of parametersLink eigenschap. Als u geen versie opgeeft contentVersion, wordt de huidige versie van de sjabloon geïmplementeerd. Als u een waarde opgeeft voor de inhoudsversie, moet deze overeenkomen met de versie in de gekoppelde sjabloon; anders mislukt de implementatie met een fout.

In de vorige voorbeelden zijn in code vastgelegde URL-waarden voor de sjabloonkoppelingen weergegeven. Deze benadering werkt mogelijk voor een eenvoudige sjabloon, maar werkt niet goed voor een grote set modulaire sjablonen. In plaats daarvan kunt u een statische variabele maken waarin een basis-URL voor de hoofdsjabloon wordt opgeslagen en vervolgens dynamisch URL's voor de gekoppelde sjablonen van die basis-URL worden gemaakt. Het voordeel van deze aanpak is dat u de sjabloon eenvoudig kunt verplaatsen of forkeren, omdat u alleen de statische variabele in de hoofdsjabloon moet wijzigen. De hoofdsjabloon geeft de juiste URI's door in de uitgevouwen sjabloon.

In het volgende voorbeeld ziet u hoe u een basis-URL gebruikt om twee URL's te maken voor gekoppelde sjablonen (sharedTemplateUrl en vmTemplateUrl).

"variables": {
  "templateBaseUrl": "https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/application-workloads/postgre/postgresql-on-ubuntu/",
  "sharedTemplateUrl": "[uri(variables('templateBaseUrl'), 'shared-resources.json')]",
  "vmTemplateUrl": "[uri(variables('templateBaseUrl'), 'database-2disk-resources.json')]"
}

U kunt ook deployment() gebruiken om de basis-URL voor de huidige sjabloon op te halen en deze te gebruiken om de URL voor andere sjablonen op dezelfde locatie op te halen. Deze methode is handig als de locatie van de sjabloon wordt gewijzigd of als u harde coderings-URL's in het sjabloonbestand wilt voorkomen. De templateLink eigenschap wordt alleen geretourneerd wanneer u een koppeling maakt naar een externe sjabloon met een URL. Als u een lokale sjabloon gebruikt, is die eigenschap niet beschikbaar.

"variables": {
  "sharedTemplateUrl": "[uri(deployment().properties.templateLink.uri, 'shared-resources.json')]"
}

Uiteindelijk gebruikt u de variabele in de uri eigenschap van een templateLink eigenschap.

"templateLink": {
 "uri": "[variables('sharedTemplateUrl')]",
 "contentVersion":"1.0.0.0"
}

Kopiëren gebruiken

Als u meerdere exemplaren van een resource met een geneste sjabloon wilt maken, voegt u het copy element toe op het niveau van de Microsoft.Resources/deployments resource. Of, als het bereik is inner, kunt u de kopie toevoegen binnen de geneste sjabloon.

In de volgende voorbeeldsjabloon ziet u hoe u deze kunt gebruiken copy met een geneste sjabloon.

"resources": [
  {
    "type": "Microsoft.Resources/deployments",
    "apiVersion": "2022-09-01",
    "name": "[format('nestedTemplate{0}', copyIndex())]",
    // yes, copy works here
    "copy": {
      "name": "storagecopy",
      "count": 2
    },
    "properties": {
      "mode": "Incremental",
      "expressionEvaluationOptions": {
        "scope": "inner"
      },
      "template": {
        "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
        "contentVersion": "1.0.0.0",
        "resources": [
          {
            "type": "Microsoft.Storage/storageAccounts",
            "apiVersion": "2022-09-01",
            "name": "[format('{0}{1}', variables('storageName'), copyIndex())]",
            "location": "West US",
            "sku": {
              "name": "Standard_LRS"
            },
            "kind": "StorageV2"
            // Copy works here when scope is inner
            // But, when scope is default or outer, you get an error
            // "copy": {
            //   "name": "storagecopy",
            //   "count": 2
            // }
          }
        ]
      }
    }
  }
]

Waarden ophalen uit de gekoppelde sjabloon

Als u een uitvoerwaarde van een gekoppelde sjabloon wilt ophalen, haalt u de eigenschapswaarde op met syntaxis zoals: "[reference('deploymentName').outputs.propertyName.value]".

Wanneer u een uitvoereigenschap ophaalt van een gekoppelde sjabloon, mag de naam van de eigenschap geen streepje bevatten.

In de volgende voorbeelden ziet u hoe u naar een gekoppelde sjabloon verwijst en een uitvoerwaarde ophaalt. De gekoppelde sjabloon retourneert een eenvoudig bericht. Eerst de gekoppelde sjabloon:

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {},
  "variables": {},
  "resources": [],
  "outputs": {
    "greetingMessage": {
      "value": "Hello World",
      "type": "string"
    }
  }
}

De hoofdsjabloon implementeert de gekoppelde sjabloon en haalt de geretourneerde waarde op. U ziet dat deze verwijst naar de implementatieresource op naam en dat deze gebruikmaakt van de naam van de eigenschap die wordt geretourneerd door de gekoppelde sjabloon.

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {},
  "variables": {},
  "resources": [
    {
      "type": "Microsoft.Resources/deployments",
      "apiVersion": "2021-04-01",
      "name": "linkedTemplate",
      "properties": {
        "mode": "incremental",
        "templateLink": {
          "uri": "[uri(deployment().properties.templateLink.uri, 'helloworld.json')]",
          "contentVersion": "1.0.0.0"
        }
      }
    }
  ],
  "outputs": {
    "messageFromLinkedTemplate": {
      "type": "string",
      "value": "[reference('linkedTemplate').outputs.greetingMessage.value]"
    }
  }
}

In het volgende voorbeeld ziet u een sjabloon waarmee een openbaar IP-adres wordt geïmplementeerd en de resource-id van de Azure-resource voor dat openbare IP-adres wordt geretourneerd:

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "publicIPAddresses_name": {
      "type": "string"
    }
  },
  "variables": {},
  "resources": [
    {
      "type": "Microsoft.Network/publicIPAddresses",
      "apiVersion": "2021-02-01",
      "name": "[parameters('publicIPAddresses_name')]",
      "location": "eastus",
      "properties": {
        "publicIPAddressVersion": "IPv4",
        "publicIPAllocationMethod": "Dynamic",
        "idleTimeoutInMinutes": 4
      },
      "dependsOn": []
    }
  ],
  "outputs": {
    "resourceID": {
      "type": "string",
      "value": "[resourceId('Microsoft.Network/publicIPAddresses', parameters('publicIPAddresses_name'))]"
    }
  }
}

Als u het openbare IP-adres van de voorgaande sjabloon wilt gebruiken bij het implementeren van een load balancer, koppelt u een koppeling naar de sjabloon en declareert u een afhankelijkheid van de Microsoft.Resources/deployments resource. Het openbare IP-adres op de load balancer wordt ingesteld op de uitvoerwaarde van de gekoppelde sjabloon.

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "loadBalancers_name": {
      "defaultValue": "mylb",
      "type": "string"
    },
    "publicIPAddresses_name": {
      "defaultValue": "myip",
      "type": "string"
    }
  },
  "variables": {},
  "resources": [
    {
      "type": "Microsoft.Network/loadBalancers",
      "apiVersion": "2021-02-01",
      "name": "[parameters('loadBalancers_name')]",
      "location": "eastus",
      "properties": {
        "frontendIPConfigurations": [
          {
            "name": "LoadBalancerFrontEnd",
            "properties": {
              "privateIPAllocationMethod": "Dynamic",
              "publicIPAddress": {
                "id": "[reference('linkedTemplate').outputs.resourceID.value]"
              }
            }
          }
        ],
        "backendAddressPools": [],
        "loadBalancingRules": [],
        "probes": [],
        "inboundNatRules": [],
        "outboundNatRules": [],
        "inboundNatPools": []
      },
      "dependsOn": [
        "[resourceId('Microsoft.Resources/deployments', 'linkedTemplate')]"
      ]
    },
    {
      "type": "Microsoft.Resources/deployments",
      "apiVersion": "2021-04-01",
      "name": "linkedTemplate",
      "properties": {
        "mode": "Incremental",
        "templateLink": {
          "uri": "[uri(deployment().properties.templateLink.uri, 'public-ip.json')]",
          "contentVersion": "1.0.0.0"
        },
        "parameters": {
          "publicIPAddresses_name": { "value": "[parameters('publicIPAddresses_name')]" }
        }
      }
    }
  ]
}

Implementatiegeschiedenis

Resource Manager verwerkt elke sjabloon als een afzonderlijke implementatie in de implementatiegeschiedenis. Een hoofdsjabloon met drie gekoppelde of geneste sjablonen wordt weergegeven in de implementatiegeschiedenis als:

Screenshot of deployment history in Azure portal.

U kunt deze afzonderlijke vermeldingen in de geschiedenis gebruiken om uitvoerwaarden op te halen na de implementatie. Met de volgende sjabloon wordt een openbaar IP-adres gemaakt en wordt het IP-adres uitgevoerd:

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "publicIPAddresses_name": {
      "type": "string"
    },
    "location": {
      "type": "string",
      "defaultValue": "[resourceGroup().location]"
    }
  },
  "variables": {},
  "resources": [
    {
      "type": "Microsoft.Network/publicIPAddresses",
      "apiVersion": "2023-04-01",
      "name": "[parameters('publicIPAddresses_name')]",
      "location": "[parameters('location')]",
      "properties": {
        "publicIPAddressVersion": "IPv4",
        "publicIPAllocationMethod": "Static",
        "idleTimeoutInMinutes": 4,
        "dnsSettings": {
          "domainNameLabel": "[format('{0}{1}', parameters('publicIPAddresses_name'), uniqueString(resourceGroup().id))]"
        }
      },
      "dependsOn": []
    }
  ],
  "outputs": {
    "returnedIPAddress": {
      "type": "string",
      "value": "[reference(parameters('publicIPAddresses_name')).ipAddress]"
    }
  }
}

De volgende sjabloon is gekoppeld aan de voorgaande sjabloon. Er worden drie openbare IP-adressen gemaakt.

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
  },
  "variables": {},
  "resources": [
    {
      "type": "Microsoft.Resources/deployments",
      "apiVersion": "2022-09-01",
      "name": "[format('linkedTemplate{0}', copyIndex())]",
      "copy": {
        "count": 3,
        "name": "ip-loop"
      },
      "properties": {
        "mode": "Incremental",
        "templateLink": {
        "uri": "[uri(deployment().properties.templateLink.uri, 'static-public-ip.json')]",
        "contentVersion": "1.0.0.0"
        },
        "parameters":{
          "publicIPAddresses_name":{"value": "[format('myip-{0}', copyIndex())]"}
        }
      }
    }
  ]
}

Na de implementatie kunt u de uitvoerwaarden ophalen met het volgende PowerShell-script:

$loopCount = 3
for ($i = 0; $i -lt $loopCount; $i++)
{
  $name = 'linkedTemplate' + $i;
  $deployment = Get-AzResourceGroupDeployment -ResourceGroupName examplegroup -Name $name
  Write-Output "deployment $($deployment.DeploymentName) returned $($deployment.Outputs.returnedIPAddress.value)"
}

Of Azure CLI-script in een Bash-shell:

#!/bin/bash

for i in 0 1 2;
do
  name="linkedTemplate$i";
  deployment=$(az deployment group show -g examplegroup -n $name);
  ip=$(echo $deployment | jq .properties.outputs.returnedIPAddress.value);
  echo "deployment $name returned $ip";
done

Een externe sjabloon beveiligen

Hoewel de gekoppelde sjabloon extern beschikbaar moet zijn, hoeft deze niet algemeen beschikbaar te zijn voor het publiek. U kunt uw sjabloon toevoegen aan een privéopslagaccount dat alleen toegankelijk is voor de eigenaar van het opslagaccount. Vervolgens maakt u een SAS-token (Shared Access Signature) om toegang in te schakelen tijdens de implementatie. U voegt dat SAS-token toe aan de URI voor de gekoppelde sjabloon. Hoewel het token wordt doorgegeven als een beveiligde tekenreeks, wordt de URI van de gekoppelde sjabloon, inclusief het SAS-token, vastgelegd in de implementatiebewerkingen. Als u de blootstelling wilt beperken, stelt u een vervaldatum in voor het token.

Het parameterbestand kan ook worden beperkt tot toegang via een SAS-token.

Op dit moment kunt u geen koppeling maken naar een sjabloon in een opslagaccount dat zich achter een Azure Storage-firewall bevindt.

Belangrijk

In plaats van uw gekoppelde sjabloon te beveiligen met een SAS-token, kunt u overwegen een sjabloonspecificatie te maken. In de sjabloonspecificatie worden de hoofdsjabloon en de gekoppelde sjablonen veilig opgeslagen als een resource in uw Azure-abonnement. U gebruikt Azure RBAC om toegang te verlenen aan gebruikers die de sjabloon moeten implementeren.

In het volgende voorbeeld ziet u hoe u een SAS-token doorgeeft bij het koppelen aan een sjabloon:

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "containerSasToken": { "type": "securestring" }
  },
  "resources": [
    {
      "type": "Microsoft.Resources/deployments",
      "apiVersion": "2022-09-01",
      "name": "linkedTemplate",
      "properties": {
        "mode": "Incremental",
        "templateLink": {
          "uri": "[format('{0}{1}', uri(deployment().properties.templateLink.uri, 'helloworld.json'), parameters('containerSasToken'))]",
          "contentVersion": "1.0.0.0"
        }
      }
    }
  ],
  "outputs": {
  }
}

In PowerShell krijgt u een token voor de container en implementeert u de sjablonen met de volgende opdrachten. U ziet dat de containerSasToken parameter is gedefinieerd in de sjabloon. Het is geen parameter in de New-AzResourceGroupDeployment opdracht.

Set-AzCurrentStorageAccount -ResourceGroupName ManageGroup -Name storagecontosotemplates
$token = New-AzStorageContainerSASToken -Name templates -Permission r -ExpiryTime (Get-Date).AddMinutes(30.0)
$url = (Get-AzStorageBlob -Container templates -Blob parent.json).ICloudBlob.uri.AbsoluteUri
New-AzResourceGroupDeployment -ResourceGroupName ExampleGroup -TemplateUri ($url + $token) -containerSasToken $token

Voor Azure CLI in een Bash-shell krijgt u een token voor de container en implementeert u de sjablonen met de volgende code:

#!/bin/bash

expiretime=$(date -u -d '30 minutes' +%Y-%m-%dT%H:%MZ)
connection=$(az storage account show-connection-string \
  --resource-group ManageGroup \
  --name storagecontosotemplates \
  --query connectionString)
token=$(az storage container generate-sas \
  --name templates \
  --expiry $expiretime \
  --permissions r \
  --output tsv \
  --connection-string $connection)
url=$(az storage blob url \
  --container-name templates \
  --name parent.json \
  --output tsv \
  --connection-string $connection)
parameter='{"containerSasToken":{"value":"?'$token'"}}'
az deployment group create --resource-group ExampleGroup --template-uri $url?$token --parameters $parameter

Voorbeeldsjablonen

In de volgende voorbeelden ziet u algemene toepassingen van gekoppelde sjablonen.

Hoofdsjabloon Een gekoppelde sjabloon Beschrijving
Hello World gekoppelde sjabloon Retourneert een tekenreeks van een gekoppelde sjabloon.
Load Balancer met openbaar IP-adres gekoppelde sjabloon Retourneert een openbaar IP-adres van een gekoppelde sjabloon en stelt deze waarde in de load balancer in.
Meerdere IP-adressen gekoppelde sjabloon Hiermee maakt u verschillende openbare IP-adressen in een gekoppelde sjabloon.

Volgende stappen