Zum Inhalt springen
sw
en

Tippe um zu suchen

Automatisierung & DevOps

Infrastructure as Code im Vergleich: Terraform, Ansible, Bicep

Terraform, Ansible und Bicep im Praxisvergleich: State-Handling, Entscheidungsbaum, Hybrid-Ansaetze und Migrationspfade fuer KMU-Infrastruktur.

12 Min Lesezeit Fortgeschritten Zuletzt aktualisiert:

Warum dieser Vergleich ueberhaupt noetig ist

In vielen Schweizer KMU sieht die Realitaet so aus: Ein paar VMs wurden vor Jahren manuell im Hyper-V-Cluster oder in Azure angelegt, die Konfiguration lebt in einem Wiki-Artikel (oder gar nur im Kopf des Admins), und niemand kann mit Sicherheit sagen, warum Server-03 eine andere Firewall-Regel hat als Server-04. Infrastructure as Code (IaC) loest genau dieses Problem: Infrastruktur wird als Text beschrieben, versioniert, geprueft und reproduzierbar ausgerollt.

Das Missverstaendnis, das in fast jedem Team auftaucht: Terraform, Ansible und Bicep werden oft als austauschbare Konkurrenten behandelt, dabei loesen sie unterschiedliche Probleme. Wer das nicht versteht, baut sich unnoetig komplizierte Pipelines oder verwendet das falsche Werkzeug fuer die falsche Aufgabe. Dieser Artikel klaert die Architekturunterschiede, zeigt einen Entscheidungsbaum fuer die Werkzeugwahl und geht auf die haerteste Frage im IaC-Alltag ein: das State-Handling.

Die drei Werkzeuge im Kern

Terraform: deklarative Provisionierung, cloud-agnostisch

Terraform (HashiCorp, seit 2024 unter Business Source License, mit dem Fork OpenTofu als freier Alternative) beschreibt den gewuenschten Endzustand deiner Infrastruktur in HCL (HashiCorp Configuration Language). Du definierst nicht die Schritte, sondern das Ziel - Terraform berechnet den Graphen der Abhaengigkeiten selbst und bringt die reale Welt in Uebereinstimmung mit deinem Code.

terraform {
  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "~> 3.90"
    }
  }
  backend "azurerm" {
    resource_group_name  = "rg-tfstate-prod"
    storage_account_name = "sttfstateprodch01"
    container_name       = "tfstate"
    key                  = "netzwerk.tfstate"
  }
}

provider "azurerm" {
  features {}
}

resource "azurerm_resource_group" "rg" {
  name     = "rg-filialen-zh"
  location = "switzerlandnorth"
}

resource "azurerm_virtual_network" "vnet" {
  name                = "vnet-zh-prod"
  address_space       = ["10.20.0.0/16"]
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name
}

Terraform kann nicht nur Azure, sondern ueber Provider auch AWS, GCP, VMware vSphere, Proxmox VE, Cloudflare, sogar M365-Ressourcen ansprechen. Das ist der grosse Vorteil in hybriden KMU-Umgebungen, wo neben Azure oft noch On-Prem-Hyper-V oder ein Cloudflare-Account existiert.

Ansible: prozedurales Konfigurationsmanagement, agentless

Ansible (Red Hat) setzt eine Ebene tiefer an: Es geht nicht darum, eine VM zu erschaffen, sondern eine bestehende Maschine in einen bestimmten Zustand zu bringen - Pakete installieren, Dienste konfigurieren, Benutzer anlegen. Ansible braucht keinen Agenten auf dem Zielsystem, sondern verbindet sich per SSH (Linux) oder WinRM (Windows) und fuehrt Module aus.

# playbook-webserver.yml
- name: IIS und Basis-Haertung auf Windows-Servern
  hosts: windows_webserver
  gather_facts: true
  tasks:
    - name: IIS-Rolle installieren
      ansible.windows.win_feature:
        name: Web-Server
        state: present
        include_management_tools: true

    - name: Firewall-Regel fuer HTTPS oeffnen
      community.windows.win_firewall_rule:
        name: "HTTPS-eingehend"
        localport: 443
        action: allow
        direction: in
        protocol: tcp
        state: present

    - name: TLS 1.0 und 1.1 deaktivieren
      ansible.windows.win_regedit:
        path: HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.0\Server
        name: Enabled
        data: 0
        type: dword

Ansible fuehrt bei jedem Lauf die Tasks aus und prueft idempotent, ob der Zustand schon erreicht ist - es fuehrt aber kein persistentes State-File wie Terraform. Das ist ein entscheidender Architekturunterschied, dazu gleich mehr.

Bicep: Azure-natives DSL statt ARM-JSON

Bicep ist Microsofts Antwort auf die Frage “warum ist ARM-JSON so unleserlich?”. Es ist eine Domain Specific Language, die zu ARM-Templates transpiliert wird und direkt von Azure Resource Manager verstanden wird - ohne Umweg ueber einen Drittanbieter-State.

// main.bicep
param location string = resourceGroup().location
param vnetAddressSpace string = '10.30.0.0/16'

resource vnet 'Microsoft.Network/virtualNetworks@2023-11-01' = {
  name: 'vnet-filiale-be'
  location: location
  properties: {
    addressSpace: {
      addressPrefixes: [
        vnetAddressSpace
      ]
    }
    subnets: [
      {
        name: 'snet-clients'
        properties: {
          addressPrefix: '10.30.1.0/24'
        }
      }
    ]
  }
}

output vnetId string = vnet.id

Deployment per Azure CLI:

az deployment group create \
  --resource-group rg-filiale-be \
  --template-file main.bicep \
  --parameters vnetAddressSpace=10.30.0.0/16

Vergleichstabelle: die Architekturunterschiede

KriteriumTerraformAnsibleBicep
Paradigmadeklarativprozedural (Tasks in Reihenfolge)deklarativ
HaupteinsatzProvisionierung (Ressourcen erschaffen)Konfiguration (Zustand auf bestehenden Systemen)Provisionierung (nur Azure)
Multi-Cloudja, ueber Provider (Azure, AWS, GCP, VMware, …)ja, ueber Module/Collectionsnein, Azure-exklusiv
State-Dateija, zwingend (lokal oder Remote-Backend)nein, kein persistenter Stateindirekt via Deployment Stacks (Azure-verwaltet)
Agent noetigneinnein (SSH/WinRM)nein
SpracheHCLYAMLBicep-DSL (kompiliert zu ARM-JSON)
Lock-in-Risikomittel (HCL + Provider-Oekosystem, BSL-Lizenz seit v1.6)gering (YAML, Module leicht austauschbar)hoch (nur Azure)
LizenzmodellBusiness Source License (Fork: OpenTofu, MPL)GPLv3, Community + Red Hat Enterprisekostenlos, Teil von Azure
Typischer Skill-Level im KMUmittel-hoch (State-Konzept muss sitzen)niedrig-mittel (YAML ist zugaenglich)mittel (wenn Azure-Fokus schon da ist)
Rollback bei FehlerPlan/Apply mit State-Vergleichkein eingebautes Rollback, nur erneuter LaufDeployment-Historie in ARM, teilweise rueckrollbar

Entscheidungsbaum: Welches Werkzeug fuer welche Aufgabe

Praktischer Ablauf zur Werkzeugwahl:

  1. Betrifft die Aenderung die Existenz einer Ressource (VM erstellen/loeschen, Subnetz anlegen, Storage-Konto provisionieren)? Dann Provisionierungs-Tool: Terraform oder Bicep.
  2. Bewegst du dich ausschliesslich in Azure und willst kein Drittanbieter-Tool im Stack? Dann Bicep - geringere Einstiegshuerde, keine externe State-Verwaltung, direkte ARM-Integration, kostenlos ohne Lizenzfragen.
  3. Hast du (oder planst du) mehr als eine Plattform - Azure plus On-Prem-Hyper-V, Azure plus AWS, Azure plus Cloudflare-DNS, Azure plus VMware? Dann Terraform (oder den freien Fork OpenTofu), weil ein einziges Tool und eine einzige Pipeline fuer alle Plattformen reicht.
  4. Geht es um den Zustand INNERHALB einer laufenden Maschine (Software installieren, Konfigurationsdateien verteilen, Patches einspielen, Benutzer/Gruppen pflegen)? Dann Ansible - unabhaengig davon, ob die VM per Terraform oder Bicep erstellt wurde.
  5. Brauchst du Orchestrierung ueber viele bestehende Server hinweg (z. B. “installiere auf allen 40 Terminalservern das neue Sicherheitspatch in dieser Reihenfolge”)? Auch dann Ansible - das ist sein ureigenes Terrain.
Neue Ressource noetig? (VM, VNet, Storage, DNS-Zone)
├── Ja
│   ├── Nur Azure? ────────────► Bicep
│   └── Multi-Cloud/On-Prem? ──► Terraform (oder OpenTofu)
└── Nein, bestehende Maschine konfigurieren
    └── Pakete, Dienste, Files, Registry, Patches ──► Ansible

Hybrid-Ansaetze: die drei Werkzeuge zusammen nutzen

In der Praxis ist die Kombination der Normalfall, kein Kompromiss. Ein gaengiges Muster im KMU-Umfeld:

  1. Terraform oder Bicep erstellt die Azure-VM, das VNet, die NSG und den Storage Account.
  2. Terraform Provisioner (remote-exec oder besser: ein separater Schritt in der Pipeline) uebergibt die IP-Adresse der frisch erstellten VM an ein Ansible-Inventory.
  3. Ansible uebernimmt danach die komplette Serverkonfiguration - Rollen installieren, Haertung anwenden, Monitoring-Agent ausrollen.
resource "azurerm_linux_virtual_machine" "app" {
  name                = "vm-app01"
  # ... weitere Attribute gekuerzt ...

  provisioner "local-exec" {
    command = "echo '${self.public_ip_address} ansible_user=azureuser' >> ../ansible/inventory.ini"
  }
}

Alternative ohne Terraform-Provisioner (sauberer, weil Terraform nicht fuer Konfigurationslogik missbraucht wird): das dynamische Azure-Inventory-Plugin von Ansible nutzt die Azure-API direkt, um alle VMs mit einem bestimmten Tag automatisch einzulesen - ganz ohne manuelle Uebergabe.

# inventory.azure_rm.yml
plugin: azure.azcollection.azure_rm
include_vm_resource_groups:
  - rg-filialen-zh
auth_source: auto
keyed_groups:
  - prefix: tag
    key: tags.rolle

State-Handling im Detail: der groesste Stolperstein

Das State-Konzept ist der Punkt, an dem die meisten KMU-Teams beim Terraform-Einstieg stolpern. Terraform fuehrt eine JSON-Datei (terraform.tfstate), die den zuletzt bekannten Zustand jeder verwalteten Ressource inklusive interner IDs enthaelt. Ohne diese Datei weiss Terraform nicht, was es verwaltet - es kann Ressourcen nicht importieren, aendern oder loeschen, wenn der State verloren geht oder nicht synchron ist.

Die drei kritischen Risiken:

  • Lokaler State ohne Backend: Liegt terraform.tfstate nur auf der Workstation eines Admins und wird versehentlich geloescht oder nicht ins Git-Repo committet (was ohnehin falsch waere, weil State Secrets im Klartext enthalten kann), verliert das Team die Kontrolle ueber die Infrastruktur.
  • State Drift: Jemand aendert eine Ressource manuell im Azure-Portal (schnelle Notloesung am Freitagabend), ohne den Terraform-Code anzupassen. Beim naechsten terraform plan zeigt Terraform eine Abweichung - im schlimmsten Fall will es die manuelle Aenderung rueckgaengig machen und ueberschreibt die Notloesung ungefragt.
  • Concurrent State Lock: Zwei Admins fuehren gleichzeitig terraform apply aus. Ohne State-Locking (z. B. via Azure Blob Lease im azurerm-Backend) korrumpiert das den State.
# State-Drift erkennen, ohne etwas zu aendern
terraform plan -refresh-only

# Manuell erstellte Ressource nachtraeglich unter Terraform-Kontrolle bringen
terraform import azurerm_storage_account.logs /subscriptions/<sub-id>/resourceGroups/rg-log/providers/Microsoft.Storage/storageAccounts/stlogprod01

# Remote State mit Locking pruefen
terraform state list
terraform state show azurerm_virtual_network.vnet

Ansible hat dieses Problem strukturell nicht, weil es keinen persistierten State fuehrt - es prueft bei jedem Lauf live den Ist-Zustand ueber Facts (ansible_facts). Der Nachteil: Ansible kann dir nicht sagen “diese Ressource wuerde geloescht”, weil es kein Vorher-Nachher-Modell kennt wie Terraform mit plan. Bicep-Deployment-Stacks liegen dazwischen: Der State existiert, wird aber vollstaendig von Azure verwaltet - du kannst ihn nicht exportieren oder in einem Fremdsystem inspizieren, was einerseits Betriebsrisiken reduziert (kein State-File, das verloren gehen kann), andererseits den Vendor-Lock-in verstaerkt.

Lock-in-Risiken realistisch einordnen

  • Bicep: voller Lock-in auf Azure. Ein Wechsel zu AWS oder GCP bedeutet Totalneuschrieb der Infrastruktur-Definitionen. Fuer ein KMU, das strategisch und dauerhaft auf Azure/M365 setzt, ist das oft ein akzeptables, sogar sinnvolles Risiko - man bekommt dafuer die beste Day-1-Unterstuetzung fuer neue Azure-Features.
  • Terraform: technisch cloud-agnostisch, aber der Provider-Code selbst (z. B. azurerm-Ressourcennamen und -Attribute) ist nicht 1:1 auf einen AWS-Provider uebertragbar - der Wechsel des Providers ist trotzdem Aufwand, nur eben nicht der Wechsel des Werkzeugs. Zusaetzlich: Seit der Lizenzumstellung auf die Business Source License (August 2023) ist Terraform selbst nicht mehr vollstaendig Open Source; wer das vermeiden will, evaluiert den Fork OpenTofu (Linux Foundation, MPL-2.0-Lizenz), der zu bestehendem Terraform-Code weitgehend kompatibel ist.
  • Ansible: das geringste Lock-in-Risiko der drei. YAML-Playbooks und Rollen sind gut lesbar, portabel, und Module lassen sich schrittweise ersetzen, ohne das ganze Automatisierungsmodell umzuwerfen.

Migration: von manueller Verwaltung zu IaC

Der haeufigste Fehler bei der Einfuehrung: alles auf einmal migrieren wollen. Bewaehrter, risikoarmer Ablauf fuer ein KMU mit gewachsener Infrastruktur:

  1. Inventar erstellen. Bevor du irgendetwas automatisierst, dokumentiere den Ist-Zustand (siehe auch IT-Dokumentation und Inventar). Ohne Inventar weisst du nicht, was du migrierst.
  2. Neuland zuerst automatisieren. Die naechste neue VM, das naechste neue VNet entsteht direkt per Terraform/Bicep - nicht mehr per Klick. So sammelt das Team Erfahrung, ohne Bestandssysteme zu gefaehrden.
  3. Bestehende Ressourcen schrittweise importieren. terraform import bzw. bei Bicep der Export bestehender ARM-Ressourcen (az group export) holt Alt-Ressourcen nachtraeglich unter IaC-Kontrolle. Wichtig: nach jedem Import sofort terraform plan laufen lassen und pruefen, dass keine ungewollte Aenderung vorgeschlagen wird.
  4. Konfiguration parallel mit Ansible dokumentieren. Fuehre ein ansible-playbook --check (Dry-Run) gegen bestehende Server aus, um den Ist-Zustand mit einem Ziel-Playbook abzugleichen, bevor du es scharf anwendest.
  5. Least-Privilege-Zugaenge fuer die Automatisierung einrichten. Der Service Principal (Azure) bzw. das Ansible-Vault-verschluesselte Credential darf nur, was es fuer seine Aufgabe braucht - keine Owner-Rolle “damit es sicher funktioniert”.
  6. Pipeline statt lokalem Apply. Sobald der erste Ordner sauber unter IaC laeuft, verschiebe terraform apply / az deployment / ansible-playbook in eine CI/CD-Pipeline (Azure DevOps, GitHub Actions) mit Plan-Review vor jedem Apply.
# vault-verschluesseltes Secret in Ansible anlegen
# ansible-vault create group_vars/prod/vault.yml
db_admin_password: "Sup3rGeheim!2026"
ansible-vault encrypt group_vars/prod/vault.yml
ansible-playbook site.yml --ask-vault-pass

Typische Fallstricke im KMU-Alltag

  • State-Backend vergessen. Terraform ohne Remote-Backend laeuft anfangs “irgendwie”, bis der Laptop des einzigen Admins den Geist aufgibt - dann ist die Infrastruktur faktisch nicht mehr verwaltbar, ausser durch komplettes Reimportieren.
  • Secrets im Klartext. Sowohl Terraform-State als auch Ansible-Playbooks werden schnell zur Ablage fuer Passwoerter, wenn niemand auf Ansible Vault oder ein Secret-Backend (Azure Key Vault, HashiCorp Vault) besteht.
  • Kein Plan-Review vor Apply. terraform apply -auto-approve in der Pipeline spart Klicks, aber auch die letzte Kontrollinstanz vor einer ungewollten Loeschung.
  • Ansible-Idempotenz missachtet. Ad-hoc-shell- oder command-Module statt spezialisierter Ansible-Module (ansible.windows.win_feature, ansible.builtin.package) fuehren dazu, dass ein Playbook bei jedem Lauf Aenderungen meldet, obwohl nichts zu tun waere - das Playbook wird unbrauchbar als Statusanzeige.
  • Bicep-Deployment ohne Deny-Settings. Ohne --deny-settings-mode kann jeder mit Portal-Zugriff eine per Bicep verwaltete Ressource manuell aendern, was beim naechsten Deployment zu unerwarteten Ueberschreibungen fuehrt.
  • Ein Terraform-State fuer alles. Ein einziger riesiger State fuer Netzwerk, VMs, Datenbanken und DNS bedeutet: jeder Plan dauert laenger, jeder Lock blockiert das ganze Team, und ein Fehler in einem Modul kann den State fuer alles gefaehrden. Besser: State pro logischer Einheit trennen (Netzwerk-State, App-State, Daten-State).
  • Ansible ueber WinRM ohne HTTPS. Windows-Hosts per WinRM nur mit HTTP statt HTTPS anzubinden, ist ein reales Sicherheitsrisiko im internen Netz - Zugangsdaten koennten im Klartext mitgelesen werden.

Sicherheitsaspekte kurz zusammengefasst

Automatisierungs-Credentials sind ein bevorzugtes Angriffsziel, weil sie oft weitreichende Rechte haben und selten rotiert werden. Fuer alle drei Werkzeuge gilt: Service Principals und SSH-Keys nach dem Least-Privilege-Prinzip vergeben, regelmaessig rotieren, und wo moeglich auf kurzlebige Zugangsdaten (OIDC-Federation zwischen CI/CD und Azure/AWS statt statischer Client Secrets) umstellen. Fuer den organisatorischen Rahmen dazu lohnt sich ein Blick in Passwort-Management und Zero-Trust-Architektur im KMU.

Weiterlernen

Vertiefend zum Thema: Terraform State Management und Drift, Ansible Playbooks, Inventory und Vault, Git fuer IT-Admins: Workflows und Branching, Azure-Grundlagen, Cloud-Migrationsstrategien und IaaS/PaaS/SaaS-Entscheidung.

Videos

YouTube
Was ist Terraform? // deutsch
YouTube
Terraform ganz einfach erklaert!

Kommentare

Frage, Verbesserungsvorschlag oder eigene Erfahrung zu diesem Artikel? Schreib einen Kommentar. Neue Beiträge erscheinen nach kurzer Moderation.

  • Lade Kommentare …
Kommentar schreiben