部署 Azure 资源时使用链接模版和嵌套模版Using linked and nested templates when deploying Azure resources
若要部署复杂的解决方案,可以将 Azure 资源管理器模板(ARM 模板)分解为许多相关模板,然后通过主模板将它们一起部署。To deploy complex solutions, you can break your Azure Resource Manager template (ARM template) into many related templates, and then deploy them together through a main template. 相关模板可以是嵌入在主模板内的单独文件或模板语法。The related templates can be separate files or template syntax that is embedded within the main template. 本文使用术语“链接模板”来指代一个通过主模板中的链接进行引用的单独模板文件。This article uses the term linked template to refer to a separate template file that is referenced via a link from the main template. 它使用术语 嵌套模板 指代主模板内嵌套的模板语法。It uses the term nested template to refer to embedded template syntax within the main template.
对于中小型解决方案,单个模板更易于理解和维护。For small to medium solutions, a single template is easier to understand and maintain. 可以查看单个文件中的所有资源和值。You can see all the resources and values in a single file. 对于高级方案,使用链接模板可将解决方案分解为目标组件。For advanced scenarios, linked templates enable you to break down the solution into targeted components. 可以轻松地将这些模板重复用于其他方案。You can easily reuse these templates for other scenarios.
如需教程,请参阅教程:部署链接模板。For a tutorial, see Tutorial: Deploy a linked template.
备注
对于链接模板或嵌套模板,只能将部署模式设置为增量。For linked or nested templates, you can only set the deployment mode to Incremental. 但是,主模板可以在完整模式下进行部署。However, the main template can be deployed in complete mode. 如果在完整模式下部署主模板,并且链接模板或嵌套模板以相同的资源组为目标,则在链接模板或嵌套模板中部署的资源会包括在针对完整模式部署进行的评估中。If you deploy the main template in the complete mode, and the linked or nested template targets the same resource group, the resources deployed in the linked or nested template are included in the evaluation for complete mode deployment. 将在主模板和链接模板或嵌套模板中部署的资源的合并集合与资源组中的现有资源进行比较。The combined collection of resources deployed in the main template and linked or nested templates is compared against the existing resources in the resource group. 此合并集合中未包含的任何资源都会被删除。Any resources not included in this combined collection are deleted.
如果链接模板或嵌套模板针对不同的资源组,则该部署使用增量模式。If the linked or nested template targets a different resource group, that deployment uses incremental mode.
嵌套模板Nested template
若要嵌套某个模板,请向主模板中添加一个部署资源。To nest a template, add a deployments resource to your main template. 在 template
属性中,指定模板语法。In the template
property, specify the template syntax.
{
"$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": "2019-10-01",
"name": "nestedTemplate1",
"properties": {
"mode": "Incremental",
"template": {
<nested-template-syntax>
}
}
}
],
"outputs": {
}
}
以下示例通过嵌套模板部署一个存储帐户。The following example deploys a storage account through a nested template.
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"storageAccountName": {
"type": "string"
}
},
"resources": [
{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2019-10-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": "2019-04-01",
"name": "[parameters('storageAccountName')]",
"location": "China North",
"sku": {
"name": "Standard_LRS"
},
"kind": "StorageV2"
}
]
}
}
}
],
"outputs": {
}
}
嵌套模板中的表达式计算作用域Expression evaluation scope in nested templates
使用嵌套模板时,可以指定是在父模板的作用域内还是在嵌套模板的作用域内计算模板表达式。When using a nested template, you can specify whether template expressions are evaluated within the scope of the parent template or the nested template. 作用域决定了如何对参数、变量和函数(例如 resourceGroup 和 subscription)进行求解。The scope determines how parameters, variables, and functions like resourceGroup and subscription are resolved.
可以通过 expressionEvaluationOptions
属性设置作用域。You set the scope through the expressionEvaluationOptions
property. 默认情况下,expressionEvaluationOptions
属性设置为 outer
,这意味着它使用父模板作用域。By default, the expressionEvaluationOptions
property is set to outer
, which means it uses the parent template scope. 将值设置为“inner
”可使表达式在嵌套模板的作用域内进行计算。Set the value to inner
to cause expressions to be evaluated within the scope of the nested template.
{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2019-10-01",
"name": "nestedTemplate1",
"properties": {
"expressionEvaluationOptions": {
"scope": "inner"
},
...
备注
当作用域设置为 outer
时,对于已在嵌套模板中部署的资源,无法在嵌套模板的 outputs 节中使用 reference
函数。When scope is set to outer
, you can't use the reference
function in the outputs section of a nested template for a resource you have deployed in the nested template. 若要返回嵌套模板中部署的资源的值,请使用 inner
作用域或将嵌套模板转换为链接模板。To return the values for a deployed resource in a nested template, either use inner
scope or convert your nested template to a linked template.
以下模板演示了如何根据作用域对模板表达式进行求解。The following template demonstrates how template expressions are resolved according to the scope. 它包含一个名为 exampleVar
的变量,父模板和嵌套模板中都定义了此变量。It contains a variable named exampleVar
that is defined in both the parent template and the nested template. 它返回此变量的值。It returns the value of the variable.
{
"$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": "2019-10-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]"
}
}
}
exampleVar
的值因 expressionEvaluationOptions
中 scope
属性的值而异。The value of exampleVar
changes depending on the value of the scope
property in expressionEvaluationOptions
. 下表显示了这两个作用域的结果。The following table shows the results for both scopes.
评估范围Evaluation scope | 输出Output |
---|---|
内部inner | from nested templatefrom nested template |
outer(或默认值)outer (or default) | from parent templatefrom parent template |
下面的示例部署一个 SQL Server,并检索要用于密码的密钥保管库机密。The following example deploys a SQL server and retrieves a key vault secret to use for the password. 作用域设置为 inner
,因为它会动态创建密钥保管库 ID(请参见外部模板 parameters
中的 adminPassword.reference.keyVault
)并将其作为参数传递到嵌套模板。The scope is set to inner
because it dynamically creates the key vault ID (see adminPassword.reference.keyVault
in the outer templates parameters
) and passes it as a parameter to the nested template.
{
"$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": "2019-10-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": "[concat('sql-', uniqueString(resourceGroup().id, 'sql'))]"
},
"resources": [
{
"type": "Microsoft.Sql/servers",
"apiVersion": "2018-06-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": {
}
}
使用嵌套模板中的安全参数值时请小心。Be careful when using secure parameter values in a nested template. 如果将范围设置为“外部”,则安全值将作为纯文本存储在部署历史记录中。If you set the scope to outer, the secure values are stored as plain text in the deployment history. 在部署历史记录中查看模板的用户可以看到安全值。A user viewing the template in the deployment history could see the secure values. 改为使用内部范围或向父模板添加需要安全值的资源。Instead use the inner scope or add to the parent template the resources that need secure values.
以下摘录显示了哪些值是安全的,哪些值是不安全的。The following excerpt shows which values are secure and which aren't secure.
{
"$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": "2020-06-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": "2019-10-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": "2020-06-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": "2019-10-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": "2020-06-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
}
}
}
]
}
}
}
]
}
链接的模板Linked template
若要链接某个模板,请向主模板中添加一个部署资源。To link a template, add a deployments resource to your main template. 在 templateLink
属性中,指定要包括的模板的 URI。In the templateLink
property, specify the URI of the template to include. 以下示例链接到存储帐户中的模板。The following example links to a template that is in a storage account.
{
"$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": "2019-10-01",
"name": "linkedTemplate",
"properties": {
"mode": "Incremental",
"templateLink": {
"uri":"https://mystorageaccount.blob.core.chinacloudapi.cn/AzureTemplates/newStorageAccount.json",
"contentVersion":"1.0.0.0"
}
}
}
],
"outputs": {
}
}
引用链接模板时,uri
的值不能是本地文件或只能在本地网络上使用的文件。When referencing a linked template, the value of uri
can't be a local file or a file that is only available on your local network. Azure 资源管理器必须能够访问该模板。Azure Resource Manager must be able to access the template. 提供可下载的 HTTP 或 HTTPS 形式的 URI 值。Provide a URI value that downloadable as HTTP or HTTPS.
可以使用包含 HTTP 或 HTTPS 的参数来引用模板。You may reference templates using parameters that include HTTP or HTTPS. 例如,一种常见模式是使用 _artifactsLocation
参数。For example, a common pattern is to use the _artifactsLocation
parameter. 可以使用如下所示的表达式来设置链接模板:You can set the linked template with an expression like:
"uri": "[concat(parameters('_artifactsLocation'), '/shared/os-disk-parts-md.json', parameters('_artifactsLocationSasToken'))]"
如果要链接到 GitHub 中的模板,请使用原始 URL。If you're linking to a template in GitHub, use the raw URL. 链接的格式为:https://raw.githubusercontent.com/Azure/azure-docs-json-samples/master/get-started-with-templates/quickstart-template/azuredeploy.json
。The link has the format: https://raw.githubusercontent.com/Azure/azure-docs-json-samples/master/get-started-with-templates/quickstart-template/azuredeploy.json
. 若要获取原始链接,请选择“原始”。To get the raw link, select Raw.
链接模板的参数Parameters for linked template
可以在外部文件中或以内联方式为链接模板提供参数。You can provide the parameters for your linked template either in an external file or inline. 提供外部参数文件时,请使用 parametersLink
属性:When providing an external parameter file, use the parametersLink
property:
"resources": [
{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2019-10-01",
"name": "linkedTemplate",
"properties": {
"mode": "Incremental",
"templateLink": {
"uri": "https://mystorageaccount.blob.core.chinacloudapi.cn/AzureTemplates/newStorageAccount.json",
"contentVersion": "1.0.0.0"
},
"parametersLink": {
"uri": "https://mystorageaccount.blob.core.chinacloudapi.cn/AzureTemplates/newStorageAccount.parameters.json",
"contentVersion": "1.0.0.0"
}
}
}
]
若要以内联方式传递参数值,请使用 parameters
属性。To pass parameter values inline, use the parameters
property.
"resources": [
{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2019-10-01",
"name": "linkedTemplate",
"properties": {
"mode": "Incremental",
"templateLink": {
"uri": "https://mystorageaccount.blob.core.chinacloudapi.cn/AzureTemplates/newStorageAccount.json",
"contentVersion": "1.0.0.0"
},
"parameters": {
"storageAccountName": {
"value": "[parameters('storageAccountName')]"
}
}
}
}
]
不能同时使用内联参数和指向参数文件的链接。You can't use both inline parameters and a link to a parameter file. 同时指定 parametersLink
和 parameters
时,部署将失败,并出现错误。The deployment fails with an error when both parametersLink
and parameters
are specified.
为链接模板使用相对路径Use relative path for linked templates
使用 Microsoft.Resources/deployments
的 relativePath
属性可以更轻松地创作链接模板。The relativePath
property of Microsoft.Resources/deployments
makes it easier to author linked templates. 可以使用此属性在相对于父级的某个位置部署远程链接模板。This property can be used to deploy a remote linked template at a location relative to the parent. 此功能要求暂存所有模板文件并使其可通过远程 URI(例如 GitHub 或 Azure 存储帐户)进行访问。This feature requires all template files to be staged and available at a remote URI, such as GitHub or Azure storage account. 通过 Azure PowerShell 或 Azure CLI 使用 URI 调用主模板时,子部署 URI 是父级和 relativePath 的组合。When the main template is called by using a URI from Azure PowerShell or Azure CLI, the child deployment URI is a combination of the parent and relativePath.
备注
当创建 templateSpec 时,relativePath
属性引用的任何模板都将通过 Azure PowerShell 或 Azure CLI 打包在 templateSpec 资源中。When creating a templateSpec, any templates referenced by the relativePath
property is packaged in the templateSpec resource by Azure PowerShell or Azure CLI. 它不要求暂存文件。It do not require the files to be staged. 有关详细信息,请参阅创建具有链接模板的模板规范。For more information, see Create a template spec with linked templates.
假设文件夹结构如下所示:Assume a folder structure like this:
以下模板展示了 mainTemplate.json 如何部署上图中所示的 nestedChild.json。The following template shows how mainTemplate.json deploys nestedChild.json illustrated in the preceding image.
{
"$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": "2020-10-01",
"name": "childLinked",
"properties": {
"mode": "Incremental",
"templateLink": {
"relativePath": "children/nestedChild.json"
}
}
}
],
"outputs": {}
}
在以下部署中,上面的模板中链接模板的 URI 是 https://raw.githubusercontent.com/Azure/azure-docs-json-samples/master/linked-template-relpath/children/nestedChild.json 。In the following deployment, the URI of the linked template in the preceding template is https://raw.githubusercontent.com/Azure/azure-docs-json-samples/master/linked-template-relpath/children/nestedChild.json.
New-AzResourceGroupDeployment `
-Name linkedTemplateWithRelativePath `
-ResourceGroupName "myResourceGroup" `
-TemplateUri "https://raw.githubusercontent.com/Azure/azure-docs-json-samples/master/linked-template-relpath/mainTemplate.json"
若要使用在 Azure 存储帐户中存储的相对路径来部署链接模板,请使用 QueryString
/query-string
参数指定要与 TemplateUri 参数一起使用的 SAS 令牌。To deploy linked templates with relative path stored in an Azure storage account, use the QueryString
/query-string
parameter to specify the SAS token to be used with the TemplateUri parameter. 只有 Azure CLI 2.18 版或更高版本和 Azure PowerShell 5.4 版或更高版本支持此参数。This parameter is only supported by Azure CLI version 2.18 or later and Azure PowerShell version 5.4 or later.
New-AzResourceGroupDeployment `
-Name linkedTemplateWithRelativePath `
-ResourceGroupName "myResourceGroup" `
-TemplateUri "https://stage20210126.blob.core.chinacloudapi.cn/template-staging/mainTemplate.json" `
-QueryString $sasToken
请确保 QueryString 中没有前导“?”。Make sure there is no leading "?" in QueryString. 在组装部署的 URI 时,部署会添加一个“?”。The deployment adds one when assembling the URI for the deployments.
模板规格Template specs
你可创建一个模板规范,将主模板及其链接模板打包到可部署的单个实体中,而不是在可访问的终结点上维护链接模板。Instead of maintaining your linked templates at an accessible endpoint, you can create a template spec that packages the main template and its linked templates into a single entity you can deploy. 模板规格是 Azure 订阅中的资源。The template spec is a resource in your Azure subscription. 这使你可以轻松地与组织中的用户安全地共享模板。It makes it easy to securely share the template with users in your organization. 可使用 Azure 基于角色的访问控制 (Azure RBAC) 来授予对模板规格的访问权限。此功能目前以预览版提供。You use Azure role-based access control (Azure RBAC) to grant access to the template spec. This feature is currently in preview.
有关详细信息,请参阅:For more information, see:
- 教程:创建具有链接模板的模板规格。Tutorial: Create a template spec with linked templates.
- 教程:将模板规格部署为链接模板。Tutorial: Deploy a template spec as a linked template.
依赖项Dependencies
与其他资源类型一样,你可以在链接模板之间设置依赖关系。As with other resource types, you can set dependencies between the linked templates. 如果某个链接模板中的资源必须在第二个链接模板中的资源之前部署,请设置第二个模板依赖于第一个模板。If the resources in one linked template must be deployed before resources in a second linked template, set the second template dependent on the first.
{
"$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": "2020-06-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": "2020-06-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"
}
}
}
]
}
contentVersioncontentVersion
无需为 templateLink
或 parametersLink
属性提供 contentVersion
属性。You don't have to provide the contentVersion
property for the templateLink
or parametersLink
property. 如果未提供 contentVersion
,则会部署模板的当前版本。If you don't provide a contentVersion
, the current version of the template is deployed. 如果提供内容版本值,它必须与链接的模板中的版本相匹配;否则,部署失败并产生错误。If you provide a value for content version, it must match the version in the linked template; otherwise, the deployment fails with an error.
使用变量来链接模板Using variables to link templates
前面的示例演示了用于模板链接的硬编码 URL 值。The previous examples showed hard-coded URL values for the template links. 这种方法可能适用于某个简单的模板,但不适用于一组大型模块化模板。This approach might work for a simple template, but it doesn't work well for a large set of modular templates. 相反,可以创建一个存储主模板的基 URL 的静态变量,并从基 URL 动态创建用于链接模板的 URL。Instead, you can create a static variable that stores a base URL for the main template and then dynamically create URLs for the linked templates from that base URL. 这种方法的好处是可以轻松地移动或派生模板,因为只需在主模板中更改静态变量。The benefit of this approach is that you can easily move or fork the template because you need to change only the static variable in the main template. 主模板会在整个分解后的模板中传递正确的 URI。The main template passes the correct URIs throughout the decomposed template.
以下示例演示如何使用基 URL 来创建两个用于链接模板的 URL(sharedTemplateUrl
和 vmTemplateUrl
)。The following example shows how to use a base URL to create two URLs for linked templates (sharedTemplateUrl
and vmTemplateUrl
).
"variables": {
"templateBaseUrl": "https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/postgresql-on-ubuntu/",
"sharedTemplateUrl": "[uri(variables('templateBaseUrl'), 'shared-resources.json')]",
"vmTemplateUrl": "[uri(variables('templateBaseUrl'), 'database-2disk-resources.json')]"
}
还可以使用 deployment() 获取当前模板的基 URL,并使用该 URL 来获取同一位置其他模板的 URL。You can also use deployment() to get the base URL for the current template, and use that to get the URL for other templates in the same location. 如果模板位置发生变化或者想要避免对模板文件中的 URL 进行硬编码,则此方法非常有用。This approach is useful if your template location changes or you want to avoid hard coding URLs in the template file. 仅当链接到带有 URL 的远程模板时,才会返回 templateLink
属性。The templateLink
property is only returned when linking to a remote template with a URL. 如果使用的是本地模板,该属性不可用。If you're using a local template, that property isn't available.
"variables": {
"sharedTemplateUrl": "[uri(deployment().properties.templateLink.uri, 'shared-resources.json')]"
}
最终,会在 templateLink
属性的 uri
属性中使用变量。Ultimately, you would use the variable in the uri
property of a templateLink
property.
"templateLink": {
"uri": "[variables('sharedTemplateUrl')]",
"contentVersion":"1.0.0.0"
}
使用副本Using copy
若要使用嵌套的模板创建资源的多个实例,请在 Microsoft.Resources/deployments
资源的级别添加 copy
元素。To create multiple instances of a resource with a nested template, add the copy
element at the level of the Microsoft.Resources/deployments
resource. 或者,如果范围为 inner
,则可以在嵌套模板中添加副本。Or, if the scope is inner
, you can add the copy within the nested template.
以下示例模板展示了如何将 copy
与嵌套的模板配合使用。The following example template shows how to use copy
with a nested template.
"resources": [
{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2019-10-01",
"name": "[concat('nestedTemplate', 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": "2019-04-01",
"name": "[concat(variables('storageName'), copyIndex())]",
"location": "China North",
"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
// }
}
]
}
}
}
]
从链接模板中获取值Get values from linked template
若要从链接模板中获取输出值,请使用如下所示的语法检索属性值:"[reference('deploymentName').outputs.propertyName.value]"
。To get an output value from a linked template, retrieve the property value with syntax like: "[reference('deploymentName').outputs.propertyName.value]"
.
从链接模板获取输出属性时,属性名称不能包含短划线。When getting an output property from a linked template, the property name must not include a dash.
以下示例演示如何引用链接模板和检索输出值。The following examples demonstrate how to reference a linked template and retrieve an output value. 链接模板返回一条简单的消息。The linked template returns a simple message. 首先,让我们看看链接模板:First, the linked template:
{
"$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"
}
}
}
主模板部署链接模板并获取返回值。The main template deploys the linked template and gets the returned value. 请注意,该模板按名称引用部署资源,并使用链接模板返回的属性的名称。Notice that it references the deployment resource by name, and it uses the name of the property returned by the linked template.
{
"$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": "2020-06-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]"
}
}
}
以下示例显示一个模板,该模板部署公共 IP 地址并返回该公共 IP 的 Azure 资源的资源 ID:The following example shows a template that deploys a public IP address and returns the resource ID of the Azure resource for that public IP:
{
"$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": "2018-11-01",
"name": "[parameters('publicIPAddresses_name')]",
"location": "chinaeast",
"properties": {
"publicIPAddressVersion": "IPv4",
"publicIPAllocationMethod": "Dynamic",
"idleTimeoutInMinutes": 4
},
"dependsOn": []
}
],
"outputs": {
"resourceID": {
"type": "string",
"value": "[resourceId('Microsoft.Network/publicIPAddresses', parameters('publicIPAddresses_name'))]"
}
}
}
在部署负载均衡器时,若要使用前面所述模板中的公共 IP 地址,请链接到该模板,并声明对 Microsoft.Resources/deployments
资源的依赖性。To use the public IP address from the preceding template when deploying a load balancer, link to the template and declare a dependency on the Microsoft.Resources/deployments
resource. 负载均衡器上的公共 IP 地址设置为链接模板的输出值。The public IP address on the load balancer is set to the output value from the linked template.
{
"$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": "2018-11-01",
"name": "[parameters('loadBalancers_name')]",
"location": "chinaeast",
"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": "2020-06-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')]"}
}
}
}
]
}
部署历史记录Deployment history
资源管理器将每个模板作为部署历史记录中的单独部署进行处理。Resource Manager processes each template as a separate deployment in the deployment history. 包含三个链接模板或嵌套模板的主模板在部署历史记录中显示为:A main template with three linked or nested templates appears in the deployment history as:
部署后,可以使用历史记录中这些不同的条目来检索输出值。You can use these separate entries in the history to retrieve output values after the deployment. 以下模板创建一个公共 IP 地址并输出该 IP 地址:The following template creates a public IP address and outputs the IP address:
{
"$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": "2018-11-01",
"name": "[parameters('publicIPAddresses_name')]",
"location": "chinaeast",
"properties": {
"publicIPAddressVersion": "IPv4",
"publicIPAllocationMethod": "Static",
"idleTimeoutInMinutes": 4,
"dnsSettings": {
"domainNameLabel": "[concat(parameters('publicIPAddresses_name'), uniqueString(resourceGroup().id))]"
}
},
"dependsOn": []
}
],
"outputs": {
"returnedIPAddress": {
"type": "string",
"value": "[reference(parameters('publicIPAddresses_name')).ipAddress]"
}
}
}
以下模板链接到前面所述的模板。The following template links to the preceding template. 它创建三个公共 IP 地址。It creates three public IP addresses.
{
"$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": "2019-10-01",
"name": "[concat('linkedTemplate', 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": "[concat('myip-', copyIndex())]"}
}
}
}
]
}
部署后,可使用以下 PowerShell 脚本检索输出值:After the deployment, you can retrieve the output values with the following 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)"
}
还可以使用 Bash shell 中的 Azure CLI 脚本:Or, Azure CLI script in a 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
保护外部模板Securing an external template
尽管链接模板必须可从外部使用,但它无需向公众正式发布。Although the linked template must be externally available, it doesn't need to be generally available to the public. 可以将模板添加到只有存储帐户所有者可以访问的专用存储帐户。You can add your template to a private storage account that is accessible to only the storage account owner. 然后,在部署期间创建共享访问签名 (SAS) 令牌来启用访问。Then, you create a shared access signature (SAS) token to enable access during deployment. 将该 SAS 令牌添加到链接模板的 URI。You add that SAS token to the URI for the linked template. 即使令牌作为安全字符串传入,链接模板的 URI(包括 SAS 令牌)也会记录在部署操作中。Even though the token is passed in as a secure string, the URI of the linked template, including the SAS token, is logged in the deployment operations. 若要限制公开,请设置令牌的到期时间。To limit exposure, set an expiration for the token.
也可将参数文件限制为通过 SAS 令牌进行访问。The parameter file can also be limited to access through a SAS token.
目前,无法链接到位于 Azure 存储防火墙后面的存储帐户中的模板。Currently, you can't link to a template in a storage account that is behind an Azure Storage firewall.
重要
请考虑创建模板规格,而不是使用 SAS 令牌保护链接模板。模板规格将主模板及其链接模板作为资源安全地存储在 Azure 订阅中。Instead of securing your linked template with a SAS token, consider creating a template spec. The template spec securely stores the main template and its linked templates as a resource in your Azure subscription. 使用 Azure RBAC 向需要部署模板的用户授予访问权限。You use Azure RBAC to grant access to users who need to deploy the template.
以下示例演示在链接到模板时如何传递 SAS 令牌:The following example shows how to pass a SAS token when linking to a template:
{
"$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": "2019-10-01",
"name": "linkedTemplate",
"properties": {
"mode": "Incremental",
"templateLink": {
"uri": "[concat(uri(deployment().properties.templateLink.uri, 'helloworld.json'), parameters('containerSasToken'))]",
"contentVersion": "1.0.0.0"
}
}
}
],
"outputs": {
}
}
在 PowerShell 中,使用以下命令获取容器的令牌并部署模板。In PowerShell, you get a token for the container and deploy the templates with the following commands. 注意,containerSasToken
参数是在模板中定义的。Notice that the containerSasToken
parameter is defined in the template. 它不是 New-AzResourceGroupDeployment
命令中的参数。It isn't a parameter in the New-AzResourceGroupDeployment
command.
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
对于 Bash Shell 中的 Azure CLI,使用以下代码获取容器的令牌并部署模板:For Azure CLI in a Bash shell, you get a token for the container and deploy the templates with the following 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
示例模板Example templates
下面的示例展示了链接的模板的常见用途。The following examples show common uses of linked templates.
主模板Main template | 链接的模板Linked template | 说明Description |
---|---|---|
Hello WorldHello World | 链接的模板linked template | 从链接的模板返回字符串。Returns string from linked template. |
使用公共 IP 地址的负载均衡器Load Balancer with public IP address | 链接的模板linked template | 从链接的模板返回公共 IP 地址并在负载均衡器中设置该值。Returns public IP address from linked template and sets that value in load balancer. |
多个 IP 地址Multiple IP addresses | 链接的模板linked template | 在链接模板中创建多个公共 IP 地址。Creates several public IP addresses in linked template. |
后续步骤Next steps
- 若要完成教程,请参阅教程:部署链接模板。To go through a tutorial, see Tutorial: Deploy a linked template.
- 若要了解如何为资源定义部署顺序,请参阅在 ARM 模板中定义资源的部署顺序。To learn about the defining the deployment order for your resources, see Define the order for deploying resources in ARM templates.
- 若要了解如何定义一个资源但要创建它的多个实例,请参阅 ARM 模板中的资源迭代。To learn how to define one resource but create many instances of it, see Resource iteration in ARM templates.
- 有关在存储帐户中设置模板和生成 SAS 令牌的步骤,请参阅使用 ARM 模板和 Azure PowerShell 部署资源或使用 ARM 模板和 Azure CLI 部署资源。For steps on setting up a template in a storage account and generating a SAS token, see Deploy resources with ARM templates and Azure PowerShell or Deploy resources with ARM templates and Azure CLI.