Использование связанных и вложенных шаблонов при развертывании ресурсов AzureUsing 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 Функцию нельзя использовать в разделе Outputs вложенного шаблона для ресурса, развернутого во вложенном шаблоне.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

Связать внешний шаблон и файл параметров можно с помощью свойств templateLink и parametersLink.To 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), который включает в себя http или https.You 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. Развертывание завершается сбоем с ошибкой когда указываются parametersLink и parameters.The deployment fails with an error when both parametersLink and parameters are specified.

Передать значение из основного шаблона в связанный можно с помощью свойства parameters.To 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')]"}
        }
     }
  }
]

Использование инструкции CopyUsing copy

Чтобы создать несколько экземпляров ресурса с вложенным шаблоном, добавьте элемент Copy на уровне ресурса Microsoft. Resources/deployments .To create multiple instances of a resource with a nested template, add the copy element at the level of the Microsoft.Resources/deployments resource.

В следующем примере шаблона показано, как использовать Copy с вложенным шаблоном.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-адреса для связанных шаблонов на основе этого адреса.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-адрес для создания двух URL-адресов для связанных шаблонов (sharedTemplateUrl и vmTemplate).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')]"
}

Вы также можете получить базовый URL-адрес текущего шаблона с помощью функции deployment() , а затем использовать его для получения 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. Свойство templateLink возвращается только при подключении к удаленному шаблону по URL-адресу.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)"
}

Или сценарий Azure CLI в оболочке Bash: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. Затем создайте маркер подписанного URL-адреса для использования при развертывании.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.

В следующем примере показано, как передать маркер 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 получение маркера для контейнера и развертывание шаблонов выполняется с помощью следующих команд.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

Для Azure CLI в оболочке Bash происходит получение маркера для контейнера и развертывание шаблонов с помощью следующего кода.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 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