开发用于确保云一致性的 ARM 模板Develop ARM templates for cloud consistency

重要

使用 PowerShell 的 Azure 功能必须已安装 AzureRM 模块。Using this Azure feature from PowerShell requires the AzureRM module installed. 该模块是旧模块,仅适用于 Windows PowerShell 5.1,它不再接收新功能。This is an older module only available for Windows PowerShell 5.1 that no longer receives new features. 针对相同版本的 PowerShell 进行安装时,AzAzureRM 模块不兼容。The Az and AzureRM modules are not compatible when installed for the same versions of PowerShell. 如果需要两个版本,请执行以下操作:If you need both versions:

  1. 在 PowerShell 5.1 会话中卸载 Az 模块Uninstall the Az module from a PowerShell 5.1 session.
  2. 在 PowerShell 5.1 会话中安装 AzureRM 模块Install the AzureRM module from a PowerShell 5.1 session.
  3. 下载并安装 PowerShell Core 6.x 或更高版本Download and install PowerShell Core 6.x or later.
  4. 在 PowerShell Core 会话中安装 Az 模块Install the Az module in a PowerShell Core session.

Azure 的主要优势是一致性。A key benefit of Azure is consistency. 一个位置的开发投入可在另一个位置重复使用。Development investments for one location are reusable in another. Azure 资源管理器 (ARM) 模板可确保部署在全球 Azure、Azure 主权云和 Azure Stack 等环境中保持一致性和可重复性。An Azure Resource Manager (ARM) template makes your deployments consistent and repeatable across environments, including the global Azure, Azure sovereign clouds, and Azure Stack. 若要在各种云中重复使用模板,需要参照本指南的说明,考虑特定于云的依赖关系。To reuse templates across clouds, however, you need to consider cloud-specific dependencies as this guide explains.

Azure 在很多位置提供了面向企业的智能云服务,其中包括:Azure offers intelligent, enterprise-ready cloud services in many locations, including:

  • 全球 Azure 平台,该平台由全球各区域不断扩大的 Azure 托管数据中心网络提供支持。The global Azure platform supported by a growing network of Azure-managed datacenters in regions around the world.

  • 独立主权云,例如 Azure 德国、Azure 美国政府和 Azure 中国世纪互联。Isolated sovereign clouds like Azure Germany, Azure US Government, and Azure China 21Vianet. 主权云提供具有大部分相同的强大功能的一致平台,全球 Azure 客户均有权访问。Sovereign clouds provide a consistent platform with most of the same great features that global Azure customers have access to.

  • Azure Stack,一种混合云平台,可从组织数据中心提供 Azure 服务。Azure Stack, a hybrid cloud platform that lets you deliver Azure services from your organization's datacenter. 企业可以在自己的数据中心中设置 Azure Stack,或者使用服务提供商提供的 Azure 服务,在他们的设施(有时称为托管区域)中运行 Azure Stack。Enterprises can set up Azure Stack in their own datacenters, or consume Azure Services from service providers, running Azure Stack in their facilities (sometimes known as hosted regions).

在所有这些云的核心,Azure 资源管理器提供一个 API,用于实现各种用户界面与 Azure 平台的通信。At the core of all these clouds, Azure Resource Manager provides an API that allows a wide variety of user interfaces to communicate with the Azure platform. 此 API 提供了强大的基础结构即代码功能。This API gives you powerful infrastructure-as-code capabilities. 使用 Azure 资源管理器可以部署和配置 Azure 云平台上提供的任何类型的资源。Any type of resource that is available on the Azure cloud platform can be deployed and configured with Azure Resource Manager. 只用一个模板即可将完整的应用程序部署和配置为操作结束状态。With a single template, you can deploy and configure your complete application to an operational end state.

Azure 环境

全球 Azure、主权云、托管云以及你的数据中心的云具有一致性,可帮助你从 Azure 资源管理器中受益。The consistency of global Azure, the sovereign clouds, hosted clouds, and a cloud in your datacenter helps you benefit from Azure Resource Manager. 在设置了基于模板的资源部署和配置后,就可以在这些云中重复使用部署投入。You can reuse your development investments across these clouds when you set up template-based resource deployment and configuration.

然而,即使全球云、主权云、托管云和混合云提供一致的服务,也不是所有云都相同。However, even though the global, sovereign, hosted, and hybrid clouds provide consistent services, not all clouds are identical. 因此,可以创建对仅特定云可以提供的功能具有依赖关系的模板。As a result, you can create a template with dependencies on features available only in a specific cloud.

本指南的其余部分介绍在计划开发新的或更新现有的适用于 Azure Stack 的 ARM 模板时需要考虑的方面。The rest of this guide describes the areas to consider when planning to develop new or updating existing ARM templates for Azure Stack. 一般情况下,注意事项应包括以下各项:In general, your checklist should include the following items:

  • 验证模板中的函数、终结点、服务和其他资源在目标部署位置是否可用。Verify that the functions, endpoints, services, and other resources in your template are available in the target deployment locations.
  • 将嵌套模板和配置项目存储在可访问的位置,确保可以跨云访问。Store nested templates and configuration artifacts in accessible locations, ensuring access across clouds.
  • 使用动态引用,不要使用硬编码链接和元素。Use dynamic references instead of hard-coding links and elements.
  • 请确保使用的模板参数适用于目标云。Ensure the template parameters you use work in the target clouds.
  • 验证特定于资源的属性在目标云中是否可用。Verify that resource-specific properties are available the target clouds.

有关 ARM 模板的简介,请参阅模板部署For an introduction to ARM templates, see Template deployment.

确保模板函数可用Ensure template functions work

ARM 模板的基本语法为 JSON。The basic syntax of an ARM template is JSON. 模板使用 JSON 的超集,通过表达式和函数扩展语法。Templates use a superset of JSON, extending the syntax with expressions and functions. 模板语言处理器经常更新以支持附加的模板函数。The template language processor is frequently updated to support additional template functions. 有关可用模板函数的详细说明,请参阅 ARM 模板函数For a detailed explanation of the available template functions, see ARM template functions.

Azure 资源管理器中引入的新模板函数在主权云或 Azure Stack 中不会立即可用。New template functions that are introduced to Azure Resource Manager aren't immediately available in the sovereign clouds or Azure Stack. 要成功部署模板,模板中引用的所有函数都必须在目标云中可用。To deploy a template successfully, all functions referenced in the template must be available in the target cloud.

Azure 资源管理器的功能始终会首先引入到全球 Azure。Azure Resource Manager capabilities will always be introduced to global Azure first. 使用以下 PowerShell 脚本可以验证新引入的模板函数在 Azure Stack 中是否可用:You can use the following PowerShell script to verify whether newly introduced template functions are also available in Azure Stack:

  1. 克隆 GitHub 存储库:https://github.com/marcvaneijk/arm-template-functionsMake a clone of the GitHub repository: https://github.com/marcvaneijk/arm-template-functions.

  2. 本地克隆存储库后,使用 PowerShell 连接到目标的 Azure 资源管理器。Once you have a local clone of the repository, connect to the destination's Azure Resource Manager with PowerShell.

  3. 导入 psm1 模块并执行 Test-AzureRmTemplateFunctions cmdlet:Import the psm1 module and execute the Test-AzureRmTemplateFunctions cmdlet:

    # Import the module
    Import-module <path to local clone>\AzTemplateFunctions.psm1
    
    # Execute the Test-AzureRmTemplateFunctions cmdlet
    Test-AzureRmTemplateFunctions -path <path to local clone> -location chinanorth
    

该脚本部署多个最小化模板,每个模板仅包含唯一的模板函数。The script deploys multiple, minimized templates, each containing only unique template functions. 脚本的输出报告受支持的和不可用的模板函数。The output of the script reports the supported and unavailable template functions.

使用链接项目Working with linked artifacts

模板可以包含对链接项目的引用以及链接到另一个模板的部署资源。A template can contain references to linked artifacts and contain a deployment resource that links to another template. 资源管理器在运行时会检索链接模板(也称为嵌套模板)。The linked templates (also referred to as nested template) are retrieved by Resource Manager at runtime. 模板也可以包含对虚拟机 (VM) 扩展的项目的引用。A template can also contain references to artifacts for virtual machine (VM) extensions. 在 VM 内运行的 VM 扩展会检索这些项目,以便在目标部署过程中配置 VM 扩展These artifacts are retrieved by the VM extension running inside of the VM for configuration of the VM extension during the template deployment.

以下部分介绍在开发模板过程中,当该模板包含与主要部署模板不相关的项目时云一致性的注意事项。The following sections describe considerations for cloud consistency when developing templates that include artifacts that are external to the main deployment template.

跨区域使用嵌套模板Use nested templates across regions

模板可以分解为可重复使用的小模板,每个小模板都有特定用途,可以在各种部署方案中重复使用。Templates can be decomposed into small, reusable templates, each of which has a specific purpose and can be reused across deployment scenarios. 要执行部署,请指定一个模板作为主要模板或主模板。To execute a deployment, you specify a single template known as the main or master template. 该模板指定要部署的资源,例如虚拟网络、VM 和 Web 应用。It specifies the resources to deploy, such as virtual networks, VMs, and web apps. 主要模板还可以包含指向另一个模板的链接,这意味着可以嵌套模板。The main template can also contain a link to another template, meaning you can nest templates. 同样,嵌套模板可以包含指向其他模板的链接。Likewise, a nested template can contain links to other templates. 嵌套深度可达五级。You can nest up to five levels deep.

以下代码展示了 templateLink 参数如何引用嵌套模板:The following code shows how the templateLink parameter refers to a nested template:

"resources": [
  {
     "type": "Microsoft.Resources/deployments",
     "apiVersion": "2017-05-10",
     "name": "linkedTemplate",
     "properties": {
       "mode": "incremental",
       "templateLink": {
          "uri":"https://mystorageaccount.blob.core.chinacloudapi.cn/AzureTemplates/vNet.json",
          "contentVersion":"1.0.0.0"
       }
     }
  }
]

Azure 资源管理器在运行时评估主要模板并检索和评估每个嵌套模板。Azure Resource Manager evaluates the main template at runtime and retrieves and evaluates each nested template. 检索了所有嵌套模板后,将平展模板并开始进一步处理。After all nested templates are retrieved, the template is flattened, and further processing is initiated.

使链接模板可跨云访问Make linked templates accessible across clouds

请考虑所用的任何链接模板的存储位置和方式。Consider where and how to store any linked templates you use. 在运行时,Azure 资源管理器会提取任意链接模板,因此需要该模板的直接访问权限。At runtime, Azure Resource Manager fetches—and therefore requires direct access to—any linked templates. 常见的一种做法是使用 GitHub 存储嵌套模板。A common practice is to use GitHub to store the nested templates. GitHub 存储库可以包含可通过 URL 公开访问的文件。A GitHub repository can contain files that are accessible publicly through a URL. 虽然此方法适用于公有云和主权云,但 Azure Stack 环境可能位于企业网络或断开连接的远程位置,无任何出站 Internet 访问权限。Although this technique works well for the public cloud and the sovereign clouds, an Azure Stack environment might be located on a corporate network or on a disconnected remote location, without any outbound Internet access. 在这些情况下,Azure 资源管理器无法检索嵌套模板。In those cases, Azure Resource Manager would fail to retrieve the nested templates.

适合跨云部署的更好做法是将链接模板存储在目标云可访问的位置。A better practice for cross-cloud deployments is to store your linked templates in a location that is accessible for the target cloud. 理想情况是在持续集成/持续开发 (CI/CD) 管道中维护和部署所有部署项目。Ideally all deployment artifacts are maintained in and deployed from a continuous integration/continuous development (CI/CD) pipeline. 或者,可以将嵌套模板存储在 blob 存储容器中,Azure 资源管理器可从其中检索它们。Alternatively, you can store nested templates in a blob storage container, from which Azure Resource Manager can retrieve them.

由于每个云上的 blob 存储使用不同的终结点完全限定的域名 (FQDN),因此请使用两个参数配置具有链接模板位置的模板。Since the blob storage on each cloud uses a different endpoint fully qualified domain name (FQDN), configure the template with the location of the linked templates with two parameters. 参数可以接受部署时的用户输入。Parameters can accept user input at deployment time. 模板一般由多人创作和共享,因此最佳做法是对这些参数使用标准名称。Templates are typically authored and shared by multiple people, so a best practice is to use a standard name for these parameters. 命名约定有助于提高模板在区域、云和作者之间的可重用性。Naming conventions help make templates more reusable across regions, clouds, and authors.

在以下代码中,_artifactsLocation 用于指向一个包含与部署相关的所有项目的位置。In the following code, _artifactsLocation is used to point to a single location, containing all deployment-related artifacts. 请注意,提供的是默认值。Notice that a default value is provided. 在部署时,如果没有为 _artifactsLocation 指定输入值,则使用默认值。At deployment time, if no input value is specified for _artifactsLocation, the default value is used. _artifactsLocationSasToken 用作 sasToken 的输入。The _artifactsLocationSasToken is used as input for the sasToken. _artifactsLocation 未受保护的情况下(例如公共 GitHub 存储库),默认值应为空字符串。The default value should be an empty string for scenarios where the _artifactsLocation isn't secured — for example, a public GitHub repository.

"parameters": {
  "_artifactsLocation": {
    "type": "string",
    "metadata": {
      "description": "The base URI where artifacts required by this template are located."
    },
    "defaultValue": "https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/201-vm-custom-script-windows/"
  },
  "_artifactsLocationSasToken": {
    "type": "securestring",
    "metadata": {
      "description": "The sasToken required to access _artifactsLocation."
    },
    "defaultValue": ""
  }
}

在整个模板中,将基 URI(来自 _artifactsLocation 参数)与项目相对路径和 _artifactsLocationSasToken 合并可生成链接。Throughout the template, links are generated by combining the base URI (from the _artifactsLocation parameter) with an artifact-relative path and the _artifactsLocationSasToken. 以下代码演示如何使用 uri 模板函数指定嵌套模板的链接:The following code shows how to specify the link to the nested template using the uri template function:

"resources": [
  {
    "type": "Microsoft.Resources/deployments",
    "apiVersion": "2019-10-01",
    "name": "shared",
    "properties": {
      "mode": "Incremental",
      "templateLink": {
        "uri": "[uri(parameters('_artifactsLocation'), concat('nested/vnet.json', parameters('_artifactsLocationSasToken')))]",
        "contentVersion": "1.0.0.0"
      }
    }
  }
]

_artifactsLocation 参数的默认值通过上述方式使用。By using this approach, the default value for the _artifactsLocation parameter is used. 如果需要从其他位置检索链接模板,则参数输入在部署时可用于重写默认值 - 无需更改模板本身。If the linked templates need to be retrieved from a different location, the parameter input can be used at deployment time to override the default value—no change to the template itself is needed.

_artifactsLocation 参数中的 URL 除了用于嵌套模板,还可用作部署模板的所有相关项目的基。Besides being used for nested templates, the URL in the _artifactsLocation parameter is used as a base for all related artifacts of a deployment template. 某些 VM 扩展包含存储在模板外的脚本的链接。Some VM extensions include a link to a script stored outside the template. 对于这些扩展,不应对链接进行硬编码。For these extensions, you should not hardcode the links. 例如,自定义脚本和 PowerShell DSC 扩展可能链接到 GitHub 上的外部脚本,如下所示:For example, the Custom Script and PowerShell DSC extensions may link to an external script on GitHub as shown:

"properties": {
  "publisher": "Microsoft.Compute",
  "type": "CustomScriptExtension",
  "typeHandlerVersion": "1.9",
  "autoUpgradeMinorVersion": true,
  "settings": {
    "fileUris": [
      "https://raw.githubusercontent.com/Microsoft/dotnet-core-sample-templates/master/dotnet-core-music-windows/scripts/configure-music-app.ps1"
    ]
  }
}

对脚本的链接进行硬编码可能会阻止模板成功部署到另一个位置。Hardcoding the links to the script potentially prevents the template from deploying successfully to another location. 在配置 VM 资源期间,VM 内运行的 VM 代理开始下载 VM 扩展中链接的的所有脚本,然后将脚本存储在 VM 的本地磁盘上。During configuration of the VM resource, the VM agent running inside the VM initiates a download of all the scripts linked in the VM extension, and then stores the scripts on the VM's local disk. 此方法的作用类似于之前在“跨区域使用嵌套模板”部分介绍的嵌套模板链接。This approach functions like the nested template links explained earlier in the "Use nested templates across regions" section.

资源管理器在运行时检索嵌套模板。Resource Manager retrieves nested templates at runtime. 对于 VM 扩展,由 VM 代理检索任何外部项目。For VM extensions, the retrieval of any external artifacts is performed by the VM agent. 除了项目检索的发起程序不同,模板定义中的解决方案都是相同的。Besides the different initiator of the artifact retrieval, the solution in the template definition is the same. 将 _artifactsLocation 参数与存储所有项目(包括 VM 扩展脚本)的基路径的默认值和 sasToken 的输入的 _artifactsLocationSasToken 参数结合使用。Use the _artifactsLocation parameter with a default value of the base path where all the artifacts are stored (including the VM extension scripts) and the _artifactsLocationSasToken parameter for the input for the sasToken.

"parameters": {
  "_artifactsLocation": {
    "type": "string",
    "metadata": {
      "description": "The base URI where artifacts required by this template are located."
    },
    "defaultValue": "https://raw.githubusercontent.com/Microsoft/dotnet-core-sample-templates/master/dotnet-core-music-windows/"
  },
  "_artifactsLocationSasToken": {
    "type": "securestring",
    "metadata": {
      "description": "The sasToken required to access _artifactsLocation."
    },
    "defaultValue": ""
  }
}

要构造项目的绝对 URI,首选方法是使用 uri 模板函数,而不是 concat 模板函数。To construct the absolute URI of an artifact, the preferred method is to use the uri template function, instead of the concat template function. 通过将 VM 扩展中经过硬编码的脚本链接替换为 uri 模板函数,可配置模板中的此功能以实现云一致性。By replacing hardcoded links to the scripts in the VM extension with the uri template function, this functionality in the template is configured for cloud consistency.

"properties": {
  "publisher": "Microsoft.Compute",
  "type": "CustomScriptExtension",
  "typeHandlerVersion": "1.9",
  "autoUpgradeMinorVersion": true,
  "settings": {
    "fileUris": [
      "[uri(parameters('_artifactsLocation'), concat('scripts/configure-music-app.ps1', parameters('_artifactsLocationSasToken')))]"
    ]
  }
}

使用此方法,包括配置脚本在内的所有部署项目均可存储在模板本身所在的位置。With this approach, all deployment artifacts, including configuration scripts, can be stored in the same location with the template itself. 若要更改所有链接的位置,只需为 _artifactsLocation 参数_指定其他基 URL。To change the location of all the links, you only need to specify a different base URL for the artifactsLocation parameters.

区分区域功能的因素Factor in differing regional capabilities

由于敏捷开发以及各种更新和新服务不断引入 Azure,区域可能在服务和更新的可用性方面有所差异With the agile development and continuous flow of updates and new services introduced to Azure, regions can differ in availability of services or updates. 经过严格的内部测试之后,通常向参与验证计划的小范围受众客户推介新服务或现有服务的更新。After rigorous internal testing, new services or updates to existing services are usually introduced to a small audience of customers participating in a validation program. 客户验证成功后,就会在部分 Azure 区域中提供服务或更新,然后引入到更多区域,推广到主权云,甚至还可能提供给 Azure Stack 的客户。After successful customer validation, the services or updates are made available within a subset of Azure regions, then introduced to more regions, rolled out to the sovereign clouds, and potentially made available for Azure Stack customers as well.

  • 在全球 Azure 云上创建时会产生 mystorageaccount1.blob.core.windows.net。mystorageaccount1.blob.core.windows.net when created on the global Azure cloud.

  • 在 Azure 中国世纪互联云创建时会产生 mystorageaccount1.blob.core.chinacloudapi.cn。mystorageaccount1.blob.core.chinacloudapi.cn when created in the Azure China 21Vianet cloud.

以下引用模板函数从存储资源提供程序中检索终结点命名空间:The following reference template function retrieves the endpoint namespace from the storage resource provider:

"diskUri":"[concat(reference(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))).primaryEndpoints.blob, 'container/myosdisk.vhd')]"

通过将存储帐户终结点的硬编码值替换为 reference 模板函数,可以使用同一个模板成功部署到不同环境,无需对终结点引用进行任何更改。By replacing the hardcoded value of the storage account endpoint with the reference template function, you can use the same template to deploy to different environments successfully without making any changes to the endpoint reference.

通过唯一 ID 引用现有资源Refer to existing resources by unique ID

还可以从同一或另一个资源组、在同一或另一订阅中以及在同一云的同一租户中引用现有资源。You can also refer to an existing resource from the same or another resource group, and within the same subscription or another subscription, within the same tenant in the same cloud. 要检索资源属性,必须使用该资源本身的唯一标识符。To retrieve the resource properties, you must use the unique identifier for the resource itself. 如以下代码所示,resourceId 模板函数检索 SQL Server 等资源的唯一 ID:The resourceId template function retrieves the unique ID of a resource such as SQL Server as the following code shows:

"outputs": {
  "resourceId":{
    "type": "string",
    "value": "[resourceId('otherResourceGroup', 'Microsoft.Sql/servers', parameters('serverName'))]"
  }
}

然后,可以使用 reference 模板函数中的 resourceId 函数检索数据库的属性。You can then use the resourceId function inside the reference template function to retrieve the properties of a database. 返回对象包含保留完整终结点值的 fullyQualifiedDomainName 属性。The return object contains the fullyQualifiedDomainName property that holds the full endpoint value. 该值在运行时检索,并提供特定于云环境的终结点命名空间。This value is retrieved at runtime and provides the cloud environment-specific endpoint namespace. 若要在不对终结点命名空间硬编码的情况下定义连接字符串,可以直接引用连接字符串中返回对象的属性,如下所示:To define the connection string without hardcoding the endpoint namespace, you can refer to the property of the return object directly in the connection string as shown:

"[concat('Server=tcp:', reference(resourceId('sql', 'Microsoft.Sql/servers', parameters('test')), '2015-05-01-preview').fullyQualifiedDomainName, ',1433;Initial Catalog=', parameters('database'),';User ID=', parameters('username'), ';Password=', parameters('pass'), ';Encrypt=True;')]"

考虑资源属性Consider resource properties

Azure Stack 环境中的特定资源具有独特属性,必须在模板中考虑这些属性。Specific resources within Azure Stack environments have unique properties you must consider in your template.

确保 VM 映像可用Ensure VM images are available

Azure 提供丰富的精选 VM 映像。Azure provides a rich selection of VM images. 这些映像已创建并准备好,可以供 Azure 和合作伙伴部署。These images are created and prepared for deployment by Azure and partners. 这些映像构成平台上 VM 的基础。The images form the foundation for VMs on the platform. 但云一致模板应该仅引用可用的参数 - 尤其是可用于全球 Azure、Azure 主权云或 Azure Stack 的 VM 映像的发布服务器、套餐和 SKU。However, a cloud-consistent template should refer to available parameters only — in particular, the publisher, offer, and SKU of the VM images available to the global Azure, Azure sovereign clouds, or an Azure Stack solution.

要检索位置中的可用 VM 映像列表,请运行以下 Azure CLI 命令:To retrieve a list of the available VM images in a location, run the following Azure CLI command:

az vm image list --all

可以使用 Azure PowerShell cmdlet Get-AzureRmVMImagePublisher 检索同一列表并使用 -Location 参数指定想要的位置。You can retrieve the same list with the Azure PowerShell cmdlet Get-AzureRmVMImagePublisher and specify the location you want with the -Location parameter. 例如:For example:

Get-AzureRmVMImagePublisher -Location "China North" | Get-AzureRmVMImageOffer | Get-AzureRmVMImageSku | Get-AzureRmVMImage

此命令需要几分钟时间在 Azure 中国云的“中国北部”区域返回所有可用的映像。This command takes a couple of minutes to return all the available images in the China North region of the Azure China cloud.

如果向 Azure Stack 提供这些 VM 映像,则会占用所有可用的存储。If you made these VM images available to Azure Stack, all the available storage would be consumed. 为了可以容纳最小的缩放单元,Azure Stack 允许选择所需的映像添加到环境。To accommodate even the smallest scale unit, Azure Stack allows you to select the images you want to add to an environment.

以下代码示例演示了在 ARM 模板中引用发布服务器、产品/服务和 SKU 参数的一致方法:The following code sample shows a consistent approach to refer to the publisher, offer, and SKU parameters in your ARM templates:

"storageProfile": {
    "imageReference": {
    "publisher": "MicrosoftWindowsServer",
    "offer": "WindowsServer",
    "sku": "2016-Datacenter",
    "version": "latest"
    }
}

检查本地 VM 大小Check local VM sizes

为了开发用于实现云一致性的模板,需要确保所有目标环境可提供所需的 VM 大小。To develop your template for cloud consistency, you need to make sure the VM size you want is available in all target environments. VM 大小是性能特征和功能的分组。VM sizes are a grouping of performance characteristics and capabilities. 某些 VM 大小取决于 VM 运行的硬件。Some VM sizes depend on the hardware that the VM runs on. 例如,如果要部署 GPU 优化的 VM,则运行虚拟机监控程序的硬件需要具有 GPU 硬件。For example, if you want to deploy a GPU-optimized VM, the hardware that runs the hypervisor needs to have the hardware GPUs.

当 Azure 引入了新的 VM 大小,且该大小具有某种硬件依赖关系时,通常会首先在 Azure 云中的一小部分区域提供该 VM 大小。When Azure introduces a new size of VM that has certain hardware dependencies, the VM size is usually made available first in a small subset of regions in the Azure cloud. 随后,向其他区域和云提供。Later, it is made available to other regions and clouds. 为了确保该 VM 大小在要部署到的每个云中存在,可以使用以下 Azure CLI 命令检索可用的大小:To make sure the VM size exists in each cloud you deploy to, you can retrieve the available sizes with the following Azure CLI command:

az vm list-sizes --location "China North"

对于 Azure PowerShell,请使用:For Azure PowerShell, use:

Get-AzureRmVMSize -Location "China North"

如需可用服务的完整列表,请参阅可用产品(按区域)For a full list of available services, see Products available by region.

检查 Azure Stack 中 Azure 托管磁盘的使用情况Check use of Azure Managed Disks in Azure Stack

托管磁盘管理 Azure 租户的存储。Managed disks handle the storage for an Azure tenant. 在部署 VM 时,可以使用使用托管磁盘隐式执行这些操作,而不是显式创建存储帐户并指定虚拟硬盘 (VHD) 的 URI。Instead of explicitly creating a storage account and specifying the URI for a virtual hard disk (VHD), you can use managed disks to implicitly perform these actions when you deploy a VM. 托管磁盘通过将同一可用性集的 VM 中的所有磁盘都放置在不同的存储单元中来提高可用性。Managed disks enhance availability by placing all the disks from VMs in the same availability set into different storage units. 此外,现有的 VHD 可从标准转换为高级存储,显著减少了停机时间。Additionally, existing VHDs can be converted from Standard to Premium storage with significantly less downtime.

虽然托管磁盘已在 Azure Stack 的路线图上,但它们当前不受支持。Although managed disks are on the roadmap for Azure Stack, they are currently not supported. 到它们可受支持时,你可以在 VM 资源的模板中使用 vhd 元素显式指定 VHD,以此方式开发适用于 Azure Stack 的云一致模板,如下所示:Until they are, you can develop cloud-consistent templates for Azure Stack by explicitly specifying VHDs using the vhd element in the template for the VM resource as shown:

"storageProfile": {
  "imageReference": {
    "publisher": "MicrosoftWindowsServer",
    "offer": "WindowsServer",
    "sku": "[parameters('windowsOSVersion')]",
    "version": "latest"
  },
  "osDisk": {
    "name": "osdisk",
    "vhd": {
      "uri": "[concat(reference(resourceId('Microsoft.Storage/storageAccounts/', variables('storageAccountName')), '2015-06-15').primaryEndpoints.blob, 'vhds/osdisk.vhd')]"
    },
    "caching": "ReadWrite",
    "createOption": "FromImage"
  }
}

与此相反,要在模板中指定托管磁盘配置,请从磁盘配置删除 vhd 元素。In contrast, to specify a managed disk configuration in a template, remove the vhd element from the disk configuration.

"storageProfile": {
  "imageReference": {
    "publisher": "MicrosoftWindowsServer",
    "offer": "WindowsServer",
    "sku": "[parameters('windowsOSVersion')]",
    "version": "latest"
  },
  "osDisk": {
    "caching": "ReadWrite",
    "createOption": "FromImage"
  }
}

相同的更改也适用于数据磁盘The same changes also apply data disks.

验证 VM 扩展在 Azure Stack 中是否使用Verify that VM extensions are available in Azure Stack

云一致性的另一个注意事项是使用虚拟机扩展配置 VM 内的资源。Another consideration for cloud consistency is the use of virtual machine extensions to configure the resources inside a VM. 并非所有的 VM 扩展在 Azure Stack 均可用Not all VM extensions are available in Azure Stack. 模板可指定专用于 VM 扩展的资源,从而在模板内创建依赖关系和条件。A template can specify the resources dedicated to the VM extension, creating dependencies and conditions within the template.

例如,如果要配置运行 Microsoft SQL Server 的 VM,VM 扩展可以配置 SQL Server 作为模板部署的一部分。For example, if you want to configure a VM running Microsoft SQL Server, the VM extension can configure SQL Server as part the template deployment. 如果部署模板也包含配置为在运行 SQL Server 的 VM 上创建数据库的应用程序服务器,想象一下会发生什么情况。Consider what happens if the deployment template also contains an application server configured to create a database on the VM running SQL Server. 除了使用应用程序服务器的 VM 扩展外,还可以在成功返回 SQL Server VM 扩展资源时配置应用程序服务器的依赖关系。Besides also using a VM extension for the application servers, you can configure the dependency of the application server on the successful return of the SQL Server VM extension resource. 此方法可确保在指示应用程序服务器创建数据库时,运行 SQL Server 的 VM 已配置并且可用。This approach ensures the VM running SQL Server is configured and available when the application server is instructed to create the database.

通过模板的声明性方法可以定义资源的最终状态及其相互依赖的关系,同时平台可以处理依赖关系所需的逻辑。The declarative approach of the template allows you to define the end state of the resources and their inter-dependencies, while the platform takes care of the logic required for the dependencies.

检查 VM 扩展是否可用Check that VM extensions are available

存在很多类型的 VM 扩展。Many types of VM extensions exist. 在开发用于实现云一致性的模板时,请务必仅使用在模板的所有目标区域均可用的扩展。When developing template for cloud consistency, make sure to use only the extensions that are available in all the regions the template targets.

要检索可用于特定区域(在本示例中为 myLocation)的 VM 扩展列表,请运行以下 Azure CLI 命令:To retrieve a list of the VM extensions that are available for a specific region (in this example, myLocation), run the following Azure CLI command:

az vm extension image list --location myLocation

此外还可执行 Azure PowerShell Get-AzureRmVmImagePublisher cmdlet,并使用 -Location 指定虚拟机映像的位置。You can also execute the Azure PowerShell Get-AzureRmVmImagePublisher cmdlet and use -Location to specify the location of the virtual machine image. 例如:For example:

Get-AzureRmVmImagePublisher -Location myLocation | Get-AzureRmVMExtensionImageType | Get-AzureRmVMExtensionImage | Select Type, Version

请确保该版本可用Ensure that versions are available

由于 VM 扩展是第一方资源管理器资源,因此它们具有自己的 API 版本。Since VM extensions are first-party Resource Manager resources, they have their own API versions. 如以下代码所示,VM 扩展类型是 Microsoft.Compute 资源提供程序中的嵌套资源。As the following code shows, the VM extension type is a nested resource in the Microsoft.Compute resource provider.

{
    "type": "Microsoft.Compute/virtualMachines/extensions",
    "apiVersion": "2015-06-15",
    "name": "myExtension",
    "location": "[parameters('location')]",
    ...

VM 扩展资源的 API 版本必须存在于你模板中计划的所有目标位置。The API version of the VM extension resource must be present in all the locations you plan to target with your template. 位置依赖关系的作用类似于之前在“验证所有资源类型的版本”部分讨论的资源提供程序 API 版本的可用性。The location dependency works like the resource provider API version availability discussed earlier in the "Verify the version of all resource types" section.

要检索 VM 扩展资源的可用 API 版本列表,请将 Get-AzureRmResourceProvider cmdlet 与 Microsoft.Compute 资源提供程序结合使用,如下所示:To retrieve a list of the available API versions for the VM extension resource, use the Get-AzureRmResourceProvider cmdlet with the Microsoft.Compute resource provider as shown:

Get-AzureRmResourceProvider -ProviderNamespace "Microsoft.Compute" | Select-Object -ExpandProperty ResourceTypes | Select ResourceTypeName, Locations, ApiVersions | where {$_.ResourceTypeName -eq "virtualMachines/extensions"}

在虚拟机规模集中还可以使用 VM 扩展。You can also use VM extensions in virtual machine scale sets. 适用相同的位置条件。The same location conditions apply. 为了开发用于实现云一致性的模板,请确保 API 版本在计划部署到的所有位置中均可用。To develop your template for cloud consistency, make sure the API versions are available in all the locations you plan on deploying to. 要检索规模集的 VM 扩展资源的 API 版本,请使用与之前相同的 cmdlet,但要指定虚拟机规模集资源类型,如下所示:To retrieve the API versions of the VM extension resource for scale sets, use the same cmdlet as before, but specify the virtual machine scale sets resource type as shown:

Get-AzureRmResourceProvider -ProviderNamespace "Microsoft.Compute" | Select-Object -ExpandProperty ResourceTypes | Select ResourceTypeName, Locations, ApiVersions | where {$_.ResourceTypeName -eq "virtualMachineScaleSets/extensions"}

每个特定的扩展也会进行版本控制。Each specific extension is also versioned. 此版本在 VM 扩展的 typeHandlerVersion 属性中显示。This version is shown in the typeHandlerVersion property of the VM extension. 请确保在模板的 VM 扩展的 typeHandlerVersion 元素中指定的版本在计划部署模板的位置中可用。Make sure that the version specified in the typeHandlerVersion element of your template's VM extensions are available in the locations where you plan to deploy the template. 例如,以下代码指定版本 1.7:For example, the following code specifies version 1.7:

{
    "type": "extensions",
    "apiVersion": "2016-03-30",
    "name": "MyCustomScriptExtension",
    "location": "[parameters('location')]",
    "dependsOn": [
        "[concat('Microsoft.Compute/virtualMachines/myVM', copyindex())]"
    ],
    "properties": {
        "publisher": "Microsoft.Compute",
        "type": "CustomScriptExtension",
        "typeHandlerVersion": "1.7",
        ...

要检索特定 VM 扩展的可用版本列表,请使用 Get AzureRmVMExtensionImage cmdlet。To retrieve a list of the available versions for a specific VM extension, use the Get-AzureRmVMExtensionImage cmdlet. 以下示例从 myLocation 检索 PowerShell DSC(所需状态配置)VM 扩展的可用版本:The following example retrieves the available versions for the PowerShell DSC (Desired State Configuration) VM extension from myLocation:

Get-AzureRmVMExtensionImage -Location myLocation -PublisherName Microsoft.PowerShell -Type DSC | FT

要获取发布者列表,请使用 Get-AzureRmVmImagePublisher 命令。To get a list of publishers, use the Get-AzureRmVmImagePublisher command. 要请求类型,请使用 Get AzureRmVMExtensionImageType 命令。To request type, use the Get-AzureRmVMExtensionImageType commend.

用于测试和自动化的提示Tips for testing and automation

在创作模板时跟踪所有相关的设置、功能和限制是一项挑战。It's a challenge to keep track of all related settings, capabilities, and limitations while authoring a template. 常见方法是针对单个云开发和测试模板,然后再针对其他位置。The common approach is to develop and test templates against a single cloud before other locations are targeted. 然而,在创作过程中越早执行测试,开发团队就会进行越少的故障排除和代码重写。However, the earlier that tests are performed in the authoring process, the less troubleshooting and code rewriting your development team will have to do. 由于位置依赖关系而失败的部署在故障排除时非常耗时。Deployments that fail because of location dependencies can be time-consuming to troubleshoot. 因此,建议在创作周期中尽早执行自动测试。That's why we recommend automated testing as early as possible in the authoring cycle. 从根本上讲,你需要使用更少的开发时间和更少的资源,云一致的项目就会变得更有价值。Ultimately, you'll need less development time and fewer resources, and your cloud-consistent artifacts will become even more valuable.

下图展示了团队使用集成开发环境 (IDE) 的开发过程的典型示例。The following image shows a typical example of a development process for a team using an integrated development environment (IDE). 在时间线中的不同阶段执行不同的测试类型。At different stages in the timeline, different test types are executed. 在这里,两名开发者正在处理同一解决方案,但这种情况同样适用于单个开发者或一个大型团队。Here, two developers are working on the same solution, but this scenario applies equally to a single developer or a large team. 每个开发者通常会创建中央存储库的本地副本,这样每个人都可以处理本地副本,并且不会影响可能使用同一文件的其他用户。Each developer typically creates a local copy of a central repository, enabling each one to work on the local copy without impacting the others who may be working on the same files.

Workflow Workflow

请考虑以下用于测试和自动化的提示:Consider the following tips for testing and automation:

  • 务必使用测试工具。Do make use of testing tools. 例如,Visual Studio Code 和 Visual Studio 包括 IntelliSense 以及可帮助你验证模板的其他功能。For example, Visual Studio Code and Visual Studio include IntelliSense and other features that can help you validate your templates.
  • 要在本地 IDE 上进行开发期间提高代码质量,请通过单元测试和集成测试执行静态代码分析。To improve the code quality during development on the local IDE, perform static code analysis with unit tests and integration tests.
  • 为了在初始开发期间获得更好的体验,单元测试和集成测试应仅在发现问题时发出警告,然后继续进行测试。For an even better experience during initial development, unit tests and integration tests should only warn when an issue is found and proceed with the tests. 这样一来,可以确定要解决的问题并设置更改的优先顺序,也称为测试驱动的部署 (TDD)。That way, you can identify the issues to addressed and prioritize the order of the changes, also referred to as test-driven deployment (TDD).
  • 请注意,在未连接到 Azure 资源管理器的情况下也可执行某些测试。Be aware that some tests can be performed without being connected to Azure Resource Manager. 其他测试(如测试模板部署)需要资源管理器执行的某些操作无法脱机完成。Others, like testing template deployment, require Resource Manager to perform certain actions that cannot be performed offline.
  • 针对验证 API 测试部署模板不等于实际的部署。Testing a deployment template against the validation API isn't equal to an actual deployment. 此外,即使从本地文件部署模板,资源管理器也会直接检索对模板中嵌套模板的任何引用,并且在部署的 VM 内运行的 VM 代理也会检索 VM 扩展引用的项目。Also, even if you deploy a template from a local file, any references to nested templates in the template are retrieved by Resource Manager directly, and artifacts referenced by VM extensions are retrieved by the VM agent running inside the deployed VM.

后续步骤Next steps