Zurück zum Blog
Security
FortgeschrittenFürPlatform EngineersSecurity EngineersSRE
9 min

OPA vs. Kyverno 2026: Kubernetes liefert Policies jetzt selbst

Kubernetes setzt Policies jetzt selbst durch: ValidatingAdmissionPolicy ist seit 1.30 stabil, MutatingAdmissionPolicy seit 1.36. Die eigentliche Frage lautet also nicht mehr OPA oder Kyverno — sondern wofür du überhaupt noch einen Controller brauchst.

opa vs kyvernokubernetes policy enginevalidatingadmissionpolicypolicy as codegatekeeper
Inhalt

Jeder Vergleich von OPA und Kyverno, den du findest, wurde für eine Welt geschrieben, die es nicht mehr gibt.

Die alte Erzählung ging so: Rego ist mächtig, aber du musst es lernen; Kyverno ist YAML und deshalb zugänglich; such dir dein Gift aus. Diese Erzählung ist gleich zweimal gestorben. Kubernetes hat angefangen, Policies selbst durchzusetzen, und Kyverno hat aufgehört, eine reine YAML-Engine zu sein.

Bevor man also zwischen zwei Controllern wählt, lautet die nützlichere Frage: Brauchst du überhaupt einen Controller?

Kubernetes erzwingt Validierung und Mutation inzwischen im API-Server, was die Rolle eines externen Policy-Controllers verändert.

Was sich geändert hat: Kubernetes hat seine eigene Policy-Engine bekommen

Zwei Funktionen haben den Boden verschoben.

ValidatingAdmissionPolicy ist seit Kubernetes 1.30 stabil. Sie ist die deklarative, im Prozess laufende Alternative zu validierenden Admission-Webhooks und nutzt die Common Expression Language.

MutatingAdmissionPolicy ist seit Kubernetes 1.36 stabil und standardmäßig aktiv. Dieselbe Idee, nur zum Verändern statt zum Ablehnen. Der Weg dorthin war lang — Alpha in 1.30, Beta in 1.34, GA in 1.36 — auf älteren Clustern also erst prüfen, bevor du damit planst.

Eine Policy besteht aus drei Teilen: der Policy selbst, einer optionalen Parameter-Ressource und einem Binding, das beides verknüpft und den Geltungsbereich festlegt. Mehr ist es nicht:

apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:
name: "demo-policy.example.com"
spec:
failurePolicy: Fail
matchConstraints:
resourceRules:
- apiGroups: ["apps"]
apiVersions: ["v1"]
operations: ["CREATE", "UPDATE"]
resources: ["deployments"]
validations:
- expression: "object.spec.replicas <= 5"

Kein Controller. Kein Webhook. Kein TLS-Zertifikat zum Rotieren. Kein zusätzlicher Netzwerk-Hop bei jedem API-Aufruf.

Der letzte Punkt wiegt schwerer, als er klingt — dazu später mehr.

Die eingebauten Policies können auch mehr, als das Spielbeispiel vermuten lässt. Es gibt variables zum Zusammensetzen von Ausdrücken, matchConditions für feingranulares Filtern, messageExpression für brauchbare Ablehnungsmeldungen, auditAnnotations und Type Checking — der API-Server prüft deinen Ausdruck gegen das Schema und meldet Fehler in status.typeChecking, bevor sie dich treffen:

status:
typeChecking:
expressionWarnings:
- fieldRef: spec.validations[0].expression
warning: |-
apps/v1, Kind=Deployment: ERROR: <input>:1:7: undefined field 'replicas'

Und validationActions erlaubt es, eine Policy als Deny, Warn oder Audit laufen zu lassen — du kannst eine Regel also erst im Beobachtungsmodus ausrollen. Das ist dieselbe Disziplin, für die ich bei Runtime-Erkennung und Alarmflut argumentiert habe: erst schauen, dann erzwingen.

Das Zweite, was sich geändert hat: Kyverno spricht CEL

Das Argument „YAML gegen Rego“ unterstellte, Kyverno sei eine YAML-und-JMESPath-Engine. Das stimmt nicht mehr.

Kyverno hat CEL übernommen, und das Projekt sagt auch klar warum — Kubernetes hat stark in CEL investiert, deshalb senke dessen Nutzung „die kognitive Last für Plattformteams, weil es eine Sache weniger zu lernen gibt“.

Die praktische Folge: Ein CEL-Ausdruck in einer eingebauten ValidatingAdmissionPolicy und einer in einer Kyverno-ValidatingPolicy sind nahe Verwandte. Die Sprache ist nicht länger die Achse, die diese Werkzeuge trennt.

Damit kam auch ein kompletter API-Umbau. Die aktuellen Policy-Typen:

Das Zweite, was sich geändert hat: Kyverno spricht CEL
Typ Aufgabe Status
ValidatingPolicy Ressourcen oder JSON-Payloads validieren Stabil (v1.18)
MutatingPolicy Neue oder bestehende Ressourcen verändern Stabil (v1.18)
GeneratingPolicy Ressourcen aus Auslösern erzeugen oder klonen Stabil (v1.18)
DeletingPolicy Passende Ressourcen zeitgesteuert löschen Stabil (v1.18)
ImageValidatingPolicy Image-Signaturen und Attestierungen prüfen Stabil (v1.18)
ClusterPolicy Alter Allzweck-Typ Deprecated (v1.18)
CleanupPolicy Altes zeitgesteuertes Löschen Deprecated (v1.18)

Wer Kyverno heute betreibt, sollte die unteren Zeilen nicht als Randnotiz lesen — das ist eine Migration mit Termin. Dazu gleich mehr.

Kyverno hat außerdem am 16. März 2026 den CNCF-Graduated-Status erreicht, nach Aufnahme im November 2020 und Incubating seit Juli 2022.

Wofür brauchst du dann noch einen Controller?

Hier die ehrliche Liste. Eingebaute Policies erledigen Validierung und Mutation zur Admission-Zeit. Sie erledigen nicht:

Wofür brauchst du dann noch einen Controller?
Fähigkeit Eingebaut Gatekeeper Kyverno
Bei Admission validieren ja ja ja
Bei Admission mutieren ja (ab 1.36) ja ja
Ressourcen erzeugen / klonen nein nein ja
Image-Signaturen prüfen nein nein ja
Bestehende Objekte auditieren nein ja ja
Policy-Reports nein ja ja
Zeitgesteuertes Aufräumen nein nein ja
Policies außerhalb von Kubernetes nein über OPA ja (JSON, Terraform)

Fähigkeitsmatrix: eingebaute Policies decken Admission ab, aber Generierung, Image-Prüfung und Reporting brauchen weiterhin einen Controller.

Drei dieser Zeilen sind der übliche Grund, warum Teams doch etwas installieren.

Generierung. Wird ein Namespace angelegt, willst du eine Default-NetworkPolicy, ein kopiertes Pull-Secret, eine ResourceQuota, eine LimitRange. Admission Control kann nur ablehnen oder bearbeiten, was jemand eingereicht hat — nicht erzeugen, was jemand vergessen hat. Kyvernos GeneratingPolicy kann das und hält die erzeugte Kopie mit ihrer Quelle synchron.

Image-Prüfung. Zu prüfen, ob ein Image signiert ist und die erwarteten Attestierungen trägt, ist Lieferketten-Durchsetzung und braucht zur Admission-Zeit Zugriff auf Registry und Transparenz-Log. Das ist das Feld von ImageValidatingPolicy. Es ist auch die fehlende Durchsetzungshälfte meines Arguments, warum eine SBOM allein das nächste Log4j nicht stoppt — eine Attestierung, die niemand prüft, ist ein Dokument, keine Kontrolle.

Hintergrund-Scans. Admission sieht nur neue und geänderte Objekte. Alles, was schon lief, als du die Policy geschrieben hast, bleibt unsichtbar. Gatekeepers Audit und Kyvernos Reports beantworten beide „Was verstößt gerade dagegen?“ — die erste Frage, die bei jeder Einführung gestellt wird.

Wo OPA tatsächlich gewinnt

Wer nur Kubernetes-Vergleiche liest, hält OPA für die umständlichere Option: Rego schreiben, Gatekeeper betreiben, ConstraintTemplate und Constraint paarweise pflegen.

apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
name: k8srequiredlabels
spec:
crd:
spec:
names:
kind: K8sRequiredLabels
validation:
openAPIV3Schema:
type: object
properties:
labels:
type: array
items:
type: string
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package k8srequiredlabels
violation[{"msg": msg}] {
required := input.parameters.labels[_]
not input.review.object.metadata.labels[required]
msg := sprintf("missing required label: %v", [required])
}

Das ist mehr Zeremonie als ein CEL-Einzeiler. Der Gewinn liegt nicht im Cluster.

OPA ist kein Kubernetes-Werkzeug. Es ist eine universelle Policy-Engine — CNCF graduiert — und Rego ist eine Sprache, die du auf API-Autorisierung in Microservices, Terraform-Pläne in der CI, Datenfilterung und Admission Control richten kannst. Wenn deine Organisation OPA ohnehin für Service-Autorisierung betreibt, ist Cluster-Policy in derselben Engine echte Konsolidierung und kein zusätzliches Werkzeug.

Gatekeeper ergänzt die Kubernetes-nativen Teile: eine parametrisierte Policy-Bibliothek, Constraints als CRDs, Mutation über Assign, AssignMetadata, ModifySet und AssignImage, Audit und External Data.

Der Handel ist in beide Richtungen real. Eine Sprache überall — zum Preis einer Sprache, die am ersten Tag niemand kann.

Wie ich tatsächlich entscheiden würde

Vier Fragen, in dieser Reihenfolge.

1. Deckt die eingebaute Policy die Regel ab? Wenn es „X ablehnen“ oder „Y als Standard setzen“ heißt, schreib eine ValidatingAdmissionPolicy oder MutatingAdmissionPolicy und hör auf. Du hast null Betriebsfläche hinzugefügt. Das sollte der Standard sein für Pflicht-Labels, verbotene Capabilities, Registry-Allowlists und Replica-Grenzen.

2. Soll der Cluster Dinge erzeugen statt nur beurteilen? Dann brauchst du Kyverno. Für Generierung gibt es weder ein eingebautes noch ein Gatekeeper-Äquivalent.

3. Brauchst du Lieferketten-Prüfung bei der Admission? Kyvernos ImageValidatingPolicy oder ein spezialisiertes Werkzeug. Weder die eingebauten Policies noch Gatekeeper können das.

4. Müssen Policies außerhalb von Kubernetes gelten? Dann OPA — und akzeptiere Rego als Preis für eine Engine über Cluster, CI und Services hinweg.

Die meisten Teams landen bei: eingebaute Policies für die einfache Mehrheit, Kyverno für die Handvoll Regeln, die Generierung, Image-Prüfung und Reports brauchen. Diese Kombination ist langweilig, und sie funktioniert.

Ein Entscheidungspfad: mit eingebauten Policies beginnen, einen Controller nur für die fehlenden Fähigkeiten ergänzen.

Die Betriebsfalle, die selten zuerst genannt wird

Ein Webhook ist kein Feature, das man einschaltet. Er ist Infrastruktur im Anfragepfad.

Setz failurePolicy: Fail, und ein nicht erreichbarer Policy-Controller blockiert jede Operation, auf die er passt. Der klassische Ausfall sieht so aus: Der Controller ist weg, die Regel passt auf Pod-Erstellung, und jetzt kannst du keine Pods mehr planen — genau in dem Vorfall, aus dem du dich herausskalieren wolltest.

Setz stattdessen Ignore, und du hast die Durchsetzung still abgeschaltet. Deine Policies existieren weiter, sehen in Git grün aus und erzwingen nichts.

Es gibt keine dritte Option, die diese Wahl vermeidet. Was hilft:

  • Namespaces ausschließen, die nie blockiert werden dürfen — mindestens kube-system und der Namespace des Policy-Controllers selbst. Ein Controller, dessen Webhook seine eigene Neuerstellung blockieren kann, beschert dir einen ernsthaft schlechten Nachmittag.
  • matchConstraints eng fassen. Eine Policy auf resources: ["*"] setzt deinen Controller in den Pfad von allem, inklusive Leases und Events. Die Doku zeigt genau dieses Muster mit matchConditions, die Leases, Node-Nutzer und RBAC-Anfragen ausnehmen.
  • Neue Regeln zuerst als Warn oder Audit laufen lassen und dann bewusst auf Deny heben.
  • Mutation läuft vor Validierung, und Mutationen können erneute Auswertung auslösen. reinvocationPolicy: IfNeeded existiert, weil eine Mutation die Annahmen einer anderen ungültig machen kann.

Das ist das stärkste praktische Argument für die eingebauten Policies: Was im API-Server ausgewertet wird, kann nicht getrennt vom API-Server ausfallen. Eine ganze Ausfallklasse verschwindet.

Webhook-Fehlerfälle: Fail blockiert den Cluster, Ignore schaltet die Durchsetzung still ab, eingebaute Policies umgehen die Wahl.

Die Migration, von der du vielleicht nichts weißt

Wer Kyverno vor 2025 eingeführt hat, betreibt seine Policies fast sicher als ClusterPolicy. Das Projekt hat den Fahrplan veröffentlicht:

Die Migration, von der du vielleicht nichts weißt
Version Datum Status
v1.17 Jan 2026 Als deprecated markiert
v1.18 Apr 2026 Nur kritische Fixes
v1.19 Jul 2026 Nur kritische Fixes
v1.20 Okt 2026 Entfernung geplant

Die CEL-basierten Typen kamen in v1.14 (April 2025) und v1.15 (Juli 2025) und sind seit v1.18 stabil, veröffentlicht am 29. April 2026. Es ist also keine Überraschung — aber echte Arbeit, die auf eine Roadmap gehört und nicht in ein Notfall-Upgrade.

Ein Detail, das man vor jeder Planung prüfen sollte: Kyvernos Support-Matrix hinkt Kubernetes hinterher. v1.18 nennt als unterstützte Kubernetes-Versionen v1.33 bis v1.35 — also nicht 1.36, das Release, in dem MutatingAdmissionPolicy GA wurde. Andere Versionen „können funktionieren, sind aber nicht getestet“. Hinzu kommen rund drei Monate Patch-Support pro Minor-Release; die Upgrade-Taktung ist damit schneller, als viele Teams annehmen.

Der Vorteil: Die Migration bringt dich zu CEL, derselben Sprache wie in den eingebauten Policies. Bei manchem, was du migrierst, wirst du feststellen, dass du es ersatzlos löschen und nativ ausdrücken kannst.

Wie „gut“ aussieht

  • Einfache Admission-Regeln liegen in eingebauten ValidatingAdmissionPolicy-Objekten, ganz ohne Controller
  • Jede neue Regel startet als Warn oder Audit und wird bewusst hochgestuft
  • Genau ein Policy-Controller ist installiert, und zwar für benannte Fähigkeiten, die du begründen kannst — Generierung, Image-Prüfung, Reports
  • kube-system und der Namespace des Controllers sind von blockierenden Webhooks ausgenommen
  • Jemand kann „Was verstößt gerade gegen diese Policy?“ beantworten, ohne ein Skript zu schreiben
  • Policies liegen in Git und laufen durch denselben Review-Pfad wie alles andere — das Platform-Engineering-Argument, angewandt auf Leitplanken

Das Fazit

Der interessante Vergleich lautet 2026 nicht OPA gegen Kyverno. Er lautet eingebaute Policies gegen alles andere.

Kubernetes validiert und mutiert inzwischen nativ, im Prozess, in CEL, mit Type Checking und Beobachtungsmodus — und das deckt den Großteil dessen ab, was die meisten Cluster erzwingen, ohne einen Webhook in den Anfragepfad zu setzen.

Was übrig bleibt, ist eine echte, aber engere Frage. Kyverno, wenn der Cluster Ressourcen erzeugen, Image-Signaturen prüfen oder berichten soll, was bereits kaputt ist. OPA, wenn Policies über Kubernetes hinausreichen müssen und eine Sprache überall den Aufwand für Rego wert ist.

Fang mit dem an, was ohnehin im Cluster steckt. Ergänze einen Controller, wenn du die Fähigkeit benennen kannst, für die du ihn holst — und wenn die Antwort nicht lautet: „Weil wir das immer so installiert haben.“

Dasselbe Prinzip zieht sich durch Secure-by-default-GKE: Die Kontrolle, die funktioniert, ist die mit der geringsten Mechanik zwischen Regel und Durchsetzung.

Häufig gestellte Fragen

Ist OPA oder Kyverno 2026 die bessere Wahl für Kubernetes?

Für reine Kubernetes-Policies ist Kyverno meist der schnellere Weg: Policies sind Kubernetes-Ressourcen in YAML mit CEL, und ein Werkzeug deckt Validierung, Mutation, Generierung, Image-Prüfung und Reporting ab. OPA mit Gatekeeper passt besser, wenn Policies über den Cluster hinausreichen, denn Rego ist eine universelle Policy-Sprache, die auch API-Autorisierung, Terraform-Prüfungen und CI-Gates abdeckt. 2026 sollte die erste Frage aber keine von beiden sein: Kubernetes erzwingt Validierung und Mutation inzwischen nativ, also prüfe zuerst, ob die eingebauten Policy-Objekte deine Regeln schon abdecken.

Was ist ValidatingAdmissionPolicy und ersetzt sie OPA und Kyverno?

ValidatingAdmissionPolicy ist die eingebaute, deklarative Alternative zu validierenden Admission-Webhooks. Sie ist seit Kubernetes 1.30 stabil, nutzt die Common Expression Language und läuft im API-Server selbst — kein externer Webhook, kein TLS-Zertifikat zum Rotieren, kein zusätzlicher Netzwerk-Hop. MutatingAdmissionPolicy ist das Gegenstück für Änderungen und seit 1.36 stabil und standardmäßig aktiv. Zusammen ersetzen sie einen großen Teil einfacher Admission-Regeln, aber keine vollständige Policy-Engine: Sie können keine Ressourcen erzeugen oder klonen, keine Image-Signaturen prüfen, keine bereits laufenden Objekte scannen und keine Policy-Reports erstellen.

Nutzt Kyverno weiterhin YAML statt Rego?

Kyverno hat nie Rego verwendet und stützt sich auch nicht mehr allein auf JMESPath. Ursprünglich nutzte Kyverno JMESPath zur JSON-Verarbeitung; da Kubernetes stark in die Common Expression Language investiert hat, unterstützt Kyverno inzwischen vollständig CEL. Moderne Kyverno-Policies bestehen aus YAML mit CEL-Ausdrücken, was das Projekt bewusst damit begründet, die kognitive Last für Plattformteams zu senken — eine Sache weniger zu lernen. Praktisch heißt das: Ein CEL-Ausdruck in einer eingebauten ValidatingAdmissionPolicy sieht einem in einer Kyverno ValidatingPolicy sehr ähnlich.

Was ist der Unterschied zwischen OPA und Gatekeeper?

OPA ist die universelle Policy-Engine und Rego ihre Sprache; das Projekt ist bei der CNCF graduiert und nicht Kubernetes-spezifisch. Gatekeeper ist die Kubernetes-Integration darauf: Es läuft als validierender und mutierender Webhook und macht Policies zu Kubernetes-Custom-Resources. In Gatekeeper schreibst du ein ConstraintTemplate mit der Rego-Logik und erzeugst dann Constraint-Ressourcen, die es mit Parametern und Geltungsbereich instanziieren. Gatekeeper ergänzt, was reines OPA im Cluster nicht mitbringt: eine parametrisierte Policy-Bibliothek, Audit-Funktionen für bestehende Verstöße, Mutations-Ressourcen wie Assign und AssignMetadata sowie External Data.

Muss ich meine Kyverno-ClusterPolicy-Ressourcen migrieren?

Ja, wenn du auf unterstützten APIs bleiben willst. Kyverno hat die CEL-basierten Policy-Typen in v1.14 und v1.15 eingeführt; seit v1.18 sind ValidatingPolicy, MutatingPolicy, GeneratingPolicy, DeletingPolicy und ImageValidatingPolicy stabil, während die alten Typen ClusterPolicy und CleanupPolicy als deprecated gelten. Das Projekt hat einen Zeitplan veröffentlicht: nur noch kritische Fixes in v1.18 und v1.19, geplante Entfernung in v1.20 im Oktober 2026. Behandle das als echte Frist und plane die Migration ein, statt sie bei einem Upgrade zu entdecken. Prüfe außerdem die Support-Matrix: Kyverno v1.18 nennt v1.33 bis v1.35 als unterstützte Kubernetes-Versionen und bietet rund drei Monate Patch-Support pro Minor-Release.

Welche Betriebsrisiken bringt ein Admission-Webhook mit sich?

Ein Webhook liegt im Pfad jeder passenden API-Anfrage und wird damit zu Infrastruktur, die den Cluster lahmlegen kann. Mit failurePolicy auf Fail blockiert ein nicht erreichbarer Webhook genau die Operationen, auf die er passt — im schlimmsten Fall kannst du keine Pods mehr erzeugen, ausgerechnet während des Vorfalls, in dem du skalieren willst. Mit Ignore verlierst du stattdessen still die Durchsetzung. Dazu kommen TLS-Zertifikate samt Rotation, die Verfügbarkeit des Controllers und Upgrade-Kompatibilität. Eingebaute Policies umgehen diese ganze Fehlerklasse, weil die Auswertung im API-Server stattfindet — eines der stärksten Argumente, sie zu nutzen, wo sie ausreichen.

Aus der Community

Diskussion im Fediverse

Antworten von Mastodon und Bluesky — direkt aus dem offenen Netz, ohne Tracking.

Antworten werden geladen …

ENDE