ループの実行を制御し、ループを入れ子にする

完了

強力なコピー ループ機能を使用することにより、動的で柔軟なテンプレートを作成できます。 リソースを作成するときのループの実行方法を制御する方法と、ループを使用してリソースのプロパティと入れ子のループを設定する方法を理解することが重要です。

このユニットでは、コピー ループの実行を制御する方法と、Bicep でリソース プロパティのループと入れ子になったループを使用する方法について学習します。

Note

このユニットのコマンドは、概念を説明するために示されています。 コマンドはまだ実行しないでください。 ここで学習した内容をすぐに練習します。

ループの実行を制御する

既定では、Azure Resource Manager によるループからのリソースの作成は、並列に、非決定論的な順序で行われます。 前の演習でループを作成したときは、両方の Azure SQL 論理サーバーが同時に作成されました。 ループ内のすべてのリソースが一度にデプロイされるため、これは全体的なデプロイ時間を短縮するのに役立ちます。

ただし、場合によっては、ループ内でリソースを並列ではなく順番にデプロイしたり、小規模な変更のバッチをまとめて並列にデプロイすることが必要になります。 たとえば、運用環境に多数の Azure App Service アプリがある場合、更新によってすべてのアプリが同時に再起動されないよう、一度に少数のアプリにのみ変更をデプロイすることが必要になる場合があります。

@batchSize デコレーターを使用することで、Bicep でのコピー ループの実行方法を制御できます。 for キーワードを使用して、リソースまたはモジュールの宣言にデコレーターを設定します。

@batchSize デコレーターを使用しない場合の、App Service アプリケーションのセットに対する Bicep の定義の例を見てみましょう。

resource appServiceApp 'Microsoft.Web/sites@2021-03-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@2021-03-01' = [for i in range(1,3): {
  name: 'app${i}'
  // ...
}]

テンプレートをデプロイすると、2 つのバッチでデプロイされます。

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.

Note

Bicep は、完全なバッチが完了するまで待ってから、次のバッチに進みます。 前の例では、app1 の前に app2 のデプロイが完了した場合、Bicep は app1 が完了するまで待ってから、app3 のデプロイを開始します。

また、@batchSize1 に設定することで、ループを順番に実行するよう Bicep に指示することもできます。

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

そのテンプレートをデプロイすると、各リソースのデプロイが完了してから、次のデプロイが開始されます。

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

リソース プロパティでループを使用する

ループを使用して、リソースのプロパティを設定することができます。 たとえば、仮想ネットワークをデプロイする場合は、そのサブネットを指定する必要があります。 サブネットには、名前とアドレス プレフィックスという 2 つの重要な情報が必要です。 オブジェクトの配列でパラメーターを使用すると、環境ごとに異なるサブネットを指定できます。

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

resource virtualNetwork 'Microsoft.Network/virtualNetworks@2021-08-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'
      }
    }]
  }
}

この例では、リソース定義内で subnets プロパティ値を囲むように for ループが使用されていることに注意してください。

入れ子になったループ

シナリオによっては、別のループの内側でループを使用する必要があります ("入れ子になったループ")。 Bicep を使用して、入れ子になったループを作成できます。

テディ ベア玩具会社では、玩具が発売されるすべての国や地域に仮想ネットワークをデプロイする必要があります。 すべての仮想ネットワークには、異なるアドレス空間と 2 つのサブネットが必要です。 まず、ループ内で仮想ネットワークをデプロイします。

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

var subnetCount = 2

resource virtualNetworks 'Microsoft.Network/virtualNetworks@2021-08-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@2021-08-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() 関数を使用して 2 つのサブネットを作成します。

このテンプレートをデプロイすると、次の仮想ネットワークとサブネットが作成されます。

仮想ネットワーク名 場所 アドレス プレフィックス サブネット
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