通过 ARM 模板和 Azure CLI 来部署资源Deploy resources with ARM templates and Azure CLI

本文介绍了如何将 Azure CLI 与 Azure 资源管理器模板(ARM 模板)配合使用,以便将资源部署到 Azure。This article explains how to use Azure CLI with Azure Resource Manager templates (ARM templates) to deploy your resources to Azure. 如果不熟悉部署和管理 Azure 解决方案的概念,请参阅模版部署概述If you aren't familiar with the concepts of deploying and managing your Azure solutions, see template deployment overview.

部署命令在 Azure CLI 版本 2.2.0 中已更改。The deployment commands changed in Azure CLI version 2.2.0. 本文中的示例需要 Azure CLI 2.2.0 或更高版本。The examples in this article require Azure CLI version 2.2.0 or later.

若要运行此示例,请安装最新版本的 Azure CLITo run this sample, install the latest version of the Azure CLI. 若要开始,请运行 az login 以创建与 Azure 的连接。To start, run az login to create a connection with Azure.

适用于 Azure CLI 的示例是针对 bash shell 编写的。Samples for the Azure CLI are written for the bash shell. 若要在 Windows PowerShell 或命令提示符中运行此示例,可能需要更改脚本的元素。To run this sample in Windows PowerShell or Command Prompt, you may need to change elements of the script.

备注

在 Azure China 中使用 Azure CLI 2.0 之前,请首先运行 az cloud set -n AzureChinaCloud 更改云环境。Before you can use Azure CLI 2.0 in Azure China, please run az cloud set -n AzureChinaCloud first to change the cloud environment. 如果要切换回全局 Azure,请再次运行 az cloud set -n AzureCloudIf you want to switch back to Global Azure, run az cloud set -n AzureCloud again.

部署范围Deployment scope

可将部署目标设定为资源组、订阅、管理组或租户。You can target your deployment to a resource group, subscription, management group, or tenant. 大多数情况下,我们会将以资源组指定为部署目标。In most cases, you'll target deployment to a resource group. 若要在更大范围内应用策略和角色分配,请使用订阅、管理组或租户部署。To apply policies and role assignments across a larger scope, use subscription, management group, or tenant deployments. 部署到订阅时,可以创建资源组并将资源部署到该资源组。When deploying to a subscription, you can create a resource group and deploy resources to it.

根据部署范围使用不同的命令。Depending on the scope of the deployment, you use different commands.

本文中的示例使用资源组部署。The examples in this article use resource group deployments.

部署本地模板Deploy local template

将资源部署到 Azure 时,执行以下操作:When deploying resources to Azure, you:

  1. 登录到 Azure 帐户Sign in to your Azure account
  2. 创建用作已部署资源的容器的资源组。Create a resource group that serves as the container for the deployed resources. 资源组名称只能包含字母数字字符、句点、下划线、连字符和括号。The name of the resource group can only include alphanumeric characters, periods, underscores, hyphens, and parenthesis. 它最多可以包含 90 个字符。It can be up to 90 characters. 它不能以句点结尾。It can't end in a period.
  3. 将定义了要创建的资源的模板部署到资源组。Deploy to the resource group the template that defines the resources to create.

模板可以包括可用于自定义部署的参数。A template can include parameters that enable you to customize the deployment. 例如,可以提供为特定环境(如开发环境、测试环境和生产环境)定制的值。For example, you can provide values that are tailored for a particular environment (such as dev, test, and production). 示例模板定义了存储帐户 SKU 的参数。The sample template defines a parameter for the storage account SKU.

以下示例将创建一个资源组,并从本地计算机部署模板:The following example creates a resource group, and deploys a template from your local machine:

az group create --name ExampleGroup --location "China North"
az deployment group create \
  --name ExampleDeployment \
  --resource-group ExampleGroup \
  --template-file storage.json \
  --parameters storageAccountType=Standard_GRS

部署可能需要几分钟才能完成。The deployment can take a few minutes to complete. 完成之后,会看到一条包含以下结果的消息:When it finishes, you see a message that includes the result:

"provisioningState": "Succeeded",

部署名称Deployment name

在前面的示例中,你已将部署命名为 ExampleDeploymentIn the preceding example, you named the deployment ExampleDeployment. 如果没有为部署提供名称,将使用模板文件的名称。If you don't provide a name for the deployment, the name of the template file is used. 例如,如果部署一个名为 azuredeploy.json 的模板,但未指定部署名称,则该部署将命名为 azuredeployFor example, if you deploy a template named azuredeploy.json and don't specify a deployment name, the deployment is named azuredeploy.

每次运行部署时,一个包含部署名称的条目会添加到资源组的部署历史记录中。Every time you run a deployment, an entry is added to the resource group's deployment history with the deployment name. 如果运行另一个部署并为其指定了相同的名称,则会将先前的条目替换为当前部署。If you run another deployment and give it the same name, the earlier entry is replaced with the current deployment. 如果要在部署历史记录中保持唯一条目,请为每个部署指定唯一名称。If you want to maintain unique entries in the deployment history, give each deployment a unique name.

若要创建唯一名称,你可以分配一个随机数。To create a unique name, you can assign a random number.

deploymentName='ExampleDeployment'$RANDOM

或者,添加日期值。Or, add a date value.

deploymentName='ExampleDeployment'$(date +"%d-%b-%Y")

如果使用相同的部署名称对同一资源组运行并发部署,则仅会完成最后一个部署。If you run concurrent deployments to the same resource group with the same deployment name, only the last deployment is completed. 尚未完成的具有相同名称的任何部署都将被最后一个部署所替换。Any deployments with the same name that haven't finished are replaced by the last deployment. 例如,如果你运行一个名为 newStorage 的部署,它部署了一个名为 storage1 的存储帐户;与此同时,你运行了另一个名为 newStorage 的部署,它部署了一个名为 storage2 的存储帐户,则你将仅部署一个存储帐户。For example, if you run a deployment named newStorage that deploys a storage account named storage1, and at the same time run another deployment named newStorage that deploys a storage account named storage2, you deploy only one storage account. 生成的存储帐户名为 storage2The resulting storage account is named storage2.

但是,如果你运行一个名为 newStorage 的部署,它部署了一个名为 storage1 的存储帐户;在该部署完成时你又立即运行了另一个名为 newStorage 的部署,它部署了一个名为 storage2 的存储帐户,则你将有两个存储帐户。However, if you run a deployment named newStorage that deploys a storage account named storage1, and immediately after it completes you run another deployment named newStorage that deploys a storage account named storage2, then you have two storage accounts. 一个名为 storage1,另一个名为 storage2One is named storage1, and the other is named storage2. 但是,部署历史记录中只有一个条目。But, you only have one entry in the deployment history.

为每个部署指定唯一的名称时,可以并发运行它们而不会发生冲突。When you specify a unique name for each deployment, you can run them concurrently without conflict. 如果你运行一个名为 newStorage1 的部署,它部署了一个名为 storage1 的存储帐户;与此同时,你又运行了另一个名为 newStorage2 的部署,它部署了一个名为 storage2 的存储帐户,则部署历史记录中将有两个存储帐户和两个条目。If you run a deployment named newStorage1 that deploys a storage account named storage1, and at the same time run another deployment named newStorage2 that deploys a storage account named storage2, then you have two storage accounts and two entries in the deployment history.

为避免与并发部署冲突并确保部署历史记录中的条目是唯一的,请为每个部署指定唯一的名称。To avoid conflicts with concurrent deployments and to ensure unique entries in the deployment history, give each deployment a unique name.

部署远程模板Deploy remote template

你可能更愿意将 ARM 模板存储在外部位置,而不是存储在本地计算机上。Instead of storing ARM templates on your local machine, you may prefer to store them in an external location. 可以将模板存储在源控件存储库(例如 GitHub)中。You can store templates in a source control repository (such as GitHub). 另外,还可以将其存储在 Azure 存储帐户中,以便在组织中共享访问。Or, you can store them in an Azure storage account for shared access in your organization.

若要部署外部模板,请使用 template-uri 参数。To deploy an external template, use the template-uri parameter. 使用示例中的 URI 从 GitHub 部署示例模板。Use the URI in the example to deploy the sample template from GitHub.

az group create --name ExampleGroup --location "China North"
az deployment group create \
  --name ExampleDeployment \
  --resource-group ExampleGroup \
  --template-uri "https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/101-storage-account-create/azuredeploy.json" \
  --parameters storageAccountType=Standard_GRS

前面的示例要求模板的 URI 可公开访问,它适用于大多数情况,因为模板应该不会包含敏感数据。The preceding example requires a publicly accessible URI for the template, which works for most scenarios because your template shouldn't include sensitive data. 如果需要指定敏感数据(如管理员密码),请以安全参数的形式传递该值。If you need to specify sensitive data (like an admin password), pass that value as a secure parameter. 但是,如果不希望模板可公开访问,可以通过将其存储在专用存储容器中来保护它。However, if you don't want your template to be publicly accessible, you can protect it by storing it in a private storage container. 若要了解如何部署需要共享访问签名 (SAS) 令牌的模板,请参阅部署具有 SAS 令牌的专用模板For information about deploying a template that requires a shared access signature (SAS) token, see Deploy private template with SAS token.

预览更改Preview changes

在部署模板之前,可以预览模板将对环境做出的更改。Before deploying your template, you can preview the changes the template will make to your environment. 使用假设操作验证模板是否进行了预期的更改。Use the what-if operation to verify that the template makes the changes that you expect. 模拟操作还验证模板是否有错误。What-if also validates the template for errors.

在本地 Shell 中使用以下命令Use the following commands in your local Shell

az group create --name examplegroup --location "China East"
az deployment group create --resource-group examplegroup \
  --template-uri <copied URL> \
  --parameters storageAccountType=Standard_GRS

parametersParameters

若要传递参数值,可以使用内联参数或参数文件。To pass parameter values, you can use either inline parameters or a parameter file.

内联参数。Inline parameters

若要传递内联参数,请在 parameters 中提供值。To pass inline parameters, provide the values in parameters. 例如,若要在 Bash shell 中将字符串和数组传递给模板,请使用:For example, to pass a string and array to a template is a Bash shell, use:

az deployment group create \
  --resource-group testgroup \
  --template-file demotemplate.json \
  --parameters exampleString='inline string' exampleArray='("value1", "value2")'

如果要将 Azure CLI 与 Windows 命令提示符 (CMD) 或 PowerShell 配合使用,请以以下格式传递数组:exampleArray="['value1','value2']"If you're using Azure CLI with Windows Command Prompt (CMD) or PowerShell, pass the array in the format: exampleArray="['value1','value2']".

还可以获取文件的内容并将该内容作为内联参数提供。You can also get the contents of file and provide that content as an inline parameter.

az deployment group create \
  --resource-group testgroup \
  --template-file demotemplate.json \
  --parameters exampleString=@stringContent.txt exampleArray=@arrayContent.json

当需要提供配置值时,从文件中获取参数值非常有用。Getting a parameter value from a file is helpful when you need to provide configuration values. 例如,可以为 Linux 虚拟机提供 cloud-init 值For example, you can provide cloud-init values for a Linux virtual machine.

arrayContent.json 格式为:The arrayContent.json format is:

[
    "value1",
    "value2"
]

若要传入对象(例如用于设置标记),请使用 JSON。To pass in an object, for example, to set tags, use JSON. 例如,模板可能包含如下所示的参数:For example, your template might include a parameter like this one:

    "resourceTags": {
      "type": "object",
      "defaultValue": {
        "Cost Center": "IT Department"
      }
    }

在这种情况下,可以传入 JSON 字符串来设置参数,如以下 Bash 脚本中所示:In this case, you can pass in a JSON string to set the parameter as shown in the following Bash script:

tags='{"Owner":"Contoso","Cost Center":"2345-324"}'
az deployment group create --name addstorage  --resource-group myResourceGroup \
--template-file $templateFile \
--parameters resourceName=abcdef4556 resourceTags="$tags"

在要传递给对象的 JSON 两侧使用双引号。Use double quotes around the JSON that you want to pass into the object.

参数文件Parameter files

你可能会发现,与在脚本中以内联值的形式传递参数相比,使用包含参数值的 JSON 文件更为容易。Rather than passing parameters as inline values in your script, you may find it easier to use a JSON file that contains the parameter values. 参数文件必须是本地文件。The parameter file must be a local file. Azure CLI 不支持外部参数文件。External parameter files aren't supported with Azure CLI.

有关参数文件的详细信息,请参阅创建资源管理器参数文件For more information about the parameter file, see Create Resource Manager parameter file.

若要传递本地参数文件,请使用 @ 指定名为 storage.parameters.json 的本地文件。To pass a local parameter file, use @ to specify a local file named storage.parameters.json.

az deployment group create \
  --name ExampleDeployment \
  --resource-group ExampleGroup \
  --template-file storage.json \
  --parameters @storage.parameters.json

处理扩展 JSON 格式Handle extended JSON format

若要使用 Azure CLI 2.3.0 或更低版本部署包含多行字符串或注释的模板,必须使用 --handle-extended-json-format 开关。To deploy a template with multi-line strings or comments using Azure CLI with version 2.3.0 or older, you must use the --handle-extended-json-format switch. 例如:For example:

{
  "type": "Microsoft.Compute/virtualMachines",
  "apiVersion": "2018-10-01",
  "name": "[variables('vmName')]", // to customize name, change it in variables
  "location": "[
    parameters('location')
    ]", //defaults to resource group location
  /*
    storage account and network interface
    must be deployed first
  */
  "dependsOn": [
    "[resourceId('Microsoft.Storage/storageAccounts/', variables('storageAccountName'))]",
    "[resourceId('Microsoft.Network/networkInterfaces/', variables('nicName'))]"
  ],

后续步骤Next steps