控制循环执行和嵌套循环

已完成

通过使用强大的复制循环功能,可以创建动态且灵活的模板。 请务必了解如何控制循环在创建资源时的执行方式,以及如何使用循环来设置资源属性和嵌套循环。

在本单元中,你将学习如何控制复制循环的执行,以及如何在 Bicep 中使用资源属性循环和嵌套循环。

注意

本单元中显示的命令用于说明概念。 请暂时不要运行这些命令。 稍后你将练习在此处学到的知识。

控制循环执行

默认情况下,Azure 资源管理器以非确定性顺序从循环中并行地创建资源。 在上一个练习中创建循环时,两个 Azure SQL 逻辑服务器是同时创建的。 这有助于缩短总体部署时间,因为循环内的所有资源都是一次部署的。

但是,在某些情况下,可能需要按顺序(而不是并行地)在循环中部署资源,或者并行部署少量更改。 例如,如果生产环境中有大量 Azure 应用服务应用,你可能希望一次仅将更改部署到一小部分,以防止更新同时重启所有应用。

可以使用 @batchSize 修饰器控制复制循环在 Bicep 中的运行方式。 使用 for 关键字将修饰器放在资源或模块声明上。

让我们看看没有 @batchSize 修饰器的一组应用服务应用程序的示例 Bicep定义:

resource appServiceApp 'Microsoft.Web/sites@2023-12-01' = [for i in range(1,3): {
  name: 'app${i}'
  // ...
}]

此循环中的所有资源将同时并行部署:

Diagram showing time on the horizontal axis, with app1, app2, and app3 stacked vertically to be deployed at the same time.

现在,应用值为 2@batchSize 修饰器:

@batchSize(2)
resource appServiceApp 'Microsoft.Web/sites@2023-12-01' = [for i in range(1,3): {
  name: 'app${i}'
  // ...
}]

当你部署模板时,Bicep 将分两批部署:

Diagram showing time on the horizontal axis, with app1 and app2 stacked to run as one batch, and app3 to run as a second batch.

注意

Bicep 将等待每个完整的批次完成,然后再继续下一个批次。 在上面的示例中,如果 app2 在 app1 之前完成其部署,Bicep 将等待 app1 完成,然后再开始部署 app3。

你还可以将 @batchSize 设置为 1,让 Bicep 按顺序运行循环:

@batchSize(1)
resource appServiceApp 'Microsoft.Web/sites@2023-12-01' = [for i in range(1,3): {
  name: 'app${i}'
  // ...
}]

当你部署模板时,Bicep 会等待每个资源部署完成,然后再开始下一个资源部署:

Diagram showing time on the horizontal axis, with app1, app2, and app3 being deployed sequentially.

将循环与资源属性一起使用

可以使用循环来帮助设置资源属性。 例如,当你部署虚拟网络时,需要指定其子网。 子网必须包含两条重要信息:名称和地址前缀。 可以将参数与对象数组一起使用,为每个环境指定不同的子网:

param subnetNames array = [
  'api'
  'worker'
]

resource virtualNetwork 'Microsoft.Network/virtualNetworks@2024-01-01' = {
  name: 'teddybear'
  location: resourceGroup().location
  properties: {
    addressSpace: {
      addressPrefixes: [
        '10.0.0.0/16'
      ]
    }
    subnets: [for (subnetName, i) in subnetNames: {
      name: subnetName
      properties: {
        addressPrefix: '10.0.${i}.0/24'
      }
    }]
  }
}

请注意,本示例中的 for 循环出现在资源定义中,位于 subnets 属性值周围。

嵌套循环

某些场景要求在另一个循环内使用循环,即嵌套循环。 可以使用 Bicep 创建嵌套循环。

对于你所在的小熊玩具公司,你需要在将推出玩具的每个国家/地区部署虚拟网络。 每个虚拟网络都需要不同的地址空间,并需要两个子网。 首先,在循环中部署虚拟网络:

param locations array = [
  'westeurope'
  'eastus2'
  'eastasia'
]

var subnetCount = 2

resource virtualNetworks 'Microsoft.Network/virtualNetworks@2024-01-01' = [for (location, i) in locations : {
  name: 'vnet-${location}'
  location: location
  properties: {
    addressSpace:{
      addressPrefixes:[
        '10.${i}.0.0/16'
      ]
    }
  }
}]

此循环为每个位置部署了虚拟网络,并且使用循环索引为虚拟网络设置 addressPrefix,以确保每个虚拟网络都获取不同的地址前缀。

可以使用嵌套循环在每个虚拟网络中部署子网:

resource virtualNetworks 'Microsoft.Network/virtualNetworks@2024-01-01' = [for (location, i) in locations : {
  name: 'vnet-${location}'
  location: location
  properties: {
    addressSpace:{
      addressPrefixes:[
        '10.${i}.0.0/16'
      ]
    }
    subnets: [for j in range(1, subnetCount): {
      name: 'subnet-${j}'
      properties: {
        addressPrefix: '10.${i}.${j}.0/24'
      }
    }]
  }
}]

嵌套循环使用 range() 函数创建两个子网。

当你部署模板时,将获取以下虚拟网络和子网:

虚拟网络名称 位置 地址前缀 子网
vnet-westeurope westeurope 10.0.0.0/16 10.0.1.0/2410.0.2.0/24
vnet-eastus2 eastus2 10.1.0.0/16 10.1.1.0/2410.1.2.0/24
vnet-eastasia eastasia 10.2.0.0/16 10.2.1.0/2410.2.2.0/24