Freigeben über


Iterative Schleifen in Bicep

In diesem Artikel erfahren Sie, wie Sie die for-Syntax verwenden, um Elemente in einer Sammlung zu durchlaufen. Diese Funktionalität wird ab v0.3.1 unterstützt. Sie können Schleifen verwenden, um mehrere Kopien einer Ressource, eines Moduls, einer Variablen, einer Eigenschaft oder einer Ausgabe zu definieren. Verwenden Sie Schleifen, um eine Wiederholungssyntax in Ihrer Bicep-Datei zu vermeiden und die Anzahl der während der Bereitstellung zu erstellenden Kopien dynamisch festzulegen. Siehe Schnellstart: Erstellen mehrerer Ressourceninstanzen in Bicep für eine Schnellstartanleitung zur Verwendung verschiedener for Syntaxen zum Erstellen mehrerer Ressourceninstanzen in Bicep.

Um Schleifen zum Erstellen mehrerer Ressourcen oder Module zu verwenden, muss jede Instanz über einen eindeutigen Wert für die name-Eigenschaft verfügen. Sie können den Indexwert oder eindeutige Werte in Arrays oder Sammlungen verwenden, um die Namen zu erstellen.

Schulungsressourcen

Weitere Informationen sowie eine Schritt-für-Schritt-Anleitung zu Schleifen finden Sie bei Microsoft Learn unter Erstellen flexibler Bicep-Dateien mithilfe von Bedingungen und Schleifen.

Schleifensyntax

Schleifen können wie folgt deklariert werden:

  • Durch Verwendung eines ganzzahligen Index. Diese Option funktioniert im Szenario „Ich möchte diese Anzahl von Instanzen erstellen“. Die Bereichsfunktion erstellt ein Array mit ganzen Zahlen, das am Startindex beginnt und die Anzahl der angegebenen Elemente enthält. Innerhalb der Schleife können Sie den ganzzahligen Index verwenden, um Werte zu ändern. Weitere Informationen finden Sie unter Ganzzahliger Index.

    [for <index> in range(<startIndex>, <numberOfElements>): {
      ...
    }]
    
  • Verwenden von Elementen in einem Array: Diese Option funktioniert, wenn Ihr Szenario lautet: "Ich möchte eine Instanz für jedes Element in einem Array erstellen." Innerhalb der Schleife können Sie den Wert des aktuellen Arrayelements verwenden, um Werte zu ändern. Weitere Informationen finden Sie unter Arrayelemente.

    [for <item> in <collection>: {
      ...
    }]
    
  • Verwenden von Elementen in einem Wörterbuchobjekt: Diese Option funktioniert, wenn Ihr Szenario lautet: "Ich möchte eine Instanz für jedes Element in einem Objekt erstellen." Die Items-Funktion konvertiert das Objekt in ein Array. Innerhalb der Schleife können Sie Eigenschaften aus dem Objekt verwenden, um Werte zu erstellen. Weitere Informationen finden Sie unter Wörterbuchobjekt.

    [for <item> in items(<object>): {
      ...
    }]
    
  • Verwenden von ganzzahligem Index und Elementen in einem Array: Diese Option funktioniert, wenn Ihr Szenario lautet: "Ich möchte eine Instanz für jedes Element in einem Array erstellen, aber ich benötige auch den aktuellen Index, um einen anderen Wert zu erstellen." Weitere Informationen finden Sie unter Loop-Array und Index.

    [for (<item>, <index>) in <collection>: {
      ...
    }]
    
  • Hinzufügen einer bedingten Bereitstellung: Diese Option funktioniert, wenn Ihr Szenario lautet: "Ich möchte mehrere Instanzen erstellen, aber ich möchte nur jede Instanz bereitstellen, wenn eine Bedingung wahr ist." Weitere Informationen finden Sie unter "Loop with condition".

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

Schleifengrenzwerte

Die Verwendung von Schleifen in Bicep weist folgende Einschränkungen auf:

  • Bicep-Schleifen funktionieren nur mit Werten, die zu Beginn der Bereitstellung bestimmt werden können.
  • Es dürfen nicht weniger als 0 oder mehr als 800 Schleifeniterationen verwendet werden.
  • Da eine Ressource keine Schleife mit geschachtelten untergeordneten Ressourcen ausführen kann, ändern Sie die untergeordneten Ressourcen in Ressourcen der obersten Ebene. Weitere Informationen finden Sie unter Iteration für eine untergeordnete Ressource.
  • Verwenden Sie die Lambda-Funktion map, um eine Schleife auf mehreren Eigenschaftenebenen anzuwenden.

Ganzzahliger Index

Erstellen Sie für ein einfaches Beispiel für die Verwendung eines Indexes eine Variable , die ein Array von Zeichenfolgen enthält:

param itemCount int = 5

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

output arrayResult array = stringArray

Die Ausgabe gibt ein Array mit den folgenden Elementen zurück:

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

Im nächsten Beispiel wird die Anzahl von Speicherkonten erstellt, die im Parameter storageCount angegeben ist. Es gibt drei Eigenschaften für jedes Speicherkonto zurück:

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
}]

Beachten Sie, dass der Index i zum Erstellen des Ressourcennamens für das Speicherkonto verwendet wird.

Im nächsten Beispiel wird ein Modul mehrmals bereitgestellt:

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
}]

Arrayelemente

Im folgenden Beispiel wird ein Speicherkonto für jeden im storageNames-Parameter angegebenen Namen erstellt. Beachten Sie, dass die Eigenschaft "Name" für jede Ressourceninstanz eindeutig sein muss.

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'
}]

Im nächsten Beispiel wird ein Array durchlaufen, um eine Eigenschaft zu definieren. Es werden zwei Subnetze innerhalb eines virtuellen Netzwerks erstellt. Beachten Sie, dass die Subnetznamen eindeutig sein müssen:

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
      }
    }]
  }
}

Array und Index

Im folgenden Beispiel werden sowohl das Arrayelement als auch der Indexwert beim Definieren des Speicherkontos verwendet:

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'
}]

Im nächsten Beispiel werden sowohl die Elemente eines Arrays als auch ein Index verwendet, um Informationen zu den neuen Ressourcen auszugeben:

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
}]

Wörterbuchobjekt

Um Elemente in einem Wörterbuchobjekt zu durchlaufen, verwenden Sie die items Funktion, die das Objekt in ein Array konvertiert. Verwenden Sie die value-Eigenschaft, um Eigenschaften für die Objekte abzurufen. Beachten Sie, dass die NSG-Ressourcennamen eindeutig sein müssen.

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
}]

Schleife mit Bedingung

Für Ressourcen und Module können Sie einen if-Ausdruck mit der Schleifensyntax hinzufügen, um die Sammlung bedingt bereitzustellen.

Das folgende Beispiel zeigt eine Schleife in Kombination mit einer Bedingungsanweisung. In diesem Beispiel wird eine einzelne Bedingung auf alle Instanzen des Moduls angewendet:

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
  }
}]

Das nächste Beispiel zeigt, wie sie eine Bedingung anwenden, die für das aktuelle Element im Array spezifisch ist:

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
    }]
  }
}]

In Batches bereitstellen

Azure-Ressourcen werden standardmäßig parallel bereitgestellt. Wenn Sie eine Schleife verwenden, um mehrere Instanzen eines Ressourcentyps zu erstellen, werden alle diese Instanzen gleichzeitig bereitgestellt. Die Reihenfolge, in der sie erstellt werden, ist nicht garantiert. Es gibt keinen Grenzwert für die Anzahl der Ressourcen, die parallel bereitgestellt werden können, mit Ausnahme der Gesamtgrenze von 800 Ressourcen, die für die Bicep-Datei gilt.

Es wird empfohlen, nicht alle Instanzen eines Ressourcentyps gleichzeitig zu aktualisieren. Wenn Sie beispielsweise die Produktionsumgebung aktualisieren, sollten Sie die Aktualisierungen staffeln, damit zu jedem Zeitpunkt nur eine bestimmte Anzahl aktualisiert wird. Sie können angeben, dass eine Teilmenge der Instanzen zusammengestapelt und gleichzeitig bereitgestellt werden soll. Die anderen Instanzen warten auf den Abschluss dieses Batches.

Fügen Sie zum seriellen Bereitstellen von Instanzen einer Ressource den batchSize-Decorator hinzu. Legen Sie dessen Wert auf die Anzahl von Instanzen fest, die gleichzeitig bereitgestellt werden sollen. Während früherer Instanzen wird eine Abhängigkeit in der Schleife erstellt, sodass ein Batch erst dann gestartet wird, nachdem der vorherige Batch abgeschlossen wurde.

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'
}]

Legen Sie für eine sequenzielle Bereitstellung die Batchgröße auf 1 fest.

Der batchSize-Decorator befindet sich im sys-Namespace. Wenn Sie diesen Decorator von einem anderen Element gleichen Namens unterscheiden müssen, stellen Sie dem Decorator sys voran: @sys.batchSize(2)

Iteration für eine untergeordnete Ressource

Die beiden folgenden Bicep-Dateien unterstützen das Erstellen mehrerer Instanzen einer untergeordneten Ressource:

Geschachtelte untergeordnete Ressourcen

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}'
    }]
  }
}

Untergeordnete Ressourcen der obersten Ebene

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
}]

Referenzressource/Modulsammlungen

Die Azure Resource Manager-Vorlage (ARM-Vorlage) references gibt ein Array von Objekten zurück, die die Laufzeitzustände einer Ressourcenauflistung darstellen. Da es keine explizite references-Funktion in Bicep gibt und die direkte Verwendung symbolischer Sammlungen erfolgt, übersetzt Bicep sie in eine ARM-Vorlage, die die ARM-Vorlagefunktion references verwendet, während der Code generiert wird. Für das Übersetzungsfeature, das die references Funktion verwendet, um symbolische Sammlungen in ARM-Vorlagen zu transformieren, ist es erforderlich, dass Bicep CLI Version 0.20.X oder höher vorhanden ist. Darüber hinaus sollte in der Datei bicepconfig.json die symbolicNameCodegen-Einstellung enthalten und auf true festgelegt sein.

Die Ausgaben der beiden Beispiele im Ganzzahlindex können wie folgt geschrieben werden:

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)

Diese Bicep-Datei wird in die folgende ARM-JSON-Vorlage transpiliert, die die references Funktion verwendet:

{
  "$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))]"
    }
  }
}

Beachten Sie, dass languageVersion in der vorstehenden ARM-JSON-Vorlage auf 1.10-experimental festgelegt sein muss, und das Ressourcenelement ein Objekt anstelle eines Arrays ist.

Nächste Schritte

Informationen zum Erstellen von Bicep-Dateien finden Sie unter Bicep-Dateistruktur und -syntax.