Flexible Templates ohne Wiederholung
Infrastructure as Code mit Azure Bicep, Teil 2
Ein Bicep-Template mit fest codierten Werten funktioniert für einen einzelnen Testlauf, wird aber schnell unbrauchbar, sobald mehrere Umgebungen wie Dev, Test und Prod bedient werden sollen. Genau an dieser Stelle setzen Parameter und Variablen an: Sie trennen die eigentliche Ressourcendefinition von den konkreten Werten und schaffen damit ein Template, das sich flexibel wiederverwenden lässt, ohne den Code mehrfach zu duplizieren.
Parameter als Eingangstor des Templates
Parameter definieren die Schnittstelle eines Bicep-Templates nach außen. Über sie werden Werte beim Deployment übergeben, ohne den eigentlichen Code anzufassen. Jeder Parameter hat einen Typ, optional einen Standardwert sowie zusätzliche Decorators wie @allowed, @minLength oder @description.
@allowed([ 'dev' 'test' 'prod' ]) param environment string = 'dev'
Der Decorator @allowed begrenzt die möglichen Eingaben auf eine feste Liste. Damit werden fehlerhafte Eingaben schon zur Validierungszeit abgefangen, lange bevor ein Deployment überhaupt gestartet wird. Das ist besonders wertvoll in Teams, in denen mehrere Personen dieselben Templates verwenden.
Variablen zur Ableitung von Werten
Während Parameter von außen kommen, werden Variablen innerhalb des Templates berechnet. Ein typisches Muster ist die Ableitung eines SKU-Namens abhängig von der gewählten Umgebung, etwa mit einer Objekt-Map.
var skuByEnvironment = {
dev: 'Standard_LRS'
test: 'Standard_LRS'
prod: 'Standard_GRS'
}
var storageName = 'st${environment}${uniqueString(resourceGroup().id)}'
Diese Kombination aus Parameter und Variable sorgt dafür, dass dieselbe Ressourcendefinition je nach Umgebung ein unterschiedliches Verhalten zeigt, ohne dass der Ressourcenblock selbst verändert werden muss.
Parameter versus Variable: der entscheidende Unterschied
Beide Konstrukte halten Werte, unterscheiden sich aber in der Herkunft dieser Werte. Ein Parameter ist die Eingabeschnittstelle eines Templates: Sein Wert kommt von außen, beim Deployment-Aufruf, und er kann sich von Deployment zu Deployment ändern. Eine Variable dagegen wird innerhalb des Templates berechnet und ist dem Aufrufer nicht zugänglich; ihr Wert ergibt sich ausschließlich aus Parametern, anderen Variablen oder festen Angaben im Code.
Daraus ergibt sich eine einfache Faustregel: Soll ein Wert von außen steuerbar sein, etwa die Zielumgebung oder die Location, wird daraus ein Parameter. Ergibt sich ein Wert dagegen aus bereits vorhandenen Werten, etwa ein zusammengesetzter Ressourcenname oder eine SKU-Zuordnung, gehört er als Variable ins Template. Parameter können zudem mit Decorators wie @allowed oder @minLength eingeschränkt werden, Variablen nicht, da ihr Wert ohnehin vollständig vom Template selbst kontrolliert wird.
Vollständiges Beispiel
Das folgende Beispiel kombiniert Parameter, Variablen und eine Storage-Account-Ressource zu einem vollständigen, funktionsfähigen Template:
@allowed([
'dev'
'test'
'prod'
])
param environment string = 'dev'
param location string = resourceGroup().location
var skuByEnvironment = {
dev: 'Standard_LRS'
test: 'Standard_LRS'
prod: 'Standard_GRS'
}
var storageName = 'st${environment}${uniqueString(resourceGroup().id)}'
resource storage 'Microsoft.Storage/storageAccounts@2023-05-01' = {
name: storageName
location: location
sku: {
name: skuByEnvironment[environment]
}
kind: 'StorageV2'
tags: {
environment: environment
}
}
output storageAccountName string = storage.name
Der Parameter environment steuert über die Variable skuByEnvironment direkt die SKU der Ressource. Gleichzeitig fließt derselbe Wert in den Ressourcennamen und in ein Tag ein. Damit entsteht ein Template, das mit einem einzigen Parameterwert drei unterschiedliche Stellen konsistent steuert.
Warum ist das wichtig?
Ohne Parameter und Variablen müsste für jede Umgebung eine eigene Kopie des Templates gepflegt werden, was den Wartungsaufwand erhöht und zu Inkonsistenzen führt. Mit einer sauberen Struktur bleibt ein einziges Template die alleinige Quelle der Wahrheit, während sich das Verhalten über klar definierte Eingaben steuern lässt.
Parameter übergeben: verschiedene Wege
Ein Parameterwert lässt sich auf mehreren Wegen in ein Deployment einbringen. Die grundlegenden CLI-Befehle dafür wurden bereits in Teil 1 dieser Serie zu Infrastructure as Code mit Azure Bicep gezeigt; hier geht es um die Optionen, einen Wert konkret zu übergeben.
Ist ein Parameter mit einem Standardwert versehen, genügt ein Deployment ganz ohne explizite Angabe. Für einzelne, abweichende Werte reicht eine Inline-Übergabe:
--parameters environment=prod
Bei mehreren Werten oder wiederkehrenden Deployments ist eine eigene Parameterdatei übersichtlicher. Die klassische Variante ist eine JSON-Parameterdatei:
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"environment": {
"value": "prod"
}
}
}
--parameters @02-bicep-parameter-variablen.parameters.json
Die Bicep-native Alternative dazu ist eine .bicepparam-Datei. Sie nutzt dieselbe Sprache wie das Template und wird über using damit verknüpft, inklusive Typprüfung und IntelliSense im Editor:
using '02-bicep-parameter-variablen.example.bicep' param environment = 'prod' --parameters 02-bicep-parameter-variablen.example.bicepparam
Für schnelle, einzelne Tests eignet sich die Inline-Übergabe am besten, für mehrere Umgebungen die .bicepparam-Datei. Überschneiden sich mehrere Quellen für denselben Parameter, gilt für die Priorität der Auswertung eine feste Rangfolge: Default im Template < Parameterdatei < Kommandozeile. Ein Wert auf der Kommandozeile gewinnt also immer, gefolgt von der Parameterdatei; der Default im Template greift nur, wenn keine der beiden anderen Quellen einen Wert liefert.
Best Practices
- Parameter erhalten sprechende Namen und, wo sinnvoll, eine @description.
- Eingeschränkte Wertebereiche werden über @allowed abgesichert, nicht nur in der Dokumentation erwähnt.
- Variablen übernehmen abgeleitete Logik, damit Ressourcenblöcke lesbar bleiben.
- Standardwerte werden bewusst gesetzt, damit ein Template auch ohne explizite Parameter lauffähig bleibt.
- Für mehrere Umgebungen wird eine .bicepparam-Datei pro Umgebung einer langen Inline-Parameterliste vorgezogen.
Häufige Fehler
- Zu viele Parameter ohne klare Struktur erschweren die Wiederverwendung.
- Fehlende @allowed-Einschränkungen führen zu Laufzeitfehlern statt frühzeitiger Validierung.
- Variablen werden für Werte verwendet, die eigentlich Parameter sein sollten, wodurch Flexibilität verloren geht.
Fazit
Parameter und Variablen bilden die Grundlage jeder flexiblen Bicep-Vorlage. Sie ermöglichen es, ein einziges Template über mehrere Umgebungen hinweg konsistent zu betreiben, ohne Duplikate zu pflegen.
Im nächsten Teil der Serie folgt der nächste logische Schritt: Schleifen, mit denen sich mehrere gleichartige Ressourcen aus einer einzigen Definition erzeugen lassen.