다음을 통해 공유


Bicep의 반복 루프

이 문서에서는 for 구문을 사용하여 컬렉션의 항목을 반복하는 방법을 보여 줍니다. 이 기능은 v0.3.1부터 지원됩니다. 루프를 사용하여 리소스, 모듈, 변수, 속성 또는 출력의 여러 복사본을 정의할 수 있습니다. 루프를 사용하여 Bicep 파일에서 반복되는 구문을 방지하고 배포 중에 만들 복사본 수를 동적으로 설정합니다. 빠른 시작: 여러 구문을 사용하여 Bicep에서 여러 리소스 인스턴스를 만드는 방법에 대한 빠른 시작은 Bicep에서 여러 리소스 인스턴스 만들기를 참조하세요.for

루프를 사용하여 여러 리소스 또는 모듈을 만들려면 각 인스턴스에 속성에 대한 고유한 값이 name 있어야 합니다. 배열 또는 컬렉션에서 인덱스 값 또는 고유 값을 사용하여 이름을 만들 수 있습니다.

학습 리소스

루프에 대한 단계별 지침은 Microsoft Learn의 조건 및 루프 모듈을 사용하여 유연한 Bicep 파일 빌드 를 참조하세요.

루프 구문

루프는 다음과 같이 선언할 수 있습니다.

  • 정수 인덱스 사용. 이 옵션은 시나리오가 "이만큼 많은 인스턴스를 만들려고 합니다."일 때 작동합니다. range 함수는 시작 인덱스에서 시작하고 지정된 요소 수를 포함하는 정수 배열을 만듭니다. 루프 내에서 정수 인덱스를 사용하여 값을 수정할 수 있습니다. 자세한 내용은 정수 인덱스를 참조하세요.

    [for <index> in range(<startIndex>, <numberOfElements>): {
      ...
    }]
    
  • 배열의 항목 사용: 이 옵션은 시나리오에서 "배열의 각 요소에 대한 인스턴스를 만들고 싶습니다."인 경우에 작동합니다. 루프 내에서 현재 배열 요소의 값을 사용하여 값을 수정할 수 있습니다. 자세한 내용은 배열 요소를 참조하세요.

    [for <item> in <collection>: {
      ...
    }]
    
  • 사전 개체의 항목 사용: 이 옵션은 시나리오에서 "개체의 각 항목에 대한 인스턴스를 만들겠습니다."인 경우에 작동합니다. items 함수는 개체를 배열로 변환합니다. 루프 내에서 개체의 속성을 사용하여 값을 만들 수 있습니다. 자세한 내용은 사전 개체를 참조하세요.

    [for <item> in items(<object>): {
      ...
    }]
    
  • 배열에서 정수 인덱스 및 항목 사용: 이 옵션은 시나리오에서 "배열의 각 요소에 대한 인스턴스를 만들려고 하지만 다른 값을 만들려면 현재 인덱스도 필요합니다."인 경우에 작동합니다. 자세한 내용은 루프 배열 및 인덱스입니다.

    [for (<item>, <index>) in <collection>: {
      ...
    }]
    
  • 조건부 배포 추가: 이 옵션은 시나리오가 "여러 인스턴스를 만들려고 하지만 조건이 맞는 경우에만 각 인스턴스를 배포하려고 합니다."인 경우에 작동합니다. 자세한 내용은 조건의 루프를 참조하세요.

    [for <item> in <collection>: if(<condition>) {
      ...
    }]
    

루프 한계

Bicep에서 루프를 사용하면 다음과 같은 제한 사항이 있습니다.

  • Bicep 루프는 배포 시작 시 확인할 수 있는 값에서만 작동합니다.
  • 루프 반복은 음수이거나 800회를 초과할 수 없습니다.
  • 리소스는 중첩된 자식 리소스로 반복할 수 없으므로 자식 리소스를 최상위 리소스로 변경합니다. 자세한 내용은 자식 리소스에 대한 반복을 참조하세요.
  • 여러 속성 수준에서 반복하려면 람다 map 함수를 사용합니다.

정수 인덱스

인덱스를 사용하는 간단한 예제를 보려면 문자열 배열이 포함된 변수 를 만듭니다.

param itemCount int = 5

var stringArray = [for i in range(0, itemCount): 'item${(i + 1)}']

output arrayResult array = stringArray

출력은 다음 값을 가진 배열을 반환합니다.

[
  "item1",
  "item2",
  "item3",
  "item4",
  "item5"
]

다음 예에서는 storageCount 매개 변수에 지정된 수의 스토리지 계정을 만듭니다. 각 스토리지 계정에 대해 세 가지 속성을 반환합니다.

param location string = resourceGroup().location
param storageCount int = 2

resource storageAcct 'Microsoft.Storage/storageAccounts@2023-05-01' = [for i in range(0, storageCount): {
  name: '${i}storage${uniqueString(resourceGroup().id)}'
  location: location
  sku: {
    name: 'Standard_LRS'
  }
  kind: 'Storage'
}]

output storageInfo array = [for i in range(0, storageCount): {
  id: storageAcct[i].id
  blobEndpoint: storageAcct[i].properties.primaryEndpoints.blob
  status: storageAcct[i].properties.statusOfPrimary
}]

인덱스 i는 스토리지 계정 리소스 이름을 만드는 데 사용됩니다.

다음 예제에서는 모듈을 여러 번 배포합니다.

param location string = resourceGroup().location
param storageCount int = 2

var baseName = 'store${uniqueString(resourceGroup().id)}'

module stgModule './storageAccount.bicep' = [for i in range(0, storageCount): {
  name: '${i}deploy${baseName}'
  params: {
    storageName: '${i}${baseName}'
    location: location
  }
}]

output storageAccountEndpoints array = [for i in range(0, storageCount): {
  endpoint: stgModule[i].outputs.storageEndpoint
}]

배열 요소

다음 예제에서는 storageNames 매개 변수에 제공된 각 이름에 대해 하나의 스토리지 계정을 만듭니다. 각 리소스 인스턴스의 이름 속성은 고유해야 합니다.

param location string = resourceGroup().location
param storageNames array = [
  'contoso'
  'fabrikam'
  'coho'
]

resource storageAcct 'Microsoft.Storage/storageAccounts@2023-05-01' = [for name in storageNames: {
  name: '${name}${uniqueString(resourceGroup().id)}'
  location: location
  sku: {
    name: 'Standard_LRS'
  }
  kind: 'Storage'
}]

다음 예에서는 속성을 정의하기 위해 배열을 반복합니다. 가상 네트워크 내에 두 개의 서브넷을 만듭니다. 서브넷 이름은 고유해야 합니다.

param rgLocation string = resourceGroup().location

var subnets = [
  {
    name: 'api'
    subnetPrefix: '10.144.0.0/24'
  }
  {
    name: 'worker'
    subnetPrefix: '10.144.1.0/24'
  }
]

resource vnet 'Microsoft.Network/virtualNetworks@2023-11-01' = {
  name: 'vnet'
  location: rgLocation
  properties: {
    addressSpace: {
      addressPrefixes: [
        '10.144.0.0/20'
      ]
    }
    subnets: [for subnet in subnets: {
      name: subnet.name
      properties: {
        addressPrefix: subnet.subnetPrefix
      }
    }]
  }
}

배열 및 인덱스

다음 예제에서는 스토리지 계정을 정의할 때 배열 요소와 인덱스 값을 모두 사용합니다.

param storageAccountNamePrefix string

var storageConfigurations = [
  {
    suffix: 'local'
    sku: 'Standard_LRS'
  }
  {
    suffix: 'geo'
    sku: 'Standard_GRS'
  }
]

resource storageAccountResources 'Microsoft.Storage/storageAccounts@2023-05-01' = [for (config, i) in storageConfigurations: {
  name: '${storageAccountNamePrefix}${config.suffix}${i}'
  location: resourceGroup().location
  sku: {
    name: config.sku
  }
  kind: 'StorageV2'
}]

다음 예제에서는 배열의 요소와 인덱스를 모두 사용하여 새 리소스에 대한 정보를 출력합니다.

param location string = resourceGroup().location
param orgNames array = [
  'Contoso'
  'Fabrikam'
  'Coho'
]

resource nsg 'Microsoft.Network/networkSecurityGroups@2023-11-01' = [for name in orgNames: {
  name: 'nsg-${name}'
  location: location
}]

output deployedNSGs array = [for (name, i) in orgNames: {
  orgName: name
  nsgName: nsg[i].name
  resourceId: nsg[i].id
}]

사전 개체

사전 개체의 요소를 반복하려면 개체를 배열로 변환하는 함수를 사용합니다items. value 속성을 사용하여 개체의 속성을 가져옵니다. 리소스 이름은 고유해야 합니다.

param nsgValues object = {
  nsg1: {
    name: 'nsg-westus1'
    location: 'westus'
  }
  nsg2: {
    name: 'nsg-east1'
    location: 'eastus'
  }
}

resource nsg 'Microsoft.Network/networkSecurityGroups@2023-11-01' = [for nsg in items(nsgValues): {
  name: nsg.value.name
  location: nsg.value.location
}]

조건이 있는 루프

리소스 및 모듈의 경우 루프 구문과 함께 if 표현식을 추가하여 조건부로 컬렉션을 배포할 수 있습니다.

다음 예는 조건문과 결합된 루프를 보여 줍니다. 이 예제에서는 모듈의 모든 인스턴스에 단일 조건이 적용됩니다.

param location string = resourceGroup().location
param storageCount int = 2
param createNewStorage bool = true

var baseName = 'store${uniqueString(resourceGroup().id)}'

module stgModule './storageAccount.bicep' = [for i in range(0, storageCount): if(createNewStorage) {
  name: '${i}deploy${baseName}'
  params: {
    storageName: '${i}${baseName}'
    location: location
  }
}]

다음 예제에서는 배열의 현재 요소와 관련된 조건을 적용하는 방법을 보여줍니다.

resource parentResources 'Microsoft.Example/examples@2024-06-06' = [for parent in parents: if(parent.enabled) {
  name: parent.name
  properties: {
    children: [for child in parent.children: {
      name: child.name
      setting: child.settingValue
    }]
  }
}]

일괄 배포

Azure 리소스는 기본적으로 병렬로 배포됩니다. 루프를 사용하여 한 리소스 종류의 여러 인스턴스를 만드는 경우 해당 인스턴스는 모두 동시에 배포됩니다. 생성되는 순서는 정해져 있지 않습니다. Bicep 파일의 총 리소스 한도인 800개 외에는 병렬로 배포된 리소스 수에 제한이 없습니다.

한 리소스 종류의 모든 인스턴스를 동시에 업데이트하려고 하지는 않을 수 있습니다. 예를 들어, 프로덕션 환경을 업데이트할 때, 어떤 특정 수의 업데이트만 한 번에 진행되도록 시간을 두고 진행할 수 있습니다. 인스턴스의 하위 집합을 함께 일괄 처리하고 동시에 배포하도록 지정할 수 있습니다. 다른 인스턴스는 해당 일괄 처리가 완료되기를 기다립니다.

리소스 인스턴스를 직렬로 배포하려면 데코레이터를batchSize 추가합니다. 값을 동시에 배포할 인스턴스 수로 설정합니다. 종속성은 루프의 이전 인스턴스 중에 만들어지므로 이전 일괄 처리가 완료될 때까지 하나의 일괄 처리를 시작하지 않습니다.

param location string = resourceGroup().location

@batchSize(2)
resource storageAcct 'Microsoft.Storage/storageAccounts@2023-05-01' = [for i in range(0, 4): {
  name: '${i}storage${uniqueString(resourceGroup().id)}'
  location: location
  sku: {
    name: 'Standard_LRS'
  }
  kind: 'Storage'
}]

순차 배포의 경우 일괄 처리 크기를 1로 설정합니다.

batchSize 데코레이터는 sys 네임스페이스에 있습니다. 이 데코레이터를 같은 이름의 다른 항목과 구별해야 하는 경우 데코레이터 앞에 sys를 추가합니다. @sys.batchSize(2)

자식 리소스에 대한 반복

자식 리소스의 인스턴스를 두 개 이상 만들려면 다음 Bicep 파일 모두 이 작업을 지원합니다.

중첩된 자식 리소스

param location string = resourceGroup().location

resource stg 'Microsoft.Storage/storageAccounts@2023-05-01' = {
  name: 'examplestorage'
  location: location
  kind: 'StorageV2'
  sku: {
    name: 'Standard_LRS'
  }
  resource service 'fileServices' = {
    name: 'default'
    resource share 'shares' = [for i in range(0, 3): {
      name: 'exampleshare${i}'
    }]
  }
}

최상위 자식 리소스

resource stg 'Microsoft.Storage/storageAccounts@2023-05-01' = {
  name: 'examplestorage'
  location: resourceGroup().location
  kind: 'StorageV2'
  sku: {
    name: 'Standard_LRS'
  }
}

resource service 'Microsoft.Storage/storageAccounts/fileServices@2023-05-01' = {
  name: 'default'
  parent: stg
}

resource share 'Microsoft.Storage/storageAccounts/fileServices/shares@2023-05-01' = [for i in range(0, 3): {
  name: 'exampleshare${i}'
  parent: service
}]

참조 리소스/모듈 컬렉션

ARM 템플릿(Azure Resource Manager 템플릿) references 함수는 리소스 컬렉션의 런타임 상태를 나타내는 개체 배열을 반환합니다. Bicep에는 명시적 references 함수가 없고 기호 컬렉션 사용이 직접 사용되므로 Bicep은 코드가 생성되는 동안 ARM 템플릿 함수를 활용하는 ARM 템플릿 references 으로 변환합니다. 함수를 사용하여 references 기호 컬렉션을 ARM 템플릿으로 변환하는 변환 기능의 경우 Bicep CLI 버전 0.20.X 이상이 필요합니다. 또한 bicepconfig.json 파일에서 symbolicNameCodegen 설정을 표시하고 true로 설정해야 합니다.

정수 인덱스에 있는 두 샘플의 출력은 다음과 같이 작성할 수 있습니다.

param location string = resourceGroup().location
param storageCount int = 2

resource storageAcct 'Microsoft.Storage/storageAccounts@2023-05-01' = [for i in range(0, storageCount): {
  name: '${i}storage${uniqueString(resourceGroup().id)}'
  location: location
  sku: {
    name: 'Standard_LRS'
  }
  kind: 'Storage'
}]

output storageInfo array = map(storageAcct, store => {
  blobEndpoint: store.properties.primaryEndpoints
  status: store.properties.statusOfPrimary
})

output storageAccountEndpoints array = map(storageAcct, store => store.properties.primaryEndpoints)

이 Bicep 파일은 references 함수를 사용하는 다음 ARM JSON 템플릿으로 전환됩니다.

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "languageVersion": "1.10-experimental",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "location": {
      "type": "string",
      "defaultValue": "[resourceGroup().location]"
    },
    "storageCount": {
      "type": "int",
      "defaultValue": 2
    }
  },
  "resources": {
    "storageAcct": {
      "copy": {
        "name": "storageAcct",
        "count": "[length(range(0, parameters('storageCount')))]"
      },
      "type": "Microsoft.Storage/storageAccounts",
      "apiVersion": "2023-04-01",
      "name": "[format('{0}storage{1}', range(0, parameters('storageCount'))[copyIndex()], uniqueString(resourceGroup().id))]",
      "location": "[parameters('location')]",
      "sku": {
        "name": "Standard_LRS"
      },
      "kind": "Storage"
    }
  },
  "outputs": {
    "storageInfo": {
      "type": "array",
      "value": "[map(references('storageAcct', 'full'), lambda('store', createObject('blobEndpoint', lambdaVariables('store').properties.primaryEndpoints, 'status', lambdaVariables('store').properties.statusOfPrimary)))]"
    },
    "storageAccountEndpoints": {
      "type": "array",
      "value": "[map(references('storageAcct', 'full'), lambda('store', lambdaVariables('store').properties.primaryEndpoints))]"
    }
  }
}

위의 ARM JSON 템플릿에서는 languageVersion1.10-experimental로 설정해야 하며 리소스 요소는 배열 대신 개체입니다.

다음 단계

Bicep 파일을 만드는 방법을 알아보려면 Bicep 파일 구조 및 구문을 참조하세요.