Использование связанных и вложенных шаблонов при развертывании ресурсов AzureUsing linked and nested templates when deploying Azure resources

Для развертывания сложных решений можно разбить шаблон на множество связанных шаблонов, а затем развернуть их вместе с помощью основного шаблона.To deploy complex solutions, you can break your 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.

Подробнее см. Руководство. Создание связанных шаблонов Azure Resource Manager.For a tutorial, see Tutorial: create linked Azure Resource Manager templates.

Примечание

Для связанных или вложенных шаблонов можно задать только добавочныйрежим развертывания.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. В свойстве шаблона укажите синтаксис шаблона.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": "West US",
              "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 и Подписка .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"
  },
  ...

В следующем шаблоне показано, как выражения шаблона разрешаются в соответствии с областью.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 зависимости от значения scope свойства в expressionEvaluationOptions .The value of exampleVar changes depending on the value of the scope property in expressionEvaluationOptions. В следующей таблице показаны результаты для обеих областей.The following table shows the results for both scopes.

expressionEvaluationOptions которыхexpressionEvaluationOptions scope Выходные данныеOutput
Внутреннееinner из вложенного шаблонаfrom nested template
внешний (или по умолчанию)outer (or default) из родительского шаблонаfrom parent template

В следующем примере выполняется развертывание SQL Server и получение секрета хранилища ключей, используемого для пароля.The following example deploys a SQL server and retrieves a key vault secret to use for the password. Область имеет значение, inner так как она динамически создает идентификатор хранилища ключей (см adminPassword.reference.keyVault . во внешних шаблонах parameters ) и передает его в качестве параметра вложенному шаблону.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": {
  }
}

Примечание

Если параметр scope имеет значение outer , нельзя использовать reference функцию в разделе Outputs вложенного шаблона для ресурса, развернутого во вложенном шаблоне.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.

Связанный шаблон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 deploys a new 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.windows.net/AzureTemplates/newStorageAccount.json",
          "contentVersion":"1.0.0.0"
        }
      }
    }
  ],
  "outputs": {
  }
}

При ссылке на связанный шаблон значение uri не должно быть локальным файлом или файлом, доступным только в локальной сети.When referencing a linked template, the value of uri must not be a local file or a file that is only available on your local network. Необходимо указать значение URI, которое можно скачать как http или HTTPS.You must provide a URI value that downloadable as http or https.

Примечание

Вы можете ссылаться на шаблоны с помощью параметров, которые в конечном итоге разрешаются для чего-либо, использующего http или HTTPS, например с помощью _artifactsLocation параметра следующим образом: "uri": "[concat(parameters('_artifactsLocation'), '/shared/os-disk-parts-md.json', parameters('_artifactsLocationSasToken'))]",You may reference templates using parameters that ultimately resolve to something that uses http or https, for example, using the _artifactsLocation parameter like so: "uri": "[concat(parameters('_artifactsLocation'), '/shared/os-disk-parts-md.json', parameters('_artifactsLocationSasToken'))]",

Диспетчер ресурсов должен иметь доступ к шаблону.Resource Manager must be able to access the template. Один из вариантов — разместить связанный шаблон в учетной записи хранения и использовать универсальный код ресурса (URI) этого элемента.One option is to place your linked template in a storage account, and use the URI for that item.

Параметры для связанного шаблона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.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"
    }
  }
  }
]

Чтобы передать значения параметров в строке, используйте свойство 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.windows.net/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.

Спецификации шаблонов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:

contentVersioncontentVersion

Вам не нужно указывать contentVersion свойство для templateLink parametersLink свойства или.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.

В предыдущих примерах были показаны жестко запрограммированные значения 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-адреса для связанных шаблонов на основе этого адреса.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 и 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": "[uri(variables('templateBaseUrl'), 'shared-resources.json')]",
  "vmTemplateUrl": "[uri(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')]"
}

В конечном счете, вы бы использовали переменную в uri свойстве templateLink Свойства.Ultimately, you would use the variable in the uri property of a templateLink property.

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

Использование инструкции 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. Или, если область является внутренней, можно добавить копию внутри вложенного шаблона.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": "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
      //}
      }
    ]
    }
  }
  }
]

Получение значений из связанного шаблона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": "2019-10-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]"
    }
  }
}

Как и в случае с другими типами ресурсов, можно задать зависимости между связанным шаблоном и другими ресурсами.As with other resource types, you can set dependencies between the linked template and other resources. Если другим ресурсам требуется выходное значение из связанного шаблона, убедитесь, что связанный шаблон развернут перед ними.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-адрес и возвращает идентификатор ресурса Azure для этого общедоступного IP-адреса: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": "eastus",
      "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": "eastus",
      "properties": {
        "frontendIPConfigurations": [
          {
            "name": "LoadBalancerFrontEnd",
            "properties": {
              "privateIPAllocationMethod": "Dynamic",
              "publicIPAddress": {
                // this is where the output value from linkedTemplate is used
                "id": "[reference('linkedTemplate').outputs.resourceID.value]"
              }
            }
          }
        ],
        "backendAddressPools": [],
        "loadBalancingRules": [],
        "probes": [],
        "inboundNatRules": [],
        "outboundNatRules": [],
        "inboundNatPools": []
      },
      // This is where the dependency is declared
      "dependsOn": [
        "linkedTemplate"
      ]
    },
    {
      "type": "Microsoft.Resources/deployments",
      "apiVersion": "2019-10-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')]"}
        }
      }
    }
  ]
}

Журнал развертыванияDeployment history

Resource Manager обрабатывает каждый шаблон как отдельное развертывание в журнале развертывания.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": "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/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)"
}

Или сценарий 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 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. Затем создайте маркер подписанного 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.

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

Для 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 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