在部署 Bicep 文件之前,可以预览将发生的更改。 Azure 资源管理器提供 What-if 操作,让你在部署 Bicep 文件时了解资源发生的更改。 what-if 操作不会对现有资源进行任何更改, 而是预测在部署指定的 Bicep 文件时发生的更改。
可将 what-if 操作与 Azure PowerShell、Azure CLI 或 REST API 操作配合使用。 资源组、订阅、管理组合租户级部署支持 What-if。
先决条件
所需的权限
若要部署 Bicep 文件或 ARM 模板,需要对要部署的资源具有写入权限,并有权访问资源 Microsoft.Resources/deployments
类型上的所有操作。 例如,若要部署虚拟机,需要 Microsoft.Compute/virtualMachines/write
和 Microsoft.Resources/deployments/*
权限。 What-if 操作具有相同的权限要求。
有关角色和权限的列表,请参阅 Azure 内置角色。
Installation
若要在 Azure CLI 中使用 what-if,则必须安装 Azure CLI 2.14.0 或更高版本。 如果需要,请安装 Azure CLI 的最新版本。
局限性
What-if 将扩展嵌套模板,直到达到以下限制:
- 500 个嵌套模板。
- 跨资源组部署中的资源组数量达到 800 个。
- 展开嵌套模板所需花费的时间达到 5 分钟。
只要达到其中一个限制,剩余资源的更改类型将设置为“忽略”。
短路
Bicep 部署中的模拟作可能会遇到“短路”的情况,即服务无法完全分析模块或资源,因为部署的结构或依赖于外部状态。 当单个资源的资源 ID 或 API 版本不能在部署上下文外部计算时,通常会因为未解析的表达式或外部依赖项而发生短路。 有关详细信息,请参阅 未计算的表达式。 虽然很少,模块或嵌套部署资源的短路也可能发生,导致模块中的所有资源被排除在 What-if 分析结果之外。 在这种情况下,API 响应包括一条诊断消息来指示问题。
运行 what-if作
使用最新版本的 Az PowerShell 模块(13.1.0 或更高版本)或 Azure CLI(2.75.0 或更高版本)将在 what-if 无法分析部署的一部分时提供诊断。 这些工具的早期版本的行为方式相同,但它们不显示诊断。 例如,如果使用 CLI 版本 2.74.0,则仍会发生此问题 - 它只是以无提示方式发生。
what-if 命令
若要在部署 Bicep 文件前预览更改,请使用:
- az deployment group what-if(适用于资源组部署)
- az deployment sub what-if(适用于订阅级别部署)
- az deployment mg what-if(适用于管理组部署)
- az deployment tenant what-if(适用于租户部署)
可以使用 --confirm-with-what-if
开关(或其缩写形式 -c
)预览更改,并让系统显示是否继续部署的提示。 将此开关添加到:
- az 创建部署组
- az deployment sub create。
- az deployment mg create(此命令用于创建管理组的部署)
- az deployment tenant create
例如,对于资源组部署,请使用 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”。
对于 REST API,请使用:
- 对于资源组部署,请使用部署 - What If
- Deployments - What If At Subscription Scope(适用于订阅部署)
- Deployments - What If At Management Group Scope(适用于管理组部署)
- Deployments - What If At Tenant Scope(适用于租户部署)。
可以通过 Azure SDK 使用 What-if 操作。
- 对于 Python,请使用 What-if。
- 对于 Java,请使用 DeploymentWhatIf 类。
- 对于 .NET,请使用 DeploymentWhatIf 类。
设置环境
为了了解 what-if 的工作原理,让我们运行一些测试。 首先,部署一个用于创建虚拟网络的 Bicep 文件。 将以下 Bicep 文件另存为 what-if-before.bicep
:
resource vnet 'Microsoft.Network/virtualNetworks@2024-07-01' = {
name: 'vnet-001'
location: resourceGroup().location
tags: {
CostCenter: '12345'
Owner: 'Team A'
}
properties: {
addressSpace: {
addressPrefixes: [
'10.0.0.0/16'
]
}
enableVmProtection: false
enableDdosProtection: false
subnets: [
{
name: 'subnet001'
properties: {
addressPrefix: '10.0.0.0/24'
}
}
{
name: 'subnet002'
properties: {
addressPrefix: '10.0.1.0/24'
}
}
]
}
}
若要部署 Bicep 文件,请使用:
az group create \
--name ExampleGroup \
--location "Central US"
az deployment group create \
--resource-group ExampleGroup \
--template-file "what-if-before.bicep"
测试修改
部署完成后,即可测试 what-if 操作。 这一次,将部署一个用于更改虚拟网络的 Bicep 文件。 与前面的示例相比,以下示例错过了其中一个原始标记,删除了一个子网,并且地址前缀已更改。 将以下 Bicep 文件另存为 what-if-after.bicep
:
resource vnet 'Microsoft.Network/virtualNetworks@2024-07-01' = {
name: 'vnet-001'
location: resourceGroup().location
tags: {
CostCenter: '12345'
}
properties: {
addressSpace: {
addressPrefixes: [
'10.0.0.0/15'
]
}
enableVmProtection: false
enableDdosProtection: false
subnets: [
{
name: 'subnet002'
properties: {
addressPrefix: '10.0.1.0/24'
}
}
]
}
}
若要查看更改,请使用:
az deployment group what-if \
--resource-group ExampleGroup \
--template-file "what-if-after.bicep"
what-if 输出类似于:
文本输出如下:
Resource and property changes are indicated with these symbols:
- Delete
+ Create
~ Modify
- tags.Owner: "Team A"
+ properties.enableVmProtection: false
~ 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"
properties.defaultOutboundAccess: false
properties.privateEndpointNetworkPolicies: "Disabled"
properties.privateLinkServiceNetworkPolicies: "Enabled"
]
Resource changes: 1 to modify.
请注意,输出顶部的颜色用于指示更改类型。
输出的底部显示了“已删除所有者”标记。 地址前缀已从 10.0.0.0/16 更改为 10.0.0.0/15。 已删除名为 subnet001 的子网。 请记住,这些更改并未部署。 如果部署 Bicep 文件,则可预览会发生的更改。
列出为已删除的某些属性实际上不会更改。 当属性不在 Bicep 文件中时,它们可能被错误地报告为已删除,但在部署过程中会自动设置为默认值。 此结果在 what-if 响应中被视为“干扰信息”。 最终部署的资源将具有为属性设置的值。 当 what-if 操作成熟时,将从结果中筛选出这些属性。
确认删除
若要在部署 Bicep 文件之前预览所做的更改,请在部署命令中使用 confirm 开关参数。 如果更改符合预期,请确认你想要完成此部署。
az deployment group create \
--resource-group ExampleGroup \
--confirm-with-what-if \
--template-file "what-if-after.bicep"
文本输出如下:
Resource and property changes are indicated with these symbols:
- Delete
+ Create
~ Modify
The deployment will update the following scope:
Scope: /subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourceGroups/ExampleGroup
~ Microsoft.Network/virtualNetworks/vnet-001 [2024-07-01]
- properties.privateEndpointVNetPolicies: "Disabled"
- tags.Owner: "Team A"
+ properties.enableVmProtection: false
~ 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"
properties.defaultOutboundAccess: false
properties.privateEndpointNetworkPolicies: "Disabled"
properties.privateLinkServiceNetworkPolicies: "Enabled"
]
Resource changes: 1 to modify.
Are you sure you want to execute the deployment? (y/n):
你会看到预期的更改,并且可以确认你想要运行此部署。
以编程方式评估 what-if 结果
现在,让我们将命令设置为变量,以编程方式评估 what-if 结果。
results=$(az deployment group what-if --resource-group ExampleGroup --template-file "what-if-after.bicep" --no-pretty-print)
了解 what-if 结果
查看结果
在 PowerShell 或 Azure CLI 中使用 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.
注释
What-if 操作无法解析引用函数。 每次将属性设置为包含引用函数的模板表达式时,What-if 都会报告属性将改变。 发生此行为的原因是,What-if 将属性的当前值(如布尔值 true
或 false
)与未解析的模板表达式进行比较。 很明显,这些值不匹配。 部署 Bicep 文件时,只有在模板表达式解析为其他值时,属性才会更改。
更改类型
what-if 操作列出七种不同的更改类型:
- 创建:资源当前不存在,但已在 Bicep 文件中定义。 将创建该资源。
- 删除:仅当为 JSON 模板部署使用完整模式时,此更改类型才适用。 资源存在,但未在 Bicep 文件中定义。 使用完整模式时,将删除该资源。 此更改类型仅包括支持完整模式删除的资源。
- 忽略:资源存在,但未在 Bicep 文件中定义。 不会部署或修改资源。 达到扩展嵌套模板的限制时,将遇到此更改类型。 请参阅 What-if 限制。
-
无更改:资源存在,且在 Bicep 文件中定义。 将重新部署资源,但资源的属性不会更改。 当 ResultFormat 设置为
FullResourcePayloads
(默认值)时,将返回此更改类型。 -
NoEffect:属性为只读,服务将忽略该属性。 例如,
sku.tier
属性始终设置为在sku.name
命名空间中匹配Microsoft.ServiceBus
。 -
修改:资源存在,且在 Bicep 文件中定义。 将重新部署资源,且资源的属性会更改。 当 ResultFormat 设置为
FullResourcePayloads
(默认值)时,将返回此更改类型。 -
部署:资源存在,并在 Bicep 文件中定义。 将重新部署资源。 资源的属性可能会更改,也可能不会更改。 当没有足够的信息来确定是否有任何属性发生更改时,操作将返回此更改类型。 仅当 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.
未计算的表达式
如果输出中出现未计算的表达式,则表示在部署上下文之外无法计算它。 表达式显示在 as-is,以指示在执行部署时将填充的信息。
param now string = utcNow()
resource sa 'Microsoft.Storage/storageAccounts@2025-01-01' = {
name: 'acct'
location: resourceGroup().location
sku: {
name: 'Standard_LRS'
}
kind: 'StorageV2'
tags: {
lastDeployedOn: now
lastDeployedBy: deployer().userPrincipalName
}
}
在前面的示例中,参数 now
使用 utcNow()
函数获取当前日期和时间。 运行 what-if 时,这些表达式会显示 as-is,因为它们不能在部署上下文之外进行评估。 what-if 输出将类似于:
Note: The result may contain false positive predictions (noise).
You can help us improve the accuracy of the result by opening an issue here: https://aka.ms/WhatIfIssues
Resource and property changes are indicated with this symbol:
~ Modify
The deployment will update the following scope:
Scope: /subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourceGroups/jgaotest
~ Microsoft.Storage/storageAccounts/acct0808 [2025-01-01]
~ tags.lastDeployedOn: "20250808T200145Z" => "[utcNow()]"
Resource changes: 1 to modify.
在 what-if 期间不计算以下表达式:
- 非确定性函数,如 newGuid() 和 utcNow()
- 对 安全参数值的任何引用。
- 对未部署在同一模板中的资源的引用。
- 对同一模板中未定义的资源属性的引用。
- 任何资源函数,例如 listKeys()。
清理资源
如果不再需要示例资源,请使用 Azure CLI 或 Azure PowerShell 删除资源组。
az group delete --name ExampleGroup
后续步骤
- 若要在管道中使用 what-if 操作,请参阅在管道中使用 What-If 测试 ARM 模板。
- 如果发现 What-if 操作出现了错误的结果,请在 https://aka.ms/whatifissues 上报告问题。
- 有关介绍如何使用 What-if 的 Learn 模块,请参阅使用 What-if 和 ARM 模板测试工具包来预览更改和验证 Azure 资源。