部署 Azure 資源時使用連結和巢狀的範本Using linked and nested templates when deploying Azure resources

若要部署解決方案,您可以使用單一範本或有許多相關範本的主要範本。To deploy your solution, you can use either a single template or a main template with many related templates. 相關範本可以是連結到主要範本的個別檔案,或是主要範本內巢狀的範本。The related template can be either a separate file that is linked to from the main template, or a template that is nested 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, and reuse templates.

在使用連結的範本時,您會建立主要範本以在部署期間接收參數值。When using linked templates, you create a main template that receives the parameter values during deployment. 主要範本包含所有連結的範本,並且會視需要將值傳遞至這些範本。The main template contains all the linked templates and passes values to those templates as needed.

如需教學課程,請參閱建立連結的 Azure Resource Manager 範本For a tutorial, see Tutorial: create linked Azure Resource Manager templates.

注意

針對連結或巢狀的範本,您只能使用累加部署模式。For linked or nested templates, you can only use Incremental deployment mode.

若要連結到其他範本,請在主要範本中新增部署資源。To link to another template, add a deployments resource to your main template.

"resources": [
  {
    "type": "Microsoft.Resources/deployments",
    "apiVersion": "2018-05-01",
    "name": "linkedTemplate",
    "properties": {
        "mode": "Incremental",
        <nested-template-or-external-template>
    }
  }
]

您針對部署資源所提供的屬性,會根據您是連結到外部範本還是在主要範本中巢狀內嵌範本而有所不同。The properties you provide for the deployment resource vary based on whether you're linking to an external template or nesting an inline template in the main template.

巢狀範本Nested template

若要在主要範本巢狀範本,使用 template 屬性,並指定範本語法。To nest the template within the main template, use the template property and specify the template syntax.

"resources": [
  {
    "type": "Microsoft.Resources/deployments",
    "apiVersion": "2018-05-01",
    "name": "nestedTemplate",
    "properties": {
      "mode": "Incremental",
      "template": {
        "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
        "contentVersion": "1.0.0.0",
        "resources": [
          {
            "type": "Microsoft.Storage/storageAccounts",
            "apiVersion": "2019-04-01",
            "name": "[variables('storageName')]",
            "location": "West US",
            "kind": "StorageV2",
            "sku": {
                "name": "Standard_LRS"
            }
          }
        ]
      }
    }
  }
]

注意

對於巢狀範本,您無法使用巢狀範本中定義的參數或變數。For nested templates, you cannot use parameters or variables that are defined within the nested template. 您可以使用來自主要範本的參數和變數。You can use parameters and variables from the main template. 在上述範例中,[variables('storageName')] 會從主要範本擷取值,而不是巢狀範本。In the preceding example, [variables('storageName')] retrieves a value from the main template, not the nested template. 這項限制不適用於外部範本。This restriction does not apply to external templates.

針對在嵌套範本內定義的兩個資源, 以及一個資源相依于另一個資源, 相依性的值只是相依資源的名稱:For two resources defined inside a nested template and one resource depends on the other, the value of the dependency is simply the name of the dependent resource:

"dependsOn": [
  "[variables('storageAccountName')]"
],

您不能在reference已部署于嵌套範本中的資源之嵌套範本的 [輸出] 區段中使用函式。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. 若要傳回巢狀範本中已部署資源的值,請將巢狀範本轉換成連結範本。To return the values for a deployed resource in a nested template, convert your nested template to a linked template.

巢狀範本需要與標準範本相同的屬性The nested template requires the same properties as a standard template.

外部範本和外部參數External template and external parameters

若要連結到外部的範本和參數檔案,請使用 templateLinkparametersLinkTo link to an external template and parameter file, use templateLink and parametersLink. 在連結到範本時,Resource Manager 服務必須能夠存取該範本。When linking to a template, the Resource Manager service must be able to access it. 您無法指定本機檔案或只可在本機網路存取的檔案。You can't specify a local file or a file that is only available on your local network. 您可以只提供 URI 值,其中包含 httphttpsYou can only provide a URI value that includes either http or https. 有一個選項是將連結的範本放在儲存體帳戶中,並將 URI 用於該項目。One option is to place your linked template in a storage account, and use the URI for that item.

"resources": [
  {
    "type": "Microsoft.Resources/deployments",
    "apiVersion": "2018-05-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"
    }
    }
  }
]

您不需要提供範本的 contentVersion 屬性或參數。You don't have to provide the contentVersion property for the template or parameters. 如果您未提供內容版本值,則會部署目前的版本範本。If you don't provide a content version value, 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.

外部範本和內嵌參數External template and inline parameters

或者,您也可以提供內嵌的參數。Or, you can provide the parameter inline. 您無法對參數檔案同時使用內嵌參數和連結。You can't use both inline parameters and a link to a parameter file. 同時指定 parametersLinkparameters 時,部署將會失敗並發生錯誤。The deployment fails with an error when both parametersLink and parameters are specified.

若要將值從主要範本傳遞至連結的範本,請使用 parametersTo pass a value from the main template to the linked template, use parameters.

"resources": [
  {
     "type": "Microsoft.Resources/deployments",
     "apiVersion": "2018-05-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')]"}
        }
     }
  }
]

使用複製Using copy

若要使用嵌套的範本來建立資源的多個實例, 請在 [ Microsoft Resources/部署] 資源層級上新增 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.

下列範例範本顯示如何搭配使用複製與嵌套的範本。The following example template shows how to use copy with a nested template.

"resources": [
  {
    "type": "Microsoft.Resources/deployments",
    "apiVersion": "2018-05-01",
    "name": "[concat('nestedTemplate', copyIndex())]",
    // yes, copy works here
    "copy":{
      "name": "storagecopy",
      "count": 2
    },
    "properties": {
      "mode": "Incremental",
      "template": {
        "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
        "contentVersion": "1.0.0.0",
        "resources": [
          {
            "type": "Microsoft.Storage/storageAccounts",
            "apiVersion": "2019-04-01",
            "name": "[concat(variables('storageName'), copyIndex())]",
            "location": "West US",
            "kind": "StorageV2",
            "sku": {
              "name": "Standard_LRS"
            }
            // no, copy doesn't work here
            //"copy":{
            //  "name": "storagecopy",
            //  "count": 2
            //}
          }
        ]
      }
    }
  }
]

先前的範例示範了範本連結的硬式編碼 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 when working with 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 you can easily move or fork the template because you only need to change the static variable in the main template. 主要範本會於整個分解的範本傳遞正確的 URI。The main template passes the correct URIs throughout the decomposed template.

下列範例示範如何使用基底 URL 來為連結的範本 (sharedTemplateUrlvmTemplate) 建立兩個 URL。The following example shows how to use a base URL to create two URLs for linked templates (sharedTemplateUrl and vmTemplate).

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

您也可以使用 deployment() 取得目前範本的基底 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')]"
}

從連結的範本取得值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 can't 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.

{
    "$schema": "https://schema.management.azure.com/schemas/2015-01-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/2015-01-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {},
    "variables": {},
    "resources": [
        {
            "type": "Microsoft.Resources/deployments",
            "apiVersion": "2018-05-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]"
        }
    }
}

如同其他資源類型,您可以設定連結的範本和其他資源之間的相依性。Like other resource types, you can set dependencies between the linked template and other resources. 因此,當其他資源需要來自所連結範本的輸出值時,請確定在資源之前部署所連結的範本。Therefore, when other resources require an output value from the linked template, make sure the linked template is deployed before them. 或者,當連結的範本仰賴其他資源時,請確定在所連結的範本之前部署其他資源。Or, when the linked template relies on other resources, make sure other resources are deployed before the linked template.

下列範例所顯示的範本,會部署公用 IP 位址並傳回資源識別碼:The following example shows a template that deploys a public IP address and returns the resource ID:

{
    "$schema": "https://schema.management.azure.com/schemas/2015-01-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": "eastus",
            "properties": {
                "publicIPAddressVersion": "IPv4",
                "publicIPAllocationMethod": "Dynamic",
                "idleTimeoutInMinutes": 4
            },
            "dependsOn": []
        }
    ],
    "outputs": {
        "resourceID": {
            "type": "string",
            "value": "[resourceId('Microsoft.Network/publicIPAddresses', parameters('publicIPAddresses_name'))]"
        }
    }
}

若要在部署負載平衡器時,使用上述範本中的公用 IP 位址,請連結到該範本並對部署資源新增相依性。To use the public IP address from the preceding template when deploying a load balancer, link to the template and add a dependency on the deployment 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/2015-01-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": "eastus",
            "properties": {
                "frontendIPConfigurations": [
                    {
                        "name": "LoadBalancerFrontEnd",
                        "properties": {
                            "privateIPAllocationMethod": "Dynamic",
                            "publicIPAddress": {
                                "id": "[reference('linkedTemplate').outputs.resourceID.value]"
                            }
                        }
                    }
                ],
                "backendAddressPools": [],
                "loadBalancingRules": [],
                "probes": [],
                "inboundNatRules": [],
                "outboundNatRules": [],
                "inboundNatPools": []
            },
            "dependsOn": [
                "linkedTemplate"
            ]
        },
        {
            "type": "Microsoft.Resources/deployments",
            "apiVersion": "2018-05-01",
            "name": "linkedTemplate",
            "properties": {
                "mode": "Incremental",
                "templateLink": {
                    "uri": "[uri(deployment().properties.templateLink.uri, 'publicip.json')]",
                    "contentVersion": "1.0.0.0"
                },
                "parameters":{
                    "publicIPAddresses_name":{"value": "[parameters('publicIPAddresses_name')]"}
                }
            }
        }
    ]
}

部署歷程記錄中連結和巢狀的範本Linked and nested templates in deployment history

在部署歷程記錄中,Resource Manager 會以個別部署的方式處理每一個範本。Resource Manager processes each template as a separate deployment in the deployment history. 因此,具有三個連結或巢狀範本的主要範本在部署歷程記錄中會顯示為:Therefore, 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/2015-01-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": "southcentralus",
            "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/2015-01-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
    },
    "variables": {},
    "resources": [
        {
            "type": "Microsoft.Resources/deployments",
            "apiVersion": "2018-05-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 殼層中使用 Azure CLI 指令碼:Or, Azure CLI script in a Bash shell:

#!/bin/bash

for i in 0 1 2;
do
    name="linkedTemplate$i";
    deployment=$(az group deployment 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) Token 來啟用存取權。Then, you create a shared access signature (SAS) token to enable access during deployment. 您會將該 SAS Token 加入連結範本的 URI。You add that SAS token to the URI for the linked template. 即使該 Token 是以安全字串來傳遞,連結範本的 URI (包括 SAS Token) 還是會記錄在部署作業中。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. 為了限制公開的程度,請為該 Token 設定到期日。To limit exposure, set an expiration for the token.

當然,也可以將參數檔案限制為透過 SAS Token 存取。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 權杖:The following example shows how to pass a SAS token when linking to a template:

{
  "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "containerSasToken": { "type": "string" }
  },
  "resources": [
    {
      "type": "Microsoft.Resources/deployments",
      "apiVersion": "2018-05-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 中,您會取得容器的 Token 並使用下列命令部署範本。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 殼層中使用 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 group deployment 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