ARM テンプレートでのリソースの反復処理

この記事では、Azure Resource Manager テンプレート (ARM テンプレート) でリソースの複数のインスタンスを作成する方法について説明します。 テンプレートのリソース セクションにコピー ループを追加することで、デプロイするリソースの数を動的に設定できます。 テンプレートの構文を繰り返す必要もありません。

プロパティ変数、および出力でもコピー ループを使用できます。

リソースをデプロイするかどうかを指定する必要がある場合は、condition 要素に関する記述を参照してください。

ヒント

ARM テンプレートと同じ機能を備え、構文も使いやすいため、Bicep をお勧めします。 詳細については、「ループ」を参照してください。

構文

テンプレートのリソース セクションに copy 要素を追加して、リソースの複数のインスタンスをデプロイします。 この copy 要素には、次の一般的な形式があります。

"copy": {
  "name": "<name-of-loop>",
  "count": <number-of-iterations>,
  "mode": "serial" <or> "parallel",
  "batchSize": <number-to-deploy-serially>
}

name プロパティは、ループを識別する任意の値です。 count プロパティは、リソースの種類に対して必要な反復の数を指定します。

modebatchSize プロパティを使用して、リソースを並列または順番に配置するかどうかを指定します。 これらのプロパティについては シリアルまたは並列で説明します。

コピー制限

count は 800 を超えることはできません。

count は負の数値にすることはできません。 Azure CLI、PowerShell、または REST API の最新バージョンを使用してテンプレートをデプロイする場合、ゼロを指定できます。 具体的には、次のものを使用する必要があります。

  • Azure PowerShell 2.6 以降
  • Azure CLI 2.0.74 以降
  • REST API バージョン 2019-05-10 以降
  • [Linked deployments](リンクされたデプロイ) には、デプロイ リソースの種類に API バージョン 2019-05-10 以降を使用する必要があります

以前のバージョンの PowerShell、CLI、および REST API では、count の 0 をサポートしていません。

コピー ループで完全モード デプロイを使用する際は注意してください。 完全モードでリソース グループに再デプロイする場合、コピー ループを解決した後でテンプレートに指定されていないリソースはすべて削除されます。

リソースの反復

次の例では、storageCount パラメーターで指定されているストレージ アカウントの数を作成します。

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "location": {
      "type": "string",
      "defaultValue": "[resourceGroup().location]"
    },
    "storageCount": {
      "type": "int",
      "defaultValue": 3
    }
  },
  "resources": [
    {
      "copy": {
        "name": "storagecopy",
        "count": "[length(range(0, parameters('storageCount')))]"
      },
      "type": "Microsoft.Storage/storageAccounts",
      "apiVersion": "2022-09-01",
      "name": "[format('{0}storage{1}', range(0, parameters('storageCount'))[copyIndex()], uniqueString(resourceGroup().id))]",
      "location": "[parameters('location')]",
      "sku": {
        "name": "Standard_LRS"
      },
      "kind": "Storage",
      "properties": {}
    }
  ]
}

各リソースの名前には、現在のループの反復を返す copyIndex() 関数が含まれます。 copyIndex() は 0 から始まります。 次の例を見てください。

"name": "[format('storage{0}', copyIndex())]",

この場合、以下の名前が作成されます。

  • storage0
  • storage1
  • storage2

インデックス値をオフセットするには、copyIndex() 関数に値を渡します。 反復回数は copy 要素で指定されたままですが、copyIndex の値が指定された値でオフセットされます。 次の例を見てください。

"name": "[format('storage{0}', copyIndex(1))]",

この場合、以下の名前が作成されます。

  • storage1
  • storage2
  • storage3

コピー操作は、配列内の各要素に対して反復処理するため、配列で作業するときに便利です。 配列で反復回数を指定するには length 関数を使います。また、配列における現在のインデックスを取得するには copyIndex を使います。

次の例では、パラメーターに指定された名前ごとに 1 つのストレージアカウントを作成します。

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "storageNames": {
      "type": "array",
      "defaultValue": [
        "contoso",
        "fabrikam",
        "coho"
      ]
    },
    "location": {
      "type": "string",
      "defaultValue": "[resourceGroup().location]"
    }
  },
  "resources": [
    {
      "copy": {
        "name": "storagecopy",
        "count": "[length(parameters('storageNames'))]"
      },
      "type": "Microsoft.Storage/storageAccounts",
      "apiVersion": "2022-09-01",
      "name": "[format('{0}{1}', parameters('storageNames')[copyIndex()], uniqueString(resourceGroup().id))]",
      "location": "[parameters('location')]",
      "sku": {
        "name": "Standard_LRS"
      },
      "kind": "Storage",
      "properties": {}
    }
  ]
}

デプロイされたリソースから値を返す場合は、outputs セクション内で copy を使用できます。

シンボリック名を使用する

シンボリック名 は、リソース コピー ループに割り当てられます。 ループ インデックスは 0 から始まります。 次の例では、 myStorages[1] はリソース ループ内の 2 番目のリソースを参照します。

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "languageVersion": "2.0",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "location": {
      "type": "string",
      "defaultValue": "[resourceGroup().location]"
    },
    "storageCount": {
      "type": "int",
      "defaultValue": 2
    }
  },
  "resources": {
    "myStorages": {
      "type": "Microsoft.Storage/storageAccounts",
      "apiVersion": "2022-09-01",
      "name": "[format('{0}storage{1}', copyIndex(), uniqueString(resourceGroup().id))]",
      "location": "[parameters('location')]",
      "sku": {
        "name": "Standard_LRS"
      },
      "kind": "Storage",
      "properties": {},
      "copy": {
        "name": "storagecopy",
        "count": "[parameters('storageCount')]"
      }
    }
  },
  "outputs": {
    "storageEndpoint":{
      "type": "object",
      "value": "[reference('myStorages[1]').primaryEndpoints]"
    }
  }
}

インデックスがランタイム値の場合は、参照を自分でフォーマットします。 次に例を示します。

"outputs": {
  "storageEndpoint":{
    "type": "object",
    "value": "[reference(format('myStorages[{0}]', variables('runtimeIndex'))).primaryEndpoints]"
  }
}

シンボリック名は、dependsOn 配列 で使用できます。 シンボリック名がコピー ループの場合、ループ内のすべてのリソースが依存関係として追加されます。 詳細については、ループ内のリソースに依存する を参照してください。

シリアルまたは並列

既定では、リソース マネージャーは並列でリソースを作成します。 テンプレートの合計リソース数の上限 (800 個) 以外、並列にデプロイされるリソースの数に制限はありません。 それらが作成される順序は保証されません。

しかし、リソースが順番にデプロイされるように指定したい場合もあります。 たとえば、運用環境を更新するとき、一度に特定の数だけ更新されるように更新時間をずらす必要がある場合があります。

リソースの複数のインスタンスを連続的にデプロイするには、modemode に、batchSize を一度にデプロイするインスタンスの数に設定します。 シリアル モードでは、Resource Manager はループ内で前のインスタンスへの依存関係を作成するので、前のバッチが完了するまで次のバッチは実行されません。

batchSize の値は、copy 要素の count の値を超えることはできません。

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "location": {
      "type": "string",
      "defaultValue": "[resourceGroup().location]"
    }
  },
  "resources": [
    {
      "copy": {
        "name": "storagecopy",
        "count": 4,
        "mode": "serial",
        "batchSize": 2
      },
      "type": "Microsoft.Storage/storageAccounts",
      "apiVersion": "2022-09-01",
      "name": "[format('{0}storage{1}', range(0, 4)[copyIndex()], uniqueString(resourceGroup().id))]",
      "location": "[parameters('location')]",
      "sku": {
        "name": "Standard_LRS"
      },
      "kind": "Storage",
      "properties": {}
    }
  ]
}

mode プロパティでも mode が既定値として使用されます。

子リソースの反復処理

子リソースにコピー ループを使用することはできません。 通常は別のリソース内で入れ子になっているように定義するリソースの複数のインスタンスを作成するには、代わりに、そのリソースを最上位のリソースとして作成する必要があります。 type および name の各プロパティを使用して、親リソースとの関係を定義します。

たとえば、通常はデータ ファクトリ内の子リソースとしてデータセットを定義するとします。

{
  "resources": [
    {
      "type": "Microsoft.DataFactory/factories",
      "name": "exampleDataFactory",
      ...
      "resources": [
        {
          "type": "datasets",
          "name": "exampleDataSet",
          "dependsOn": [
            "exampleDataFactory"
          ],
          ...
        }
      ]
      ...
    }
  ]
}

複数のデータ セットを作成するには、それをデータ ファクトリの外部に移動します。 データセットは、データ ファクトリと同じレベルである必要がありますが、今までどおりデータ ファクトリの子リソースです。 type および name の各プロパティを使用して、データセットとデータ ファクトリの関係を保存します。 テンプレート内の位置から type を推論できなくなったため、{resource-provider-namespace}/{parent-resource-type}/{child-resource-type} の形式で完全修飾型を指定する必要があります。

データ ファクトリのインスタンスを使用して親子関係を確立するには、親リソースの名前を含むデータ セットの名前を指定します。 {parent-resource-name}/{child-resource-name} の形式で入力します。

実装の例を次に示します。

"resources": [
{
  "type": "Microsoft.DataFactory/factories",
  "name": "exampleDataFactory",
  ...
},
{
  "type": "Microsoft.DataFactory/factories/datasets",
  "name": "[format('exampleDataFactory/exampleDataSet{0}', copyIndex())]",
  "dependsOn": [
    "exampleDataFactory"
  ],
  "copy": {
    "name": "datasetcopy",
    "count": "3"
  },
  ...
}]

サンプル テンプレート

次の例は、リソースまたはプロパティの複数のインスタンスを作成するための一般的なシナリオを示しています。

Template 説明
Copy storage 名前にインデックス番号を含む複数のストレージ アカウントをデプロイします。
Serial copy storage 複数のストレージ アカウントを一度に 1 つずつデプロイします。 名前にはインデックス番号が含まれます。
Copy storage with array 複数のストレージ アカウントをデプロイします。 名前には、配列からの値が含まれます。
リソース グループをコピーする 複数のリソース グループをデプロイします。

次のステップ