---
title: "OPA vs. Kyverno 2026: Kubernetes liefert Policies jetzt selbst"
description: "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."
author: Aleksei Aleinikov
date: 2026-08-12
lang: de
tags: [opa vs kyverno, kubernetes policy engine, validatingadmissionpolicy, policy as code, gatekeeper]
canonical: https://www.alekseialeinikov.com/de/blog/topics/security/opa-vs-kyverno-2026-kubernetes-policy-engine-vergleich
source: alekseialeinikov.com
---

# OPA vs. Kyverno 2026: Kubernetes liefert Policies jetzt selbst

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.](https://www.alekseialeinikov.com/blog/opa-kyverno-2026.webp)

## 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:

```yaml
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:

```yaml
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](https://www.alekseialeinikov.com/de/blog/topics/security/falco-in-produktion-runtime-security-ohne-alarm-flut-2026) 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:

| 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**:

| 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.](https://www.alekseialeinikov.com/blog/opa-kyverno-matrix-2026.webp)

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](https://www.alekseialeinikov.com/de/blog/topics/devops/sbom-stoppt-das-naechste-log4j-nicht-2026) — 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.

```yaml
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.](https://www.alekseialeinikov.com/blog/opa-kyverno-decision-2026.webp)

## 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.](https://www.alekseialeinikov.com/blog/opa-kyverno-webhook-2026.webp)

## 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:

| 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](https://www.alekseialeinikov.com/de/blog/topics/devops/platform-engineering-auf-kubernetes-2026)-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](https://www.alekseialeinikov.com/de/blog/topics/architecture/secure-by-default-gke-referenzarchitektur-2026): Die Kontrolle, die funktioniert, ist die mit der geringsten Mechanik zwischen Regel und Durchsetzung.
