Wer mit Infrastructure-as-Code in Azure beschäftigt ist, hat sicher schon von Microsoft Bicep gehört – einer neuen Sprache zum Erstellen von Ressourcen in der Cloud. Zeit für einen Überblick, der zeigt, wieso es zur Entwicklung von Bicep kam, was die neue Sprache kann und welche Vorteile sie für den Admin bietet.
Microsoft Bicep ist eine relativ neue, deklarative Sprache zur Definition von Azure-Ressourcen. Sie bietet eine benutzerfreundliche Syntax und erleichtert das Erstellen von Ressourcen deutlich. Das Ziel dieses Artikels ist es nicht, alle Sprachelemente von Bicep zu behandeln, dafür gibt es zu viele. Vielmehr wollen
wir eine Übersicht geben, was die Neuentwicklung generell leisten kann und wo die größten Unterschiede zu herkömmlichen ARM-Vorlagen auf JSON-Basis liegen. Die Vorteile von Microsoft Bicep gegenüber ARM-Vorlagen sind zum Beispiel eine höhere Lesbarkeit, eine einfachere Syntax, das Arbeiten mit Bedingungen
und der komfortablere Umgang mit Modulen.
Exklusiv für Azure
Um in Azure Ressourcen deklarativ zu erstellen, gibt es schon sehr lange ARMVorlagen. Diese konstruieren sich aus JSON, einer universell einsetzbaren Sprache für die Übertragung und zum Speichern strukturierter Daten. Sie wurde nicht speziell für Azure entwickelt und zeigt sich bei komplexen Daten schnell unübersichtlich.
Microsoft Bicep ist angetreten, genau dieses Manko zu beheben. Die Sprache ist exklusiv für Azure erdacht worden. Ein Ziel dabei war, die Komplexität von ARMVorlagen zu vermeiden, um die Definition von Ressourcen einfacher zu gestalten. Bicep-Dateien kommen in der Regel mit wesentlich weniger Zeilen aus als
ARM-Vorlagen – und mit weniger Klammern aller Art. Auf der anderen Seite heißt dies auch: Die Sprache lässt sich nur für die Azure-Cloud verwenden.
Microsoft Bicep ist eine relativ neue, deklarative Sprache zur Definition von Azure-Ressourcen. Sie bietet eine benutzerfreundliche Syntax und erleichtert das Erstellen von Ressourcen deutlich. Das Ziel dieses Artikels ist es nicht, alle Sprachelemente von Bicep zu behandeln, dafür gibt es zu viele. Vielmehr wollen
wir eine Übersicht geben, was die Neuentwicklung generell leisten kann und wo die größten Unterschiede zu herkömmlichen ARM-Vorlagen auf JSON-Basis liegen. Die Vorteile von Microsoft Bicep gegenüber ARM-Vorlagen sind zum Beispiel eine höhere Lesbarkeit, eine einfachere Syntax, das Arbeiten mit Bedingungen
und der komfortablere Umgang mit Modulen.
Exklusiv für Azure
Um in Azure Ressourcen deklarativ zu erstellen, gibt es schon sehr lange ARMVorlagen. Diese konstruieren sich aus JSON, einer universell einsetzbaren Sprache für die Übertragung und zum Speichern strukturierter Daten. Sie wurde nicht speziell für Azure entwickelt und zeigt sich bei komplexen Daten schnell unübersichtlich.
Microsoft Bicep ist angetreten, genau dieses Manko zu beheben. Die Sprache ist exklusiv für Azure erdacht worden. Ein Ziel dabei war, die Komplexität von ARMVorlagen zu vermeiden, um die Definition von Ressourcen einfacher zu gestalten. Bicep-Dateien kommen in der Regel mit wesentlich weniger Zeilen aus als
ARM-Vorlagen – und mit weniger Klammern aller Art. Auf der anderen Seite heißt dies auch: Die Sprache lässt sich nur für die Azure-Cloud verwenden.
Skripte: Von ARM zu Bicep und zurück
Azure führt allerdings Bicep-Code nicht direkt aus, sondert wandelt diesen in traditionelle ARM-Vorlagen um. Was am Ende aber bedeutet, dass Bicep nur das leisten kann, was auch ARM-Vorlagen bewirken können. Natürlich lassen sich ARM-Dateien auch in Bicep umwandeln. Microsoft stellt dafür eine beispielhafte
Anwendung zur Verfügung [1]. In dieser sind viele Vorlagen enthalten, sodass Sie sofort mit Bicep starten können.
Bild 1 zeigt die Vorlage "microsoft.compute/vm-windows-admincenter/main.bicep" links und die korrespondierende ARM-Datei rechts. Beide sind vergleichsweise einfach und genau deshalb als Beispiel gut geeignet. Wenn Sie sich die Bicep-Datei anschauen, fallen sofort Muster
aus vertrauten Sprachen auf. So können Sie Parameter mit "param" und Variablen mit "var" deklarieren.
Bild 1: Der sogenannte Bicep Playground, links mit einer Bicep- und rechts mit einer ARM-Datei.
Parametern lässt sich dabei ein Standartwert mitgeben und Sie können festlegen, welche Werte der Parameter annehmen kann – dies alles mit vergleichsweise wenig Code. Das folgende Snippet deklariert einen Parameter "publicIPAllocationMethod" mit dem Standardwert "Dynamic", wobei für den Parameter nur die Werte
"Dynamic" und "Static" erlaubt sind.
@description('Allocation method for the Public IP used to access the Virtual Machine.')
@allowed([
'Dynamic'
'Static'
])
param publicIPAllocationMethod
string = 'Dynamic'
Der korrespondierende Code für die ARM-Vorlage ist da wesentlich komplexer und länger:
"publicIPAllocationMethod": {
"type": "string",
"defaultValue": "Dynamic",
"allowedValues": [
"Dynamic",
"Static"
],
"metadata": {
"description": "Allocation method for the Public IP used to access the Virtual Machine."
}
},
Die Deklaration von Ressourcen ist ebenfalls einfacher. Der folgende Code deklariert ein Speicherkonto in Bicep:
Dabei gilt die Konvention, dass nach dem Schlüsselwort "resource" ebendiese einen symbolischen Namen erhält. Dies ist nicht der Name der Ressourcen in Azure. Diesen legen Sie vielmehr über "name:" fest. Er folgt der Namenskonvention der Ressourcen in Azure und ist in der Regel ein
Parameter. Hinter dem symbolischen Namen der Ressourcen folgt der Ressourcentyp, wobei sich mit "@" noch die API-Version angeben lässt.
Sie können Bicep sehr gut mit Visual Studio Code schreiben, das die Sprache schon integriert hat. IntelliSense ist ebenso verfügbar wie eine visuelle Vorschau der in Bicep definierten Ressourcen. Auf dem Client ausführen lassen sich Bicep-Vorlagen mit der PowerShell oder der
Azure-CLI. Dafür ist aber eine vergleichsweise aufwendige Installation nötig – unter [2] gibt es eine detaillierte Anleitung.
Das alles können Sie sich aber auch ganz sparen und das Skript gleich in der Azure Cloud Shell ausführen. Dazu müssen Sie es jedoch jedes Mal hochladen. Ein exemplarischer Aufruf mit PowerShell in Windows könnte wie folgt aussehen:
Connect-AzAccount # Nur, wenn nicht Cloud Shell
New-AzResourceGroupDeployment -ResourceGroupName projectx1000 -TemplateFile "C:\Scripts\bicep\storage.bicep" # in der Cloud Shell ein anderer Pfad
Weitere Sprachkonstrukte
Das Arbeiten mit Schleifen und Bedingungen ist in Bicep wesentlich einfacher als in JSON. Selbst wenn Sie nur die Grundlagen von Programmierung verstehen, sollten Sie sich hier gut zurechtfinden. Angenommen, Sie möchten zwei Speicherkonten erstellen, die beide natürlich
über einen eindeutigen Namen verfügen müssen, wäre dies mit dem Code aus Listing 1 möglich.
Listing 1: Speicherkonto anlegen
param location string = resourceGroup().location
param storageCount int = 2
resource storageAcct 'Microsoft.Storage/storageAccounts@2021-06-01' = [for i in range(0, storageCount): {name: '${i}storage${uniqueString(resourceGroup().id)}'
location: location
sku: {/
name: 'Standard_LRS'
}
kind: 'Storage'
}]
Das Schüsselwort ist hier "for", das über den Parameter "storageCount" iteriert und damit die zwei Speicherkonten anlegt. Den eindeutigen Namen erhalten diese außer über die Zahl des Parameters über die Funktion "uniqueString". Diese erstellt einen eindeutigen Namen aus der ID der
Ressourcengruppe, indem sie aus diesem Wert ein Hash generiert.
Bicep kennt Bedingungen, unter anderen mit "if ". Damit lassen sich schnell und einfach Entscheidungen treffen. Interessant ist dies besonders dann, wenn Sie Ressourcen abhängig von Parametern bereitstellen wollen (oder auch nicht). Im folgenden Beispiel gehen wir davon aus,
dass es eine Stage- und eine Produktionsumgebung gibt. Kommt das Skript in der Stage-Umgebung zur Ausführung, soll die Ressource nicht wirklich erstellt werden, in der produktiven Umgebung hingegen schon. Sie können einem Bicep-Skript Argumente beim Aufruf übergeben. Damit ist es zum Beispiel möglich, dass ein und
dasselbe Skript unterschiedliche Ressourcen in unterschiedlichen Umgebungen erstellt – siehe Listing 2.
Listing 2: Nutzung von Parametern
param storageAccountName string
param location string = resourceGroup().location
@allowed([
'stage'
'prod'
])
param stageOrProd string = 'stage'
resource sa 'Microsoft.Storage/storageAccounts@2019-06-01' = if (stageOrProd =='prod') {
name: storageAccountName
location: location
sku: {
name: 'Standard_LRS'{
tier: 'Standard' {
}
kind: 'StorageV2'
properties: {
accessTier: 'Hot'
}
}
Ausgaben fügen Sie mit "output" hinzu. Die Deklaration lautet output <name> <data-type> = <value>. Jede Ausgabe braucht also neben dem Ausgabewert auch einen Datentyp. Praktisch ist, dass Sie auf alle Werte einer zuvor erstellten Ressource zugreifen können. Bild 2 zeigt
eine mögliche Ausgabe beim Schreiben in Visual Studio Code nach dem Erstellen der zwei Speicherkonten mit den möglichen Parametern. Die Ausgabe selbst bietet viele Optionen, es lohnt sich, das entsprechende Dokument [3] zu lesen.
Bild 2: So sehen in Bicep Ausgaben mit Parametern aus.
Mit Modulen arbeiten
Ein weiterer Vorteil von Bicep ist die einfache Verwendung von Modulen. In anderen Sprachen ist von Include-Dateien die Rede. Auch dies geht zwar mit ARMVorlagen, gestaltet sich aber wesentlich komplexer. Wenn wir in Bicep die Deklaration des Speicherkontos in ein Modul auslagern und dieses später aufrufen
möchten, könnte dies so aussehen.
module stgModule '../storageAccount.bicep' = {
name: 'storageDeploy'
params: {
storagePrefix: 'examplestg1'
}
}
Auch das Modul hat einen symbolischen Namen, mit dem später auf das Modul selbst und seine Ausgaben zugegriffen wird. Hinter dem Namen steht der Name und Pfad der Moduldatei, gefolgt von Parametern. Diese sind optional – es ist auch möglich, alle Parameter in der Moduldatei anzugeben. Die Moduldatei selbst ist ein
Bicep-Skript ohne weitere Deklaration.
Um die Ausgabe mit Werten aus dem Modul zu erhalten, referenzieren Sie einfach auf den Modulnamen und ergänzen diesen mit Outputs. Fügen Sie dann die Eigenschaft hinzu, die Sie abrufen möchten. Beachten sie, dass die Ausgabe vom Typ "object" ist:
Viele Organisationen verfügen schon über eine große Anzahl von ARM-Dateien, in denen sie immer wiederkehrende Ressourcen definiert haben. Es wäre wenig sinnvoll, diese mit einem Ruck alle auf Bicep zu konvertieren. Dies ist auch nicht notwendig, da Bicep eben nicht nur Bicep-Vorlagen als Module verwenden
kann, sondern auch ARM-Vorlagen. In dem Fall binden Sie beim Anflanschen des Moduls einfach die ARM-Datei ein. Ein möglicher Weg für einen sanften Übergang wäre es, die bestehenden ARMDateien zu belassen und nur neuen Code in Bicep zu schreiben.
Es gibt aber durchaus Gründe, überhaupt nicht mit Bicep zu arbeiten. Haben Sie sich zum Beispiel erst kürzlich in ARM eingearbeitet, ist es möglicherweise schwierig, sofort wieder eine neue Sprache zu lernen. Diese ist zwar komfortabler und leichter als ARM-Vorlagen, leistet aber am Ende das Gleiche. Wenn Sie ein
cloudübergreifendes Framework für Infrastructure-as-Code einsetzen, und dieses Framework ihnen kein Bicep-Skript ausgibt, sondern nur ARM, müssten sie die Dateien anschließend in Bicep konvertieren. Die Frage ist, ob es das wert ist.
Fazit
Bicep ist als speziell für die Bereitstellung von Ressourcen in Azure entwickelte Sprache ein großer Wurf und weist eine erheblich einfachere Syntax auf als ARMVorlagen. Die Einarbeitung ist simpel, die Fehlerwahrscheinlichkeit gering. Für Neueinsteiger ist es das Mittel der Wahl, aber auch für alte Hasen biete Bicep viel
Nützliches.