您现在访问的是微软AZURE全球版技术文档网站,若需要访问由世纪互联运营的MICROSOFT AZURE中国区技术文档网站,请访问 https://docs.azure.cn.

Azure 资源管理器模板最佳做法Azure Resource Manager template best practices

本文提供有关如何构造资源管理器模板的建议。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 Enterprise 基架:出于合规目的监管订阅For recommendations about how to govern your Azure subscriptions, see Azure enterprise scaffold: Prescriptive subscription governance.

有关如何生成在所有 Azure 云环境中工作的模板的建议,请参阅开发用于实现云一致性的 Azure 资源管理器模板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 MB 以内,每个参数文件大小限制为 64 KB 以内。Limit the size of your template to 4 MB, and each parameter file to 64 KB. 4-MB 限制适用于模板使用迭代资源定义以及变量和参数值进行扩展后的最终状态。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.

ParametersParameters

使用参数时,本部分中的信息可以提供帮助。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. 如果将 API 版本设置为参数,代码编辑器中的 IntelliSense 无法确定正确架构。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.

  • 请尽量少使用 allowedValuesUse 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 部署命令中的参数相同时,资源管理器会将 postfix 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”的参数,则该参数会与 New-AzResourceGroupDeployment cmdlet 中的“ResourceGroupName”参数冲突。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).

  • 为所有密码和机密使用 securestringUse securestring for all passwords and secrets. 如果将敏感数据传入 JSON 对象,请使用 secureObject 类型。If you pass sensitive data in a JSON object, use the secureObject type. 部署资源后,无法读取带 secureString 或 secureObject 类型的模板参数。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().locationUse 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."
         }
       }
    },
    
  • 请勿为位置参数指定 allowedValuesDon'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:

  • 对变量名称使用混合大小写。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 函数。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. 直接在模板的 resourcesoutputs 节中构造需要 reference 函数的值。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.

  • 会自动从依赖项顺序中删除 condition 元素设置为 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.",
           ...
       }
    ]
    
  • 如果在模板中使用“公共终结点”(例如 Azure Blob 存储公共终结点),请不要将命名空间硬编码。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]"
         }
    }
    

    如果在创建的同一模板中部署存储帐户,且存储帐户的名称不与模板中的其他资源共享,则在引用资源时,无需指定 provider 命名空间或 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]"
         }
    }
    

    还可以引用不同资源组中的现有存储帐户: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. 若要连接到虚拟机 (VM) 进行调试或管理,请使用出站 NAT 规则、虚拟网络网关或 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:

  • 公共 IP 地址的 domainNameLabel 属性必须唯一。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))]"
    }
    
  • 将密码添加到自定义脚本扩展时,请在 protectedSettings 属性中使用 commandToExecute 属性: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'))]"
         }
    }
    

    备注

    为了确保机密内容作为参数传递给 VM 和扩展时经过加密,请使用相关扩展的 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.

outputsOutputs

如果使用模板创建公共 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 地址和 FQDN 的详细信息。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