IaC und ITIL v4
Automatisierung und IT-Service-Management gelten oft als Gegensätze: Hier die schnelle Pipeline, dort das Change Advisory Board mit Wochenrhythmus. Richtig umgesetzt ergänzen sie sich. Die Pipeline liefert genau das, was ITIL verlangt – bewertete, genehmigte, dokumentierte und nachvollziehbare Änderungen –, nur automatisch, vollständig und ohne Medienbruch.
Zurück zur IaC-Übersicht · Grundlagen unter ITIL v4
Die Leitprinzipien in der IaC-Praxis
ITIL v4 formuliert sieben Leitprinzipien. Jedes hat eine direkte Entsprechung in Infrastructure as Code.
| Leitprinzip | Umsetzung mit IaC |
|---|---|
| Focus on value | Server sind Mittel zum Zweck; der Wert ist der Service, nicht die Maschine |
| Start where you are | Bestehende Ressourcen per terraform import übernehmen statt neu bauen |
| Progress iteratively with feedback | Kleine Merge Requests, jeder mit Plan und Prüfung |
| Collaborate and promote visibility | Änderungen sind als Code für alle lesbar, Reviews finden im MR statt |
| Think and work holistically | Netz, Compute, Image und Konfiguration in einer durchgängigen Kette |
| Keep it simple and practical | Ein Weg für alle Änderungen: die Pipeline |
| Optimize and automate | Erst den Ablauf standardisieren, dann automatisieren |
Welche ITIL-Praktiken betroffen sind
| Praxis | Pet-Welt (manuell) | Cattle-Welt (IaC) |
|---|---|---|
| Change Enablement | Ticket, CAB-Termin, Admin setzt um | Merge Request, automatische Bewertung, Pipeline setzt um |
| Release Management | Wartungsfenster, Installationsanleitung | Versionierte Image-Version in der Compute Gallery |
| Deployment Management | Handarbeit auf jedem Server | Rolling Upgrade des Scale Sets |
| Service Configuration Management | CMDB wird von Hand gepflegt und veraltet | State, Tags und Resource Graph liefern den Ist-Zustand |
| Incident Management | Admin loggt sich ein, repariert | Health Probe erkennt, Automatic Repair ersetzt |
| Problem Management | Ursachen gehen im Einzelfall unter | Häufung automatischer Repairs zeigt Muster |
| Monitoring and Event Management | Überwachung einzelner Hosts | Überwachung des Service und der Soll-Ist-Abweichung (Drift) |
| Information Security Management | Wer hat wann was geändert? Oft unklar | Git-Historie, Pipeline-Protokoll, Anmeldeprotokolle der Identitäten |
Change Enablement
Change-Typen
ITIL v4 unterscheidet drei Arten von Changes. Die Pipeline bildet alle drei ab – aber auf einem technischen Weg.
| Change-Typ | ITIL-Definition | In der Pipeline |
|---|---|---|
| Standard | Vorab bewertet, geringes Risiko, festgelegtes Verfahren | Plan enthält nur unkritische Änderungen → MR-Freigabe genügt |
| Normal | Einzeln zu bewerten und zu genehmigen | Plan enthält Löschungen, Ersetzungen oder kritische Ressourcen → zusätzliche Change-Genehmigung |
| Emergency | Muss schnellstmöglich umgesetzt werden | Beschleunigter MR mit nachgelagerter Prüfung (siehe unten) |
Der entscheidende Schritt: Nicht der Mensch klassifiziert den Change, sondern der Plan. terraform plan weiß exakt, welche Ressourcen angelegt, geändert, ersetzt oder gelöscht werden. Daraus lässt sich der Change-Typ regelbasiert ableiten.
Was als Standard Change gilt
Ein Change ist ein Standard Change, wenn alle folgenden Bedingungen erfüllt sind:
- Alle Prüfungen der Pipeline sind grün (Format, Validierung, Lint, Checkov).
- Der Plan löscht oder ersetzt keine Ressource.
- Der Plan ändert keine Ressource eines als kritisch eingestuften Typs (Netz, Firewall, Gallery, Ressourcengruppen).
- Die Änderung wurde im Merge Request von einer zweiten Person freigegeben.
Typische Standard Changes im Lab sind das Skalieren des Scale Sets und das Ausrollen einer neuen Image-Version – beides In-Place-Updates, die Azure batchweise und mit Health Probe absichert.
Diese Regeln einmal formal zu genehmigen, ist der eigentliche Change-Management-Akt. Danach wendet die Pipeline sie bei jedem Lauf gleich an.
Automatische Klassifizierung
Das Skript wertet den Plan im JSON-Format aus, bestimmt den Change-Typ und erzeugt einen Change-Datensatz als Markdown.
- classify_change.py
#!/usr/bin/env python3 """Klassifiziert einen Terraform-Plan als ITIL-Change-Typ. Aufruf: classify_change.py <plan.json> <stack> Erzeugt: change-record.md und change.env (für GitLab-dotenv-Reports) """ import datetime import json import os import sys # Änderungen an diesen Typen sind immer ein Normal Change CRITICAL_TYPES = { "azurerm_resource_group", "azurerm_virtual_network", "azurerm_subnet", "azurerm_network_security_group", "azurerm_subnet_network_security_group_association", "azurerm_shared_image_gallery", "azurerm_shared_image", } def classify(plan): changes, reasons = [], [] for rc in plan.get("resource_changes", []): actions = rc["change"]["actions"] if actions in (["no-op"], ["read"]): continue changes.append((rc["address"], rc["type"], actions)) if "delete" in actions: art = "wird ersetzt" if "create" in actions else "wird gelöscht" reasons.append(f"{rc['address']} {art}") elif rc["type"] in CRITICAL_TYPES: reasons.append(f"{rc['address']}: kritischer Ressourcentyp") if not changes: return "none", changes, reasons return ("normal" if reasons else "standard"), changes, reasons def main(): plan_file, stack = sys.argv[1], sys.argv[2] with open(plan_file, encoding="utf-8") as fh: plan = json.load(fh) change_type, changes, reasons = classify(plan) lines = [ f"# Change-Datensatz – Schicht {stack}", "", f"- Zeitpunkt: {datetime.datetime.now(datetime.timezone.utc):%Y-%m-%d %H:%M} UTC", f"- Change-Typ: **{change_type}**", f"- Commit: {os.environ.get('CI_COMMIT_SHA', 'lokal')}", f"- Merge Request: {os.environ.get('CI_MERGE_REQUEST_IID', '-')}", f"- Ausgelöst von: {os.environ.get('GITLAB_USER_LOGIN', 'lokal')}", "", "## Geplante Änderungen", ] lines += [f"- `{addr}`: {'/'.join(act)}" for addr, _, act in changes] or ["- keine"] if reasons: lines += ["", "## Gründe für Normal Change"] + [f"- {r}" for r in reasons] with open("change-record.md", "w", encoding="utf-8") as fh: fh.write("\n".join(lines) + "\n") with open("change.env", "w", encoding="utf-8") as fh: fh.write(f"CHANGE_TYPE_{stack.upper()}={change_type}\n") print(f"[{stack}] Change-Typ: {change_type}") for r in reasons: print(f" - {r}") if __name__ == "__main__": main()
Das Skript liegt als ci/classify_change.py im Repository. Die Liste CRITICAL_TYPES ist selbst eine Change-Management-Entscheidung und deshalb über CODEOWNERS geschützt.
Einbindung in die Pipeline
Ergänzungen zur IaC-Pipeline:
- .gitlab-ci.yml
stages: [validate, security, image, plan, change, apply, drift] .plan: # ... bisheriger Inhalt, am Ende des script-Blocks ergänzen: script: - *tf_init - terraform plan -lock=false -out=tfplan - terraform show -no-color tfplan > plan.txt - terraform show -json tfplan > plan-full.json - python3 ../ci/classify_change.py plan-full.json "$STACK" # ... jq-Zusammenfassung für das MR-Widget wie bisher artifacts: paths: ["$STACK/tfplan", "$STACK/plan.txt", "$STACK/change-record.md"] reports: terraform: "$STACK/plan.json" dotenv: "$STACK/change.env" expire_in: 1 week change:gate: stage: change needs: ["plan:base", "plan:workload"] script: - echo "Change-Typ base=$CHANGE_TYPE_BASE workload=$CHANGE_TYPE_WORKLOAD" - | if [ "$CHANGE_TYPE_BASE" = "normal" ] || [ "$CHANGE_TYPE_WORKLOAD" = "normal" ]; then case ",$CI_MERGE_REQUEST_LABELS," in *,change-approved,*) echo "Normal Change: Genehmigung liegt vor." ;; *) echo "Normal Change: Label 'change-approved' fehlt – Genehmigung erforderlich." exit 1 ;; esac else echo "Standard Change: MR-Freigabe genügt." fi rules: - if: $CI_PIPELINE_SOURCE == "merge_request_event"
Zusammen mit der Projekteinstellung „Pipelines must succeed“ lässt sich ein Normal Change nicht mergen, bevor die Genehmigung vorliegt. Nach dem Setzen des Labels muss die MR-Pipeline neu gestartet werden.
Grenzen der Lab-Lösung: Ein Label kann jeder mit Reporter-Rechten setzen. Im Produktivbetrieb prüft der Gate-Job stattdessen per API im ITSM-Werkzeug (z. B. ServiceNow oder Jira Service Management), ob der im MR referenzierte Change genehmigt ist. Das Prinzip bleibt gleich: Die Pipeline fragt nach, der Mensch genehmigt im dafür vorgesehenen System.
Emergency Changes
Auch im Notfall gilt: Kein Handeingriff im Azure-Portal. Jeder manuelle Eingriff erzeugt Drift, die später niemand mehr erklären kann.
- Hotfix-Branch, Merge Request mit Kennzeichnung
emergencyim Titel - Verkürzte Freigabe durch eine vorab benannte Person der Rufbereitschaft
- Pipeline läuft vollständig durch – Validierung und Plan dauern Minuten, nicht Stunden
- Nachträgliche Bewertung im nächsten regulären Change-Review
Für den Fall, dass die Pipeline selbst ausfällt, gibt es einen Break-Glass-Zugang: ein Notfallkonto mit Schreibrechten, dessen Nutzung alarmiert wird. Danach wird die manuelle Änderung per Merge Request in den Code übernommen; der nächtliche Drift-Check stellt sicher, dass das nicht vergessen wird.
Service Configuration Management
Was ist ein Configuration Item?
In der Pet-Welt ist jeder Server ein CI mit eigenem Lebenslauf. In der Cattle-Welt verschiebt sich die Granularität: Einzelne Instanzen leben Stunden oder Tage und sind austauschbar. Sie als CI zu pflegen, erzeugt nur Rauschen.
| Pet-Welt: CI | Cattle-Welt: CI |
|---|---|
Server zeus | Service „Webshop“, umgesetzt durch Scale Set vmss-iaclab-web |
| Installierte Softwarestände | Image-Version 1.1.0 (enthält den vollständigen Softwarestand) |
| Konfigurationsdateien | Commit im Repository |
| Handgepflegte Abhängigkeiten | Abhängigkeiten aus Terraform-Code und Resource Graph |
Tags als CI-Attribute
Damit Azure-Ressourcen einem Service zugeordnet werden können, bekommen alle Ressourcen einheitliche Tags. Das Schema wird in locals.tags beider Schichten ergänzt:
locals {
tags = {
service = "iac-lab-web" # Service-Zuordnung in der CMDB
owner = "plattform-team" # verantwortliche Organisationseinheit
criticality = "low" # Grundlage für Priorisierung von Incidents
managed_by = "terraform"
repo = "gitlab.com/<gruppe>/iac-lab-azure"
layer = "workload"
}
}
Eine Azure Policy prüft, ob die Pflicht-Tags vorhanden sind. Die Policy startet im Prüfmodus (enforce = false), damit sie nichts blockiert, bis alle Ressourcen konform sind:
data "azurerm_policy_definition" "require_tag" {
display_name = "Require a tag on resources"
}
resource "azurerm_resource_group_policy_assignment" "require_service_tag" {
name = "require-tag-service"
resource_group_id = azurerm_resource_group.web.id
policy_definition_id = data.azurerm_policy_definition.require_tag.id
enforce = false # erst prüfen, später erzwingen
parameters = jsonencode({
tagName = { value = "service" }
})
}
Damit ist auch die Regel selbst Code, versioniert und über die Pipeline geändert – Policy as Code.
Ist-Zustand für die CMDB
Der Azure Resource Graph liefert den aktuellen Bestand aller Ressourcen eines Services in Sekunden:
az graph query -q " Resources | where tags.service == 'iac-lab-web' | project name, type, location, resourceGroup, owner=tostring(tags.owner), criticality=tostring(tags.criticality) " --output table
Als nächtlicher Pipeline-Job mit –output json lässt sich das Ergebnis in die CMDB importieren. Drei Quellen ergänzen sich:
| Quelle | Liefert |
|---|---|
| Terraform-Code | Soll-Zustand und Absicht (was sein soll) |
| Terraform-State | Was Terraform verwaltet und zuletzt gesehen hat |
| Resource Graph | Was in Azure tatsächlich existiert (was ist) |
Ressourcen, die im Resource Graph auftauchen, aber keinen Tag managed_by = terraform tragen, sind Kandidaten für Schatten-IT oder vergessene Handarbeit.
Incident und Problem Management
- Automatische Incident-Behebung: Eine Instanz, deren Health Probe fehlschlägt, wird vom Scale Set ersetzt. Für den Service ist der Incident behoben, bevor ein Mensch ihn bemerkt.
- Aber: Ein automatisch behobener Incident ist trotzdem ein Signal. Das Aktivitätsprotokoll des Scale Sets zeigt jede Reparatur; eine Warnung bei gehäuften Reparaturen gehört ins Monitoring.
- Problem Management: Wenn Instanzen regelmäßig ausgetauscht werden, liegt die Ursache im Image oder in der Konfiguration. Die Lösung ist eine neue Image-Version – also wieder ein Change über die Pipeline.
- Drift als Incident: Eine Drift-Meldung aus dem nächtlichen Check bedeutet, dass jemand an der Pipeline vorbei geändert hat. Das ist ein Prozessverstoß, kein technischer Fehler.
Nachvollziehbarkeit und Audit
Für jede Änderung lässt sich lückenlos beantworten, was, wann, von wem, warum und mit wessen Genehmigung geändert wurde:
| Frage | Nachweis |
|---|---|
| Was? | Diff im Merge Request, plan.txt, change-record.md |
| Wann? | Zeitstempel von Merge und Apply-Job |
| Wer? | Autor des MR, Auslöser des Apply-Jobs |
| Warum? | Beschreibung des MR, verknüpftes Ticket |
| Genehmigt von? | MR-Freigaben, Change-Genehmigung |
| Wie in Azure? | Aktivitätsprotokoll, Anmeldeprotokolle der Workload-Identität |
| Vorheriger Stand? | Git-Historie, versionierter Terraform-State |
In regulierten Umfeldern, etwa im Finanzsektor unter DORA, verlangen die Aufsichtsvorgaben ein dokumentiertes, geprüftes und genehmigtes IKT-Änderungsmanagement. Eine Pipeline erfüllt diese Anforderungen strukturell besser als ein manueller Prozess, weil sie keinen Schritt auslassen kann. Wichtig sind passende Aufbewahrungsfristen für Pipeline-Protokolle und Artefakte.
Kennzahlen für kontinuierliche Verbesserung
Die vier Kennzahlen aus der DevOps-Forschung (DORA – DevOps Research and Assessment, nicht zu verwechseln mit der EU-Verordnung DORA) passen direkt zur ITIL-Praxis Continual Improvement:
| Kennzahl | Frage | Quelle in der Pipeline |
|---|---|---|
| Deployment Frequency | Wie oft wird erfolgreich ausgerollt? | Anzahl erfolgreicher Apply-Jobs |
| Lead Time for Changes | Wie lange vom Commit bis zur Produktion? | Zeit zwischen erstem Commit und Apply |
| Change Failure Rate | Welcher Anteil der Changes führt zu Störungen? | Rollbacks, Hotfixes je Apply |
| Time to Restore Service | Wie schnell ist der Service nach einer Störung wieder da? | Dauer bis zum erfolgreichen Rollback/Repair |
Ergänzend aus ITIL-Sicht: Anteil Standard Changes an allen Changes (Ziel: steigend) und Anzahl Drift-Meldungen (Ziel: null).
Weiterführend
- ITIL v4 – Grundlagen
- IaC-Pipeline – die technische Umsetzung
- IaC-Lab – die verwaltete Infrastruktur
- Lebenszyklus – Rolling Updates, Rollback, Decommissioning
