Рекомендации по работе с шаблонами Azure Resource ManagerAzure Resource Manager template best practices

В этой статье представлены рекомендации о том, как создать шаблон Resource Manager.This article gives recommendations about how to construct your Resource Manager template. Эти рекомендации помогут избежать распространенных проблем при использовании шаблона для развертывания решения.These recommendations help you avoid common problems when using a template to deploy a solution.

Рекомендации по управлению подписками Azure см. в статье Корпоративный каркас Azure: рекомендуемая система управления подписками.For recommendations about how to govern your Azure subscriptions, see Azure enterprise scaffold: Prescriptive subscription governance.

Рекомендации о том, как создавать шаблоны, которые работают во всех облачных средах Azure, см. в статье Разработка шаблонов Azure Resource Manager для обеспечения согласованности с облаком.For recommendations about how to build templates that work in all Azure cloud environments, see Develop Azure Resource Manager templates for cloud consistency.

Ограничения шаблоновTemplate limits

Ограничьте размер шаблона до 4 МБ, а каждый файл параметров — до 64 КБ.Limit the size of your template to 4 MB, and each parameter file to 64 KB. Ограничение 4 МБ применяется к окончательному состоянию шаблона после его расширения с помощью итерационных определений ресурсов, а также значений переменных и параметров.The 4-MB limit applies to the final state of the template after it has been expanded with iterative resource definitions, and values for variables and parameters.

Кроме того, ограничение распространяется на:You're also limited to:

  • 256 параметров;256 parameters
  • 256 переменных;256 variables
  • 800 ресурсов (включая число копий);800 resources (including copy count)
  • 64 выходных значения;64 output values
  • 24 576 знаков в выражении шаблона.24,576 characters in a template expression

Некоторые ограничения можно превысить, используя вложенные шаблоны.You can exceed some template limits by using a nested template. Дополнительные сведения см. разделе Использование связанных шаблонов в при развертывании ресурсов Azure.For more information, see Using linked templates when deploying Azure resources. Чтобы уменьшить число параметров, переменных или выходных данных, можно объединить несколько значений в объект.To reduce the number of parameters, variables, or outputs, you can combine several values into an object. См. дополнительные сведения об использовании объектов как параметров.For more information, see Objects as parameters.

Группа ресурсовResource group

При развертывании ресурсов в группе ресурсов Группа ресурсов хранит метаданные о ресурсах.When you deploy resources to a resource group, the resource group stores metadata about the resources. Метаданные хранятся в расположении группы ресурсов.The metadata is stored in the location of the resource group.

Если регион группы ресурсов временно недоступен, вы не сможете обновить ресурсы в группе ресурсов, так как недоступны их метаданные.If the resource group's region is temporarily unavailable, you can't update resources in the resource group because the metadata is unavailable. Ресурсы в других регионах будут работать должным образом, но обновить их не получится.The resources in other regions will still function as expected, but you can't update them. Чтобы свести риск к минимуму, размещайте группу ресурсов и ресурсы в одном регионе.To minimize risk, locate your resource group and resources in the same region.

ПараметрыParameters

Здесь приведены некоторые рекомендации по работе с параметрами.The information in this section can be helpful when you work with parameters.

Общие рекомендации по работе с параметрамиGeneral recommendations for parameters

  • Используйте как можно меньше параметров.Minimize your use of parameters. Вместо этого используйте переменные или литеральные значения для свойств, которые не указываются во время развертывания.Instead, use variables or literal values for properties that don't need to be specified during deployment.

  • Имена для параметров необходимо указывать в нижнем регистре.Use camel case for parameter names.

  • Для настройки используйте параметры, которые отличаются в зависимости от среды, например, номер SKU, размер или емкость.Use parameters for settings that vary according to the environment, like SKU, size, or capacity.

  • Используйте параметры для имен ресурсов, которые вы хотите задать, чтобы упростить идентификацию.Use parameters for resource names that you want to specify for easy identification.

  • Укажите описание для каждого параметра в метаданных.Provide a description of every parameter in the metadata:

    "parameters": {
         "storageAccountType": {
             "type": "string",
             "metadata": {
                 "description": "The type of the new storage account created to store the VM disks."
             }
         }
    }
    
  • Укажите значения по умолчанию для конфиденциальных параметров.Define default values for parameters that aren't sensitive. Указав значение по умолчанию, проще развернуть шаблон, и пользователи шаблона будут видеть пример соответствующего значения.By specifying a default value, it's easier to deploy the template, and users of your template see an example of an appropriate value. Любое значение для параметра по умолчанию должно быть допустимым для всех пользователей в конфигурации развертывания по умолчанию.Any default value for a parameter must be valid for all users in the default deployment configuration.

    "parameters": {
          "storageAccountType": {
              "type": "string",
              "defaultValue": "Standard_GRS",
              "metadata": {
                  "description": "The type of the new storage account created to store the VM disks."
              }
          }
    }
    
  • Чтобы указать дополнительный параметр, не используйте пустую строку в качестве значения по умолчанию.To specify an optional parameter, don't use an empty string as a default value. Вместо этого используйте литеральное значение или выражение языка для составления значения.Instead, use a literal value or a language expression to construct a value.

    "storageAccountName": {
       "type": "string",
       "defaultValue": "[concat('storage', uniqueString(resourceGroup().id))]",
       "metadata": {
         "description": "Name of the storage account"
       }
    },
    
  • Не используйте параметр для версии API для типа ресурса.Don't use a parameter for the API version for a resource type. Свойства и значения ресурса могут отличаться для разных версий.Resource properties and values can vary by version number. Функции IntelliSense в редакторах кода не могут определить правильную схему, если версия API указана в качестве значения параметра.IntelliSense in a code editor can't determine the correct schema when the API version is set to a parameter. Вместо этого жестко задайте версию API в шаблоне.Instead, hard-code the API version in the template.

  • Используйте allowedValues только в крайнем случае.Use allowedValues sparingly. Используйте ее только в том случае, когда необходимо убедиться в том, что некоторые значения не включены в разрешенные параметры.Use it only when you must make sure some values aren't included in the permitted options. При излишнем использованием allowedValues допустимые развертывания можно заблокировать, не обновляя списка.If you use allowedValues too broadly, you might block valid deployments by not keeping your list up-to-date.

  • Если имя параметра в шаблоне совпадает с параметром в команде развертывания PowerShell, Resource Manager разрешает такие конфликты именования, добавляя постфикс FromTemplate к параметру шаблона.When a parameter name in your template matches a parameter in the PowerShell deployment command, Resource Manager resolves this naming conflict by adding the postfix FromTemplate to the template parameter. Предположим, вы добавили в шаблон параметр ResourceGroupName, и он конфликтует с параметром ResourceGroupName в командлете New-AzResourceGroupDeployment.For example, if you include a parameter named ResourceGroupName in your template, it conflicts with the ResourceGroupName parameter in the New-AzResourceGroupDeployment cmdlet. При развертывании вам будет предложено указать значение для параметра ResourceGroupNameFromTemplate.During deployment, you're prompted to provide a value for ResourceGroupNameFromTemplate.

Рекомендации по безопасности параметровSecurity recommendations for parameters

  • Всегда используйте параметры для имен пользователей и паролей (или секретов).Always use parameters for user names and passwords (or secrets).

  • Используйте securestring для всех паролей и секретов.Use securestring for all passwords and secrets. При передаче конфиденциальных данных в объекте JSON используйте тип secureObject.If you pass sensitive data in a JSON object, use the secureObject type. Параметры шаблона с типами строки и объекта безопасности невозможно считать после развертывания ресурса.Template parameters with secure string or secure object types can't be read after resource deployment.

    "parameters": {
         "secretValue": {
             "type": "securestring",
             "metadata": {
                 "description": "The value of the secret to store in the vault."
             }
         }
    }
    
  • Не указывайте значения по умолчанию для имен пользователей, паролей или любое значение, которое требует тип secureString.Don't provide default values for user names, passwords, or any value that requires a secureString type.

  • Не указывайте значения по умолчанию для свойств, позволяющих увеличить контактную зону для атаки на приложения.Don't provide default values for properties that increase the attack surface area of the application.

Рекомендации по расположению параметровLocation recommendations for parameters

  • Используйте параметр для указания расположения ресурсов и задайте значения по умолчанию для resourceGroup().location.Use a parameter to specify the location for resources, and set the default value to resourceGroup().location. Параметр расположения позволяет пользователям шаблона указывать расположение, на которое они имеют разрешение для развертывания.Providing a location parameter enables users of the template to specify a location that they have permission to deploy to.

    "parameters": {
       "location": {
         "type": "string",
         "defaultValue": "[resourceGroup().location]",
         "metadata": {
           "description": "The location in which the resources should be deployed."
         }
       }
    },
    
  • Не указывайте allowedValues для параметра расположения.Don't specify allowedValues for the location parameter. Указываемые расположения могут оказаться недоступными во всех облаках.The locations you specify might not be available in all clouds.

  • Используйте значение параметра расположения для ресурсов, которые могут находиться в одном расположении.Use the location parameter value for resources that are likely to be in the same location. Такой подход позволит реже обращаться к пользователю за информацией о расположении.This approach minimizes the number of times users are asked to provide location information.

  • Для ресурсов, которые недоступны во всех расположениях, используйте отдельный параметр или укажите литеральное значение расположения.For resources that aren't available in all locations, use a separate parameter or specify a literal location value.

ПеременныеVariables

Ниже приведены некоторые рекомендации по работе с переменными.The following information can be helpful when you work with variables:

  • Имена переменных следует заменять регистром Camel.Use camel case for variable names.

  • Применяйте переменные для значений, которые необходимо использовать в шаблоне более одного раза.Use variables for values that you need to use more than once in a template. Если значение используется только один раз, жестко задайте его. Это облегчит чтение шаблона.If a value is used only once, a hard-coded value makes your template easier to read.

  • Используйте переменные для значений, составленных на основе сложного упорядочения функций шаблонов.Use variables for values that you construct from a complex arrangement of template functions. Шаблон более удобный для считывания, когда сложное выражение отображается только в переменных.Your template is easier to read when the complex expression only appears in variables.

  • На ресурсе не используйте переменные для apiVersion.Don't use variables for apiVersion on a resource. Версия API определяет схему ресурса.The API version determines the schema of the resource. Часто невозможно изменить версию без изменения свойств ресурса.Often, you can't change the version without changing the properties for the resource.

  • Нельзя использовать функцию reference в разделе variables шаблона.You can't use the reference function in the variables section of the template. Функция reference получает свое значение из состояния среды выполнения ресурса,The reference function derives its value from the resource's runtime state. а переменные разрешаются при начальной обработке шаблона.However, variables are resolved during the initial parsing of the template. Сформируйте значения, которым требуется функция reference, непосредственно в разделе resources или outputs шаблона.Construct values that need the reference function directly in the resources or outputs section of the template.

  • Добавьте переменные для имен ресурсов, которые должны быть уникальными.Include variables for resource names that must be unique.

  • Используйте цикл копирования переменных, чтобы создать повторяющийся шаблон объектов JSON.Use a copy loop in variables to create a repeated pattern of JSON objects.

  • Удалите неиспользуемые переменные.Remove unused variables.

Зависимости ресурсовResource dependencies

Решая, какие зависимости следует установить, следуйте следующим рекомендациям.When deciding what dependencies to set, use the following guidelines:

  • Используйте функцию reference и передайте имя ресурса, чтобы задать неявные зависимости между ресурсами, которые должны совместно использовать свойство.Use the reference function and pass in the resource name to set an implicit dependency between resources that need to share a property. Не добавляйте явный элемент dependsOn, если неявная зависимость уже определена.Don't add an explicit dependsOn element when you've already defined an implicit dependency. Такой подход уменьшает риск появления ненужных зависимостей.This approach reduces the risk of having unnecessary dependencies.

  • Назначайте дочерний ресурс зависимым от его родительского ресурса.Set a child resource as dependent on its parent resource.

  • Ресурсы, в которых установлено значение элемента условия false, автоматически удаляются из порядка зависимостей.Resources with the condition element set to false are automatically removed from the dependency order. Назначайте зависимости так, как и при развернутом ресурсе.Set the dependencies as if the resource is always deployed.

  • Позвольте зависимостям задействоваться последовательно, не задавая их явно.Let dependencies cascade without setting them explicitly. Например, виртуальная машина зависит от виртуального сетевого интерфейса, а он зависит от виртуальной сети и общедоступных IP-адресов.For example, your virtual machine depends on a virtual network interface, and the virtual network interface depends on a virtual network and public IP addresses. Таким образом, виртуальная машина развертывается только после всех трех ресурсов, но эта зависимость виртуальной машины от них не задана явным образом.Therefore, the virtual machine is deployed after all three resources, but don't explicitly set the virtual machine as dependent on all three resources. Такой подход проясняет порядок зависимостей и упрощает последующее изменение шаблона.This approach clarifies the dependency order and makes it easier to change the template later.

  • Если значение может быть определено до развертывания, попробуйте развернуть ресурс без зависимостей.If a value can be determined before deployment, try deploying the resource without a dependency. Например, если в значении конфигурации требуется указать имя другого ресурса, можно обойтись и без зависимости.For example, if a configuration value needs the name of another resource, you might not need a dependency. Эта рекомендация не всегда уместна, так как некоторые ресурсы проверяют наличие другого ресурса.This guidance doesn't always work because some resources verify the existence of the other resource. Если произошла ошибка, добавьте зависимость.If you receive an error, add a dependency.

РесурсыResources

Ниже приведены некоторые рекомендации по работе с ресурсами.The following information can be helpful when you work with resources:

  • Чтобы другим участникам было проще понять назначение этого ресурса, укажите комментарии для каждого ресурса в шаблоне:To help other contributors understand the purpose of the resource, specify comments for each resource in the template:

    "resources": [
       {
           "name": "[variables('storageAccountName')]",
           "type": "Microsoft.Storage/storageAccounts",
           "apiVersion": "2019-06-01",
           "location": "[resourceGroup().location]",
           "comments": "This storage account is used to store the VM disks.",
           ...
       }
    ]
    
  • Если вы используете в шаблоне общедоступную конечную точку (например, общедоступную конечную точку хранилища BLOB-объектов Azure), то не следует жестко кодировать пространство имен.If you use a public endpoint in your template (such as an Azure Blob storage public endpoint), don't hard-code the namespace. Используйте функцию reference для динамического извлечения пространства имен.Use the reference function to dynamically retrieve the namespace. Вы можете использовать этот подход, чтобы развернуть шаблон в другом общедоступном пространстве имен, не изменяя конечную точку в шаблоне вручную.You can use this approach to deploy the template to different public namespace environments without manually changing the endpoint in the template. Задайте для версии API ту же версию, которая указана в учетной записи хранения в вашем шаблоне.Set the API version to the same version that you're using for the storage account in your template:

    "diagnosticsProfile": {
         "bootDiagnostics": {
             "enabled": "true",
             "storageUri": "[reference(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')), '2019-06-01').primaryEndpoints.blob]"
         }
    }
    

    Если учетная запись хранения развернута в том же создаваемом шаблоне, а имя учетной записи хранения не используется совместно с другим ресурсом в шаблоне, то при ссылке на ресурс не нужно указывать пространство имен поставщика или apiVersion.If the storage account is deployed in the same template that you're creating and the name of the storage account is not shared with another resource in the template, you don't need to specify the provider namespace or the apiVersion when you reference the resource. В следующем примере показан упрощенный синтаксис.The following example shows the simplified syntax:

    "diagnosticsProfile": {
         "bootDiagnostics": {
             "enabled": "true",
             "storageUri": "[reference(variables('storageAccountName')).primaryEndpoints.blob]"
         }
    }
    

    Вы также можете использовать функцию reference для ссылки на учетную запись хранения в другой группе ресурсов:You also can reference an existing storage account that is in a different resource group:

    "diagnosticsProfile": {
         "bootDiagnostics": {
             "enabled": "true",
             "storageUri": "[reference(resourceId(parameters('existingResourceGroup'), 'Microsoft.Storage/storageAccounts', parameters('existingStorageAccountName')), '2019-06-01').primaryEndpoints.blob]"
         }
    }
    
  • Назначайте общедоступные IP-адреса виртуальной машине только в том случае, если это требуется для работы приложения.Assign public IP addresses to a virtual machine only when an application requires it. Чтобы подключиться к виртуальной машине с целью отладки, управления или администрирования, используйте правила преобразования сетевых адресов для входящих подключений, шлюз виртуальной машины или jumpbox.To connect to a virtual machine (VM) for debugging, or for management or administrative purposes, use inbound NAT rules, a virtual network gateway, or a jumpbox.

    Дополнительные сведения о подключении к виртуальным машинам можно получить в приведенных ниже статьях.For more information about connecting to virtual machines, see:

  • Свойство DomainNameLabel для общедоступных IP-адресов должно быть уникальным.The domainNameLabel property for public IP addresses must be unique. Свойство domainNameLabel должно содержать то 3 до 63 знаков и соответствовать правилам, определенным этим регулярным выражением: ^[a-z][a-z0-9-]{1,61}[a-z0-9]$.The domainNameLabel value must be between 3 and 63 characters long, and follow the rules specified by this regular expression: ^[a-z][a-z0-9-]{1,61}[a-z0-9]$. Так как функция uniqueString создает строку длиной 13 знаков, в параметре dnsPrefixString можно использовать не более 50 знаков:Because the uniqueString function generates a string that is 13 characters long, the dnsPrefixString parameter is limited to 50 characters:

    "parameters": {
         "dnsPrefixString": {
             "type": "string",
             "maxLength": 50,
             "metadata": {
                 "description": "The DNS label for the public IP address. It must be lowercase. It should match the following regular expression, or it will raise an error: ^[a-z][a-z0-9-]{1,61}[a-z0-9]$"
             }
         }
    },
    "variables": {
         "dnsPrefix": "[concat(parameters('dnsPrefixString'),uniquestring(resourceGroup().id))]"
    }
    
  • При добавлении пароля в расширение пользовательских скриптов используйте свойство commandToExecute в protectedSettings:When you add a password to a custom script extension, use the commandToExecute property in the protectedSettings property:

    "properties": {
         "publisher": "Microsoft.Azure.Extensions",
         "type": "CustomScript",
         "typeHandlerVersion": "2.0",
         "autoUpgradeMinorVersion": true,
         "settings": {
             "fileUris": [
                 "[concat(variables('template').assets, '/lamp-app/install_lamp.sh')]"
             ]
         },
         "protectedSettings": {
             "commandToExecute": "[concat('sh install_lamp.sh ', parameters('mySqlPassword'))]"
         }
    }
    

    Примечание

    Чтобы обеспечить шифрование секретов, которые передаются как параметры в виртуальные машины и расширения, необходимо использовать свойство protectedSettings соответствующих расширений.To ensure that secrets are encrypted when they are passed as parameters to VMs and extensions, use the protectedSettings property of the relevant extensions.

Выходные данныеOutputs

Если вы используете шаблон, чтобы создать общедоступные IP-адреса, добавьте раздел outputs, который возвращает сведения об IP-адресе и полное доменное имя (FQDN).If you use a template to create public IP addresses, include an outputs section that returns details of the IP address and the fully qualified domain name (FQDN). С помощью этих выходных данных можно легко получить сведения об общедоступных IP-адресах и полных доменных именах после развертывания.You can use output values to easily retrieve details about public IP addresses and FQDNs after deployment.

"outputs": {
    "fqdn": {
        "value": "[reference(parameters('publicIPAddresses_name')).dnsSettings.fqdn]",
        "type": "string"
    },
    "ipaddress": {
        "value": "[reference(parameters('publicIPAddresses_name')).ipAddress]",
        "type": "string"
    }
}

Следующие шагиNext steps