Policy-as-Code: OPA, Kyverno, Guardrails
Policies ohne Ticket-Factory: Validierung, Mutation, Audit.
Lernziele
Nach dieser Lektion kannst du erklären, wie Admission Control in Kubernetes funktioniert und wo Policy-Engines dort ansetzen. Du kannst Kyverno und OPA/Gatekeeper fundiert vergleichen, kennst den Unterschied zwischen Validierung, Mutation und Audit und weißt, wie man Policies einführt, ohne dass Entwickler die Plattform als Schikane erleben.
Das Problem: Regeln, die niemand durchsetzt, existieren nicht
Deine Organisation hat Standards: Container laufen nicht als root, jedes Deployment hat Resource Limits, Images kommen nur aus der internen Registry. Wo stehen diese Regeln? Im Wiki. Wer setzt sie durch? Reviewer — wenn sie Zeit haben und daran denken. Bei hundert Teams und tausenden Deployments pro Woche ist das Ergebnis vorhersehbar: Die Regeln gelten genau so lange, bis jemand unter Druck merged.
Die Alternative, jeden Change durch ein zentrales Security-Gate zu schleusen, bringt die Ticket-Factory zurück, die du mit Self-Service (Lektion 27) gerade abgeschafft hast. Der Ausweg: Regeln werden Code, der automatisch und für alle gleich durchgesetzt wird — versioniert, getestet und reviewbar wie jede andere Plattform-Komponente. In Kubernetes gibt es dafür einen idealen Ansatzpunkt.
Der Enforcement-Punkt: Admission Control
Jede Anfrage an die Kubernetes-API durchläuft nach Authentifizierung und Autorisierung die Admission-Phase. Dort kann der API-Server externe Webhooks aufrufen: Mutating Webhooks dürfen das Objekt verändern, Validating Webhooks dürfen es ablehnen — beide bevor irgendetwas in etcd gespeichert wird. Eine Policy-Engine ist im Kern ein Controller, der sich als solcher Webhook registriert.
Das macht Admission Control zum perfekten Enforcement-Punkt: Es ist egal, ob das Objekt von kubectl, einer CI-Pipeline oder Argo CD kommt — alles läuft durch dieselbe Tür. Eine abgelehnte Anfrage scheitert sofort mit einer Fehlermeldung, nicht erst im Audit drei Wochen später.
Drei Wirkungsweisen musst du auseinanderhalten:
- Validierung: Anfrage prüfen und ggf. ablehnen. „Deployment ohne Resource Limits? Abgelehnt, mit Begründung.”
- Mutation: Anfrage vor dem Speichern ergänzen. „Kein
securityContextgesetzt? Wir setzen sichere Defaults.” Mutation ist das freundlichere Werkzeug — die Plattform repariert, statt zu blockieren. - Audit/Background-Scan: Bestehende Ressourcen gegen Policies prüfen und Verstöße reporten, ohne einzugreifen. Unverzichtbar, weil Admission nur neue Anfragen sieht — was vor der Policy schon im Cluster war, findet nur der Scan.
Wichtig fürs Verständnis der Grenzen: Ein Admission Webhook ist eine synchrone Komponente im Schreibpfad der API. Ist er langsam, wird jedes Deployment langsam. Ist er down, entscheidet seine failurePolicy: Fail blockiert dann alle betroffenen Anfragen (sicher, aber die Plattform steht), Ignore lässt sie ungeprüft durch (verfügbar, aber die Tür ist offen).
Kyverno vs. OPA/Gatekeeper
Die zwei dominierenden Engines unterscheiden sich vor allem in der Policy-Sprache.
OPA/Gatekeeper baut auf Open Policy Agent auf, einer generischen Policy-Engine mit der Sprache Rego. Rego ist mächtig — beliebige Logik, wiederverwendbar auch außerhalb von Kubernetes (CI-Checks, Terraform-Pläne, Microservice-Autorisierung) — aber es ist eine eigene Sprache mit eigener Denkweise, die dein Team lernen und pflegen muss. Gatekeeper kapselt Rego in ConstraintTemplates und Constraints als CRDs.
Kyverno wurde spezifisch für Kubernetes gebaut: Policies sind selbst YAML-Ressourcen, deren Match- und Pattern-Syntax sich an Kubernetes-Manifesten orientiert. Wer Deployments schreiben kann, kann die meisten Kyverno-Policies lesen. Kyverno kann validieren, mutieren, Ressourcen generieren (z. B. automatisch eine NetworkPolicy in jeden neuen Namespace legen) und Image-Signaturen verifizieren.
Die ehrliche Entscheidungsheuristik: Brauchst du Policies nur für Kubernetes und soll das ganze Team sie pflegen können, ist Kyverno der pragmatische Default. Brauchst du eine Policy-Sprache über Kubernetes hinaus oder sehr komplexe Logik, rechtfertigt das den Rego-Invest. Erwähnenswert ist außerdem, dass Kubernetes mit ValidatingAdmissionPolicy inzwischen eingebaute, CEL-basierte Validierung mitbringt — für einfache Regeln ohne externe Engine, ohne Webhook im Pfad; Mutation, Generierung und Reporting bleiben aber Engine-Territorium.
Rollout ohne Aufstand: Audit zuerst
Der technisch einfachste Teil von Policy-as-Code ist die Policy. Der schwierige Teil ist die Einführung. Wer von heute auf morgen fünfzig Regeln auf Enforce schaltet, blockiert laufende Deployments und produziert einen organisationsweiten Aufstand — danach ist Policy-as-Code politisch verbrannt.
Das bewährte Vorgehen ist gestuft: Jede neue Policy startet im Audit-Modus und sammelt nur Verstöße. Mit diesen Reports gehst du zu den Teams — nicht als Vorwurf, sondern als Arbeitsliste mit Frist. Erst wenn die Verstöße abgebaut sind, schaltest du auf Enforce, idealerweise erst in Dev/Staging, dann in Produktion. Und jede ablehnende Policy braucht eine Fehlermeldung, die den Fix enthält: „Abgelehnt: runAsNonRoot fehlt. Siehe Golden-Path-Doku Abschnitt X” statt eines kryptischen Webhook-Errors. Die Qualität dieser Meldungen entscheidet, ob Policies als Hilfe oder als Schikane wahrgenommen werden.
Dazu gehört ein geregelter Exception-Prozess: Es wird legitime Ausnahmen geben (das Monitoring-DaemonSet braucht nun einmal hostPath). Ausnahmen gehören als Code ins Repo — explizit, begrenzt auf konkrete Workloads, mit Begründung und Ablaufdatum — nicht als stillschweigend deaktivierte Policy.
Praxis: eine Policy von Audit bis Enforce
In einem lokalen Cluster (kind reicht):
helm repo add kyverno https://kyverno.github.io/kyverno/
helm repo update
helm install kyverno kyverno/kyverno -n kyverno --create-namespace
Eine Validierungs-Policy, zunächst im Audit-Modus:
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-resource-limits
spec:
validationFailureAction: Audit
background: true
rules:
- name: check-limits
match:
any:
- resources:
kinds: ["Deployment"]
validate:
message: "CPU- und Memory-Limits sind Pflicht. Siehe Plattform-Doku: Resource Governance."
pattern:
spec:
template:
spec:
containers:
- resources:
limits:
memory: "?*"
cpu: "?*"
Teste beide Modi:
kubectl apply -f policy.yaml
kubectl create deployment test --image=nginx # geht durch (Audit)
kubectl get policyreport -A # Verstoß ist dokumentiert
# Auf Enforce schalten und erneut versuchen
kubectl patch clusterpolicy require-resource-limits --type merge \
-p '{"spec":{"validationFailureAction":"Enforce"}}'
kubectl create deployment test2 --image=nginx # wird abgelehnt, mit deiner Message
Lies die Ablehnungsmeldung bewusst: Genau dieser Text ist das, was hunderte Entwickler von deiner Plattform sehen werden.
Typische Stolperfallen
Big-Bang-Enforce: Policies ohne Audit-Phase scharfschalten bricht laufende Workloads und verbrennt Vertrauen. Audit → Kommunikation → Enforce, immer.
failurePolicy nicht durchdacht: Webhook down plus Fail heißt: niemand deployt mehr — auch nicht der Fix für den Webhook. Die Engine selbst (und kritische System-Namespaces) brauchen eine bewusste Ausnahme-Strategie.
Mutation-Überraschungen mit GitOps: Mutiert die Engine Felder, die auch im Git-Manifest stehen, meldet Argo CD permanenten Diff. Mutating Policies und GitOps-Diffing müssen aufeinander abgestimmt sein (z. B. via Diff-Ignores oder indem Mutation nur Felder setzt, die Git leer lässt).
Policies ohne Tests: Eine fehlerhafte Policy ist ein clusterweiter Incident. Policies gehören in CI getestet — mit Beispiel-Manifesten, die durchgehen und solchen, die abgelehnt werden müssen (Kyverno bringt dafür kyverno test als CLI mit).
Interview-Vorbereitung
Die Standardfrage „Wie setzt du Policies in Kubernetes durch?” beantwortest du entlang der Kette: Problem (Wiki-Regeln ohne Enforcement, Reviews skalieren nicht) → Mechanismus (Admission Webhooks: validieren und mutieren vor dem Persistieren) → Engine-Wahl mit Kriterium (Kyverno: YAML, Kubernetes-only; OPA: Rego, generisch) → Rollout (Audit zuerst, hilfreiche Fehlermeldungen, Exceptions als Code).
Typische Follow-ups:
- „Was passiert, wenn die Policy-Engine ausfällt?” —
failurePolicyentscheidet:Failblockiert API-Schreibzugriffe,Ignorelässt ungeprüft durch; deshalb HA-Deployment und Ausnahmen für System-Namespaces. - „Validierung oder Mutation — was bevorzugst du?” — Mutation für sichere Defaults (weniger Friction), Validierung für harte Grenzen; Mutation immer transparent dokumentieren.
- „Wie verhinderst du, dass Policies die Entwickler ausbremsen?” — Audit-Phase, Fix in der Fehlermeldung, Self-Service-Exceptions mit Ablaufdatum, Policies im Golden Path bereits eingepreist.
- „Reicht nicht Pod Security Admission?” — Für Pod-Security-Baselines ja, aber PSA kann weder mutieren noch eigene Organisationsregeln (Registry-Whitelist, Label-Pflichten) abbilden.
Zusammenfassung
Policy-as-Code macht Organisationsregeln zu versioniertem, automatisch durchgesetztem Code am Admission-Punkt der Kubernetes-API. Validierung lehnt ab, Mutation repariert, Audit deckt Bestandsverstöße auf. Kyverno punktet mit YAML-Policies für Kubernetes-zentrierte Teams, OPA/Gatekeeper mit Rego für komplexe oder plattformübergreifende Logik. Der Erfolg entscheidet sich im Rollout: Audit vor Enforce, Fehlermeldungen mit Fix, Exceptions als Code. Admission Webhooks sind dabei nur ein Spezialfall eines größeren Musters — Controller, die den Cluster beobachten und auf Ereignisse reagieren. Wie du solche Controller und eigene CRDs als Plattform-API baust, ist Thema der nächsten Lektion.