Eine Bicep-Datei ist zu groß geworden? Erstelle Module

Veröffentlicht am:

main.bicep enthält inzwischen Eingaben, Benennungslogik, ein Speicherkonto, Blob-Einstellungen, eine Ressourcenschleife, eine bedingte Ressource und Ausgaben. Networking, Monitoring oder einen weiteren Dienst in dieselbe Datei einzufügen, würde Reviews und Wartung zunehmend erschweren.

Behalte main.bicep als Bereitstellungseinstieg und verschiebe die vollständige Storage-Implementierung in ein fokussiertes Modul. Das Refactoring darf die vorhandenen TEST-Ressourcen weder neu erstellen noch neu konfigurieren.

Storage-Modul erstellen

Erstelle modules/storage.bicep:

param applicationName string
param containerNames array
param costCenter string
param deployAuditContainer bool
param environment string
param location string
param owner string
param storageSku string

var normalizedEnvironment = toLower(environment)
var storageAccountName = 'stct${normalizedEnvironment}${uniqueString(resourceGroup().id)}'
var commonTags = {
  Application: applicationName
  CostCenter: costCenter
  Environment: toUpper(normalizedEnvironment)
  ManagedBy: 'Bicep'
  Owner: owner
}

resource storageAccount 'Microsoft.Storage/storageAccounts@2025-06-01' = {
  name: storageAccountName
  location: location
  tags: commonTags
  sku: {
    name: storageSku
  }
  kind: 'StorageV2'
  properties: {
    allowBlobPublicAccess: false
    minimumTlsVersion: 'TLS1_2'
    supportsHttpsTrafficOnly: true
  }
}

resource blobService 'Microsoft.Storage/storageAccounts/blobServices@2025-06-01' = {
  parent: storageAccount
  name: 'default'
  properties: {
    containerDeleteRetentionPolicy: {
      enabled: true
      days: 7
    }
    deleteRetentionPolicy: {
      enabled: true
      days: 7
    }
  }
}

resource appContainers 'Microsoft.Storage/storageAccounts/blobServices/containers@2025-06-01' = [
  for containerName in containerNames: {
    parent: blobService
    name: containerName
    properties: {
      publicAccess: 'None'
    }
  }
]

resource auditContainer 'Microsoft.Storage/storageAccounts/blobServices/containers@2025-06-01' = if (deployAuditContainer) {
  parent: blobService
  name: 'audit'
  properties: {
    publicAccess: 'None'
  }
}

output storageAccountName string = storageAccount.name
output storageAccountId string = storageAccount.id
output blobEndpoint string = storageAccount.properties.primaryEndpoints.blob
output containerIds array = [
  for i in range(0, length(containerNames)): appContainers[i].id
]
output auditContainerId string? = deployAuditContainer ? auditContainer.id : null

Das Modul besitzt einen klaren Vertrag:

  • Parameter sind die Werte, die es von der aufrufenden Datei benötigt
  • Ressourcen sind die Storage-Implementierung, die es verwaltet
  • Outputs sind die Werte, die es an die aufrufende Datei zurückgibt

main.bicep zum Orchestrator machen

Behalte die vorhandenen Parameterdeklarationen in main.bicep. Entferne die Storage-Variablen, Ressourcen und direkten Ressourcenausgaben und füge Folgendes hinzu:

module storage './modules/storage.bicep' = {
  name: '${deployment().name}-storage'
  params: {
    applicationName: applicationName
    containerNames: containerNames
    costCenter: costCenter
    deployAuditContainer: deployAuditContainer
    environment: environment
    location: location
    owner: owner
    storageSku: storageSku
  }
}

output storageAccountName string = storage.outputs.storageAccountName
output storageAccountId string = storage.outputs.storageAccountId
output blobEndpoint string = storage.outputs.blobEndpoint
output containerIds array = storage.outputs.containerIds
output auditContainerId string? = storage.outputs.?auditContainerId

main.bicep übergibt seine Parameterwerte über params. Zurückgegebene Werte liest die Datei über storage.outputs.

Der Modulbereitstellungsname kombiniert den Namen der übergeordneten Bereitstellung mit -storage. Dadurch verwenden verschiedene übergeordnete Bereitstellungen im selben Bereich nicht einen einzigen festen Namen.

Die DEV-, TEST- und PROD-Dateien .bicepparam bleiben unverändert. Sie sind weiterhin mit main.bicep verknüpft, dessen Eingabevertrag sich nicht geändert hat.

Refactoring validieren

Prüfe beide Dateien mit dem Linter:

az bicep lint \
  --file modules/storage.bicep

az bicep lint \
  --file main.bicep

Kompiliere anschließend die TEST-Parameterdatei mit dem überarbeiteten Einstiegspunkt:

az bicep build-params \
  --file environments/test.bicepparam \
  --stdout > /dev/null

Fahre nur fort, wenn alle Befehle ohne Diagnose abgeschlossen werden.

Beweisen, dass Ressourcen nicht neu erstellt werden

Wähle das CloudTrips-TEST-Abonnement und führe What-if aus:

az account set \
  --subscription "<Name oder ID des CloudTrips-TEST-Abonnements>"

az deployment group what-if \
  --resource-group rg-cloudtrips-bicep-test-weu \
  --parameters environments/test.bicepparam

Die Vorschau kann eine verschachtelte Ressource Microsoft.Resources/deployments für das Storage-Modul zeigen. Sie kann außerdem Modify für den Blob-Dienst und seine Container melden, weil Azure Standardeigenschaften ergänzt, die in der Bicep-Datei nicht deklariert sind. In dieser Bereitstellung sind folgende Zeilen zu erwarten:

  • allowPermanentDelete: false und staticWebsite.enabled: false beim Blob-Dienst
  • defaultEncryptionScope: "$account-encryption-key" und denyEncryptionScopeOverride: false bei jedem Container

Das Minuszeichen bedeutet, dass ein Wert in der aktuellen Ressourcendarstellung von Azure vorhanden ist, aber in der vorgeschlagenen Vorlage fehlt. Azure stellt diese Anbieterstandardwerte nach der Bereitstellung wieder her. Microsoft bezeichnet solche Einträge deshalb als What-if-Rauschen.

Bestätige, dass das Speicherkonto NoChange meldet und die Vorschau kein Create, Delete oder Ersetzen des Speicherkontos, Blob-Dienstes oder der Container enthält. Namen und Ressourcen-IDs müssen gleich bleiben; nur die Organisation des Bicep-Codes ändert sich.

TEST-What-if-Ergebnis nach dem Modul-Refactoring mit Anbieterstandard-Rauschen, aber ohne Ersetzen von Ressourcen

Modul-Refactoring bereitstellen

Stelle dieselbe TEST-Konfiguration bereit:

az deployment group create \
  --name deploy-cloudtrips-storage-test-modules \
  --resource-group rg-cloudtrips-bicep-test-weu \
  --parameters environments/test.bicepparam \
  --query "properties.{state:provisioningState,outputs:outputs}" \
  --output yaml

Dadurch entstehen zwei Bereitstellungseinträge: --name legt den Namen der übergeordneten Bereitstellung fest, und der Modulausdruck ergänzt -storage für die verschachtelte Bereitstellung. Die Storage-Ressourcen werden nur einmal über dieses Modul bereitgestellt.

Bestätige den Status Succeeded und dass die Ausgaben des Einstiegspunkts weiterhin die Werte für Speicherkonto und Container enthalten.

Verschachtelte Modulbereitstellung überprüfen

Ein lokales Bicep-Modul wird in eine verschachtelte ARM-Bereitstellung kompiliert. Prüfe die Modulbereitstellung:

az deployment group show \
  --resource-group rg-cloudtrips-bicep-test-weu \
  --name deploy-cloudtrips-storage-test-modules-storage \
  --query "properties.{state:provisioningState,outputs:outputs}" \
  --output yaml

Bestätige den verschachtelten Status Succeeded. Im Azure-Portal sollte die Seite Bereitstellungen der Ressourcengruppe sowohl die übergeordnete Bereitstellung als auch die Storage-Modulbereitstellung anzeigen.

Seite der Ressourcengruppen-Bereitstellungen mit erfolgreicher übergeordneter und Storage-Modulbereitstellung

CloudTrips besitzt nun einen kleinen Einstiegspunkt und ein Storage-Modul mit definiertem Ein-/Ausgabevertrag. Zukünftige Dienste können als eigene Module hinzugefügt werden, ohne sämtliche Implementierungsdetails nach main.bicep zurückzubringen.