StartRöstnotizenAusschankDie Röstkurve
M365 Barista Talk · LinkedIn

R-03 Foundry & Azure

Bicep Patterns für wartbare Azure-Plattformen

22.10.20268 MinutenDunkel · UmsetzungTeilen
Ferdi Lethen-Oellers neben dem Schriftzug „Bicep Patterns: nicht anfassen, läuft?“

Stell dir vor, du bist drei Wochen im Urlaub. In der zweiten Woche muss im Prod-VNet eine Firewall-Regel geändert werden, und zwar dringend. Deine Kollegin öffnet dein Bicep-Repo. Findet sie die richtige Stelle in fünf Minuten? Oder ruft sie dich am Strand an?

Das ist für mich der ehrlichste Test für Infrastructure as Code. Nicht, ob das Template heute läuft, sondern ob jemand anderes es morgen ändern kann, ohne Angst zu haben. Die Sprache macht es einem leicht, und genau deshalb wächst die erste Datei einfach immer weiter. Wartbar wird eine Plattform erst durch ein paar Muster, die du von Anfang an einhältst. Fünf davon zeige ich dir hier.

1. Module statt Monolith

Die wichtigste Regel: Eine Datei beschreibt eine Sache. Das Netzwerk, die Log-Analytics-Workspaces und der Key Vault bekommen jeweils ein eigenes Modul. Die main.bicep ist dann nur noch Orchestrierung. Sie ruft Module auf und reicht Outputs von einem Modul ans nächste weiter.

targetScope = 'subscription'

param location string = 'germanywestcentral'
param env string

resource rg 'Microsoft.Resources/resourceGroups@2024-03-01' = {
  name: 'rg-platform-${env}'
  location: location
}

module logging 'modules/logging.bicep' = {
  scope: rg
  name: 'logging-${env}'
  params: { location: location, env: env }
}

module network 'modules/network.bicep' = {
  scope: rg
  name: 'network-${env}'
  params: {
    location: location
    env: env
    logAnalyticsId: logging.outputs.workspaceId
  }
}

Zwei Details helfen im Alltag. Gib jedem Modul-Deployment einen sprechenden name, dann findest du es im Portal unter „Deployments“ sofort. Und definiere Outputs nur dort, wo ein anderes Modul sie wirklich braucht.

2. Nicht selbst bauen, was es schon gibt: Azure Verified Modules

Bevor du ein Storage-Modul von Hand schreibst, schau in die Registry. Azure Verified Modules sind vorgefertigte, getestete und verifizierte Module von Microsoft, und sie sind inzwischen der einzige Standard in der öffentlichen Bicep-Registry.

Für ältere Templates heißt das: Die früheren Community-Module bleiben zwar in der Registry, und deine Referenzen funktionieren weiter. Ihr Quellcode ist aber durch einen Verweis auf den AVM-Nachfolger ersetzt, und VS Code schlägt sie nicht mehr vor. Sie bekommen also keine Updates mehr. Dein Code bricht nicht, er veraltet still. Genau deshalb lohnt sich der Blick in die alten Templates.

Die Einbindung läuft über den Alias br/public:

module vault 'br/public:avm/res/key-vault/vault:0.11.0' = {
  name: 'kv-${env}'
  params: {
    name: 'kv-plat-${env}'
    location: location
    enablePurgeProtection: true
  }
}

Die Version 0.11.0 ist ein Beispiel. Nimm die aktuelle Version aus dem AVM-Modulindex und pinne sie fest.

Das ist nicht in jedem Fall die ganze Lösung. Ein Wrapper-Modul für deine Unternehmensvorgaben bleibt sinnvoll, zum Beispiel für feste Tags, Diagnose-Einstellungen und Namenskonvention. Der Wrapper ruft intern das AVM-Modul auf. So pflegst du deine Standards an einer Stelle und musst das Rad nicht neu erfinden.

3. Parameter-Dateien pro Umgebung

Wenn in deiner main.bicep if (env == 'prod') steht, ist das ein Warnsignal. Umgebungsunterschiede gehören in Parameter-Dateien, nicht in die Logik. Dafür gibt es .bicepparam. Die Datei ist typisiert und prüft deine Werte schon im Editor:

using './main.bicep'

param env = 'prod'
param location = 'germanywestcentral'

Pro Umgebung gibt es eine Datei (dev.bicepparam, test.bicepparam, prod.bicepparam) und ein Template. Mit @allowed, @minLength und @description an den Parametern im Template fängst du Tippfehler ab, bevor sie in Azure landen.

⚠️ Achtung
Geheimnisse gehören nicht in Parameter-Dateien. Parameter-Dateien landen im Git, und das Git-Log vergisst nichts. Markiere den Parameter im Template mit @secure() und lass die .bicepparam-Datei den Wert direkt aus dem Key Vault holen.

using './main.bicep'

param adminPassword = getSecret('<subscription-id>', 'rg-secrets', 'kv-secrets-prod', 'adminPassword')

Damit das klappt, muss beim Key Vault enabledForTemplateDeployment aktiviert sein.

4. Deployment Stacks: Aufräumen gehört zum Deployment

Bicep legt Ressourcen an und ändert sie. Wenn du eine Ressource aus dem Template löschst, bleibt sie in Azure trotzdem stehen. Nach einem Jahr hast du so eine Plattform, die nicht mehr zu deinem Code passt.

Deployment Stacks lösen genau das. Ein Stack merkt sich, welche Ressourcen er verwaltet. Du entscheidest, was mit Ressourcen passiert, die nicht mehr im Template stehen:

Einstellung Was passiert mit entfernten Ressourcen?
detachAll Sie werden nur aus der Verwaltung gelöst und bleiben in Azure.
deleteResources Die Ressourcen werden gelöscht.
deleteAll Zusätzlich werden auch die Resource Groups gelöscht.

Mit Deny-Settings schützt du verwaltete Ressourcen außerdem vor manuellen Änderungen, entweder nur gegen Löschen (denyDelete) oder gegen Ändern und Löschen (denyWriteAndDelete).

az stack sub create \
  --name stack-platform-prod \
  --location germanywestcentral \
  --parameters prod.bicepparam \
  --action-on-unmanage detachAll \
  --deny-settings-mode denyWriteAndDelete

Weil die .bicepparam-Datei per using schon auf das Template zeigt, brauchst du --template-file hier nicht.

Mein Rat: Starte auf einer Test-Subscription mit detachAll, bis du verstehst, was der Stack alles als „seins“ betrachtet. Erst dann stellst du auf deleteResources um. Ein Stack mit Löschmodus im falschen Scope löscht dir sonst Dinge, die du behalten wolltest. Das ist nicht trivial, und ein Montagmorgen mit leerer Resource Group ist kein guter Start in die Woche.

5. Qualität in die Pipeline: Linter, What-if und Review

Wartbarkeit entsteht auch durch Automatik. Drei Dinge gehören in jede Pull-Request-Pipeline:

Schritt 1: Build und Linter. az bicep build oder az bicep lint mit den Regeln aus der bicepconfig.json. Dort legst du fest, welche Regeln als Warnung und welche als Fehler gelten. Mein Tipp: Aktivier die Regel use-recent-module-versions. Sie warnt dich, sobald eine gepinnte AVM-Version veraltet ist.

Schritt 2: What-if. az deployment sub what-if zeigt im PR, was sich ändern würde. Der Reviewer sieht dann nicht nur Code, sondern die Wirkung auf die Umgebung.

Schritt 3: Gate vor Prod. Prod wird erst nach Freigabe ausgerollt. Dev und Test laufen automatisch.

What-if ist keine Garantie, denn die Vorschau kann bei manchen Ressourcentypen Rauschen zeigen. Trotzdem ist sie besser als ein Blindflug.

Welches Muster für welchen Fall?

Situation Muster Aufwand
Template wird unübersichtlich Module aufteilen gering
Standardressourcen (Key Vault, Storage, VNet) Azure Verified Modules gering
Dev, Test und Prod weichen ab .bicepparam pro Umgebung gering
Altlasten und manuelle Eingriffe Deployment Stacks mittel
Mehrere Teams, geteilte Plattform Pipeline mit Linter und What-if mittel

Was bleibt

Bicep wird nicht durch mehr Features wartbar, sondern durch Disziplin. Teile in Module auf, nutze geprüfte Bausteine, trenne Konfiguration vom Code und lass Stacks und Pipeline aufpassen, dass Code und Realität zusammenbleiben. Du musst nicht alles auf einmal einführen. Fang mit der Modul-Aufteilung an, das bringt am schnellsten Ruhe in die Dateien. Und dein Urlaub bleibt ein Urlaub.

☕ Espresso-Moment: Ein guter Espresso braucht ein sauberes Rezept, nicht mehr Zutaten. Dein Template auch.

Das nimmst du mit

  • Zerlege die main.bicep in Module, eine Verantwortung pro Datei.
  • Prüfe vor jedem Eigenbau, ob es ein Azure Verified Module gibt, und pinne die Version.
  • Durchsuche alte Templates nach Nicht-AVM-Modulen. Sie laufen weiter, bekommen aber keine Updates mehr.
  • Ziehe Umgebungsunterschiede in .bicepparam-Dateien. Secrets holst du per getSecret aus dem Key Vault, nie aus dem Repo.
  • Teste Deployment Stacks erst mit detachAll, bevor du Ressourcen automatisch löschen lässt.
  • Lass in jedem Pull Request Linter und What-if laufen, inklusive use-recent-module-versions.

Frage oder Feedback? Schreib mir auf LinkedIn.

Diese Röstnotiz teilen

Ferdi Lethen-Oellers
Ferdi Lethen-Oellers

Senior Modern Workplace Consultant bei der amexus, Microsoft MVP, Autor von „Microsoft 365 Administration für Dummies“.