ARM 模板部署 What-if 操作

在部署 Azure 资源管理器模板(ARM 模板)之前,可以预览将要进行的更改。 Azure 资源管理器提供 what-if(假设)操作,让你在部署模板时了解资源发生的更改。 what-if 操作不会对现有资源进行任何更改, 而是预测在部署指定的模板时发生的更改。

可将 what-if 操作与 Azure PowerShell、Azure CLI 或 REST API 操作配合使用。 资源组、订阅、管理组合租户级部署支持 What-if。

安装 Azure PowerShell 模块

若要在 PowerShell 中使用 what-if,则必须安装 Az 模块 4.2 或更高版本。

若要安装该模块,请使用:

Install-Module -Name Az -Force

若要详细了解如何安装模块,请参阅安装 Azure PowerShell

安装 Azure CLI 模块

若要在 Azure CLI 中使用 what-if,则必须安装 Azure CLI 2.14.0 或更高版本。 如果需要,请安装 Azure CLI 的最新版本

查看结果

在 PowerShell 或 Azure CLI 中使用 what-if 时,输出包含进行了颜色编码的结果,方便你查看不同类型的更改。

资源管理器模板部署 what-if 操作 fullresourcepayloads 和更改类型

文本输出如下:

Resource and property changes are indicated with these symbols:
  - Delete
  + Create
  ~ Modify

The deployment will update the following scope:

Scope: /subscriptions/./resourceGroups/ExampleGroup

  ~ Microsoft.Network/virtualNetworks/vnet-001 [2018-10-01]
    - tags.Owner: "Team A"
    ~ properties.addressSpace.addressPrefixes: [
      - 0: "10.0.0.0/16"
      + 0: "10.0.0.0/15"
      ]
    ~ properties.subnets: [
      - 0:

          name:                     "subnet001"
          properties.addressPrefix: "10.0.0.0/24"

      ]

Resource changes: 1 to modify.

备注

What-if 操作无法解析引用函数。 每次将属性设置为包含引用函数的模板表达式时,What-if 都会报告属性将改变。 发生此行为的原因是,What-if 将属性的当前值(如布尔值 truefalse)与未解析的模板表达式进行比较。 很明显,这些值不匹配。 部署模板时,只有在模板表达式解析为其他值时,属性才会更改。

what-if 命令

Azure PowerShell

若要在部署模板前预览更改,请使用 New-AzResourceGroupDeploymentNew-AzSubscriptionDeployment。 将 -Whatif 开关参数添加到部署命令。

  • 对于资源组部署,请使用 New-AzResourceGroupDeployment -Whatif
  • 对于订阅级别的部署,请使用 New-AzSubscriptionDeployment -WhatifNew-AzDeployment -Whatif

可使用 -Confirm 开关参数来预览所做的更改,让系统显示是否继续部署的提示。

  • 对于资源组部署,请使用 New-AzResourceGroupDeployment -Confirm
  • 对于订阅级别的部署,请使用 New-AzSubscriptionDeployment -ConfirmNew-AzDeployment -Confirm

上述命令返回适用于手动检查的文本摘要。 若要获取可通过编程方式检查更改的对象,请使用 Get-AzResourceGroupDeploymentWhatIfResultGet-AzSubscriptionDeploymentWhatIfResult

  • 对于资源组部署,请使用 $results = Get-AzResourceGroupDeploymentWhatIfResult
  • 对于订阅级别的部署,请使用 $results = Get-AzSubscriptionDeploymentWhatIfResult$results = Get-AzDeploymentWhatIfResult

Azure CLI

若要在部署模板前预览更改,请使用:

可以使用 --confirm-with-what-if 开关(或其缩写形式 -c)预览更改,并让系统显示是否继续部署的提示。 将此开关添加到:

例如,对于资源组部署,请使用 az deployment group create --confirm-with-what-if-c

上述命令返回适用于手动检查的文本摘要。 若要获取可通过编程方式检查更改的 JSON 对象,请使用 --no-pretty-print 开关。 例如,对于资源组部署,请使用 az deployment group what-if --no-pretty-print

若要返回没有颜色的结果,请打开 Azure CLI 配置文件。 将“no_color”设置为“yes”。

Azure REST API

对于 REST API,请使用:

更改类型

what-if 操作列出六种不同的更改类型:

  • 创建:资源当前不存在,但已在模板中定义。 将创建该资源。

  • 删除:仅当为部署使用 完整模式时,此更改类型才适用。 资源存在,但未在模板中定义。 使用完整模式时,将删除该资源。 此更改类型仅包括支持完整模式删除的资源。

  • 忽略:资源存在,但未在模板中定义。 不会部署或修改资源。

  • 无更改:资源存在,且已在模板中定义。 将重新部署资源,但资源的属性不会更改。 当 ResultFormat 设置为 FullResourcePayloads(默认值)时,将返回此更改类型。

  • 修改:资源存在,且已在模板中定义。 将重新部署资源,且资源的属性会更改。 当 ResultFormat 设置为 FullResourcePayloads(默认值)时,将返回此更改类型。

  • 部署:资源存在,且已在模板中定义。 将重新部署资源。 资源的属性可能会更改,也可能不会更改。 当没有足够的信息来确定是否有任何属性发生更改时,操作将返回此更改类型。 仅当 ResultFormat 设置为 ResourceIdOnly 时,才会看到此状况。

结果格式

控制返回的有关预测更改的详细信息级别。 可以使用两个选项:

  • FullResourcePayloads - 返回将会更改的资源的列表,以及将会更改的属性的相关详细信息。
  • ResourceIdOnly - 返回将会更改的资源列表

默认值为 FullResourcePayloads。

对于 PowerShell 部署命令,请使用 -WhatIfResultFormat 参数。 在编程对象命令中,使用 ResultFormat 参数。

对于 Azure CLI,请使用 --result-format 参数。

以下结果显示了两种不同的输出格式:

  • 完整资源有效负载

    Resource and property changes are indicated with these symbols:
      - Delete
      + Create
      ~ Modify
    
    The deployment will update the following scope:
    
    Scope: /subscriptions/./resourceGroups/ExampleGroup
    
      ~ Microsoft.Network/virtualNetworks/vnet-001 [2018-10-01]
        - tags.Owner: "Team A"
        ~ properties.addressSpace.addressPrefixes: [
          - 0: "10.0.0.0/16"
          + 0: "10.0.0.0/15"
          ]
        ~ properties.subnets: [
          - 0:
    
            name:                     "subnet001"
            properties.addressPrefix: "10.0.0.0/24"
    
          ]
    
    Resource changes: 1 to modify.
    
  • 仅限资源 ID

    Resource and property changes are indicated with this symbol:
      ! Deploy
    
    The deployment will update the following scope:
    
    Scope: /subscriptions/./resourceGroups/ExampleGroup
    
      ! Microsoft.Network/virtualNetworks/vnet-001
    
    Resource changes: 1 to deploy.
    

运行 what-if 操作

设置环境

为了了解 what-if 的工作原理,让我们运行一些测试。 首先,部署一个用于创建虚拟网络的模板。 将使用此虚拟网络来测试 what-if 如何报告更改。

备注

当我们使用以 https://raw.githubusercontent.com/ 开头的指定模板文件 URI 部署资源时,控制台有时会生成错误,如 Unable to download deployment content

可以执行以下操作来解决相应问题。

  1. 复制模板 URI,通过更改前缀、中缀和模板文件名来转换 URI。 例如,源 URI 是 https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/101-cosmosdb-sql-autoscale/azuredeploy.json

    类别 原始值 转换后的值 操作
    前缀 https://raw.githubusercontent.com https://github.com 更新
    中辍 blob mastermain 之前添加分支名称
    模板文件名 azuredeploy.json 你的下载模板文件名 update

    修改后,转换后的 URI 看起来将类似于 https://github.com/Azure/azure-quickstart-templates/blob/master/101-cosmosdb-sql-autoscale/azuredeploy.json

    请注意,某些模板 URI 已更新为 https://github.com/Azure/azure-quickstart-template/quickstarts/{Microsoft_Resource_Provider_Name}/ ,你可以按照相应的路径规定来更新原始 URI。

  2. 复制转换后的 URI,并在 Internet 浏览器中手动下载特定的模板内容。

  3. 修改从 GitHub 存储库下载或引用的模板,以适应 Azure 中国世纪互联环境。 例如,替换某些终结点(将“blob.core.windows.net”替换为“blob.core.chinacloudapi.cn”,将“cloudapp.azure.com”替换为“chinacloudapp.cn”);必要时更改某些不受支持的位置、VM 映像、VM 大小、SKU 以及资源提供程序的 API 版本。

  4. 将参数 -TemplateUri 替换为 -TemplateFile(对于 powershell)或将参数 --template-uri 替换为 --template-file(针对 CLI),然后用已下载的实际文件名称更新指定的 URI,然后重新运行脚本。

    语言类别 参考链接 操作
    PowerShell New-AzResourceGroupDeployment -TemplateUri 替换为 -TemplateFile
    如有必要,请按照前面的步骤下载 --TemplateParameterUri 内容并在 cmdlet 中替换为 --TemplateParameterFile
    Azure CLI az deployment group create --template-uri 替换为 --template-file
New-AzResourceGroup `
  -Name ExampleGroup `
  -Location chinaeast
New-AzResourceGroupDeployment `
  -ResourceGroupName ExampleGroup `
  -TemplateUri "https://raw.githubusercontent.com/Azure/azure-docs-json-samples/master/azure-resource-manager/what-if/what-if-before.json"

测试修改

部署完成后,即可测试 what-if 操作。 这一次,将部署一个用于更改虚拟网络的模板。 该模板中缺少一个原始标记,已删除了一个子网,并且已更改了地址前缀。

New-AzResourceGroupDeployment `
  -Whatif `
  -ResourceGroupName ExampleGroup `
  -TemplateUri "https://raw.githubusercontent.com/Azure/azure-docs-json-samples/master/azure-resource-manager/what-if/what-if-after.json"

what-if 输出类似于:

资源管理器模板部署 what-if 操作输出

文本输出如下:

Resource and property changes are indicated with these symbols:
  - Delete
  + Create
  ~ Modify

The deployment will update the following scope:

Scope: /subscriptions/./resourceGroups/ExampleGroup

  ~ Microsoft.Network/virtualNetworks/vnet-001 [2018-10-01]
    - tags.Owner: "Team A"
    ~ properties.addressSpace.addressPrefixes: [
      - 0: "10.0.0.0/16"
      + 0: "10.0.0.0/15"
      ]
    ~ properties.subnets: [
      - 0:

        name:                     "subnet001"
        properties.addressPrefix: "10.0.0.0/24"

      ]

Resource changes: 1 to modify.

请注意,输出顶部的颜色用于指示更改类型。

输出的底部显示了“已删除所有者”标记。 地址前缀已从 10.0.0.0/16 更改为 10.0.0.0/15。 已删除名为 subnet001 的子网。 请记住,这些更改并未部署。 如果部署该模板,则可预览会发生的更改。

列出为已删除的某些属性实际上不会更改。 当属性不在模板中时,它们可能被错误地报告为已删除,但在部署过程中会自动设置为默认值。 此结果在 what-if 响应中被视为“干扰信息”。 最终部署的资源将具有为属性设置的值。 当 what-if 操作成熟时,将从结果中筛选出这些属性。

以编程方式评估 what-if 结果

现在,让我们将命令设置为变量,以编程方式评估 what-if 结果。

$results = Get-AzResourceGroupDeploymentWhatIfResult `
  -ResourceGroupName ExampleGroup `
  -TemplateUri "https://raw.githubusercontent.com/Azure/azure-docs-json-samples/master/azure-resource-manager/what-if/what-if-after.json"

可以看到每项更改的摘要。

foreach ($change in $results.Changes)
{
  $change.Delta
}

确认删除

what-if 操作支持使用部署模式。 设置为完整模式时,将删除不在模板中的资源。 以下示例部署一个处于完整模式的未定义任何资源的模板

若要在部署模板之前预览所做的更改,请在部署命令中使用 confirm 开关参数。 如果更改符合预期,请确认你想要完成此部署。

New-AzResourceGroupDeployment `
  -ResourceGroupName ExampleGroup `
  -Mode Complete `
  -Confirm `
  -TemplateUri "https://raw.githubusercontent.com/Azure/azure-docs-json-samples/master/empty-template/azuredeploy.json"

由于该模板中未定义任何资源,且部署模式设置为完成,因此会删除虚拟网络。

资源管理器模板部署 what-if 操作输出 - 完整部署模式

文本输出如下:

Resource and property changes are indicated with this symbol:
  - Delete

The deployment will update the following scope:

Scope: /subscriptions/./resourceGroups/ExampleGroup

  - Microsoft.Network/virtualNetworks/vnet-001

      id:
"/subscriptions/./resourceGroups/ExampleGroup/providers/Microsoft.Network/virtualNet
works/vnet-001"
      location:        "chinaeast"
      name:            "vnet-001"
      tags.CostCenter: "12345"
      tags.Owner:      "Team A"
      type:            "Microsoft.Network/virtualNetworks"

Resource changes: 1 to delete.

Are you sure you want to execute the deployment?
[Y] Yes  [A] Yes to All  [N] No  [L] No to All  [S] Suspend  [?] Help (default is "Y"):

你会看到预期的更改,并且可以确认你想要运行此部署。

SDK

可以通过 Azure SDK 使用 What-if 操作。

后续步骤