Kyverno
auf einem Blatt.
Dichte Referenz für Senior Platform Engineers und SREs zur Kubernetes-Policy-Engine (CNCF Graduated). Controller-Architektur, CEL-Policy-Typen, Image-Verifikation mit Sigstore, PolicyReports, Abgrenzung zu ValidatingAdmissionPolicy/MutatingAdmissionPolicy, Webhook-Tuning und Anti-Patterns. Keine Einsteiger-Folien.
Vorschau (2 Seiten A4 quer + Brand-Rückseite)


PDF herunterladen
Direkter Download, keine Mail-Adresse nötig. CC BY-SA 4.0: kopieren, drucken, weiterverteilen ist ausdrücklich erlaubt, solange die Quellenangabe sichtbar bleibt.
Was drin steht
Architektur
Vier Controller (Admission, Background, Reports, Cleanup), dynamisch generierte Webhooks aus den Policy-Matches, Cert-Rotation, HA mit 3 Replicas.
Policy-Typen 1.19
CEL-Engine policies.kyverno.io/v1 (stable seit 1.17, Feature-Parität seit 1.19): ValidatingPolicy, MutatingPolicy, GeneratingPolicy, DeletingPolicy, ImageValidatingPolicy. ClusterPolicy deprecated, Removal mit 1.20 (geschätzt Nov 2026).
Validieren & Mutieren
validationActions Deny/Audit, Admission- vs. Background-Evaluation, JSON-Mode für CI-Pipelines, ApplyConfiguration/JSONPatch, mutateExisting.
Supply Chain
ImageValidatingPolicy mit Cosign (Key/Keyless) und Notary, SBOM- und in-toto-Attestations, mutateDigest und verifyDigest gegen mutable Tags.
VAP/MAP & Exceptions
Präzise Abgrenzung zu K8s-nativen CEL-Policies (VAP GA 1.30, MAP GA 1.36), native VAP-Generierung, PolicyException-Governance, Autogen für Pod-Controller.
Compliance & Betrieb
PolicyReports (wgpolicyk8s.io) als Audit-Evidenz, failurePolicy fail-closed vs. fail-open, Webhook-Timeout, resourceFilters, K8s-Matrix, 1.19-Upgrade, Security-Mindestversion 1.19.1, Anti-Patterns aus der Praxis.
Cheatsheet im Volltext
Derselbe Inhalt wie im PDF, zum Mitlesen, Durchsuchen und direkten Kopieren der YAML-Snippets. Stand: Kyverno v1.19 (Edition 2026.10).
Architektur
Vier Controller, eine Policy-Engine
Admission-Controller (Pflicht): nimmt die Webhook-Callbacks des API-Servers an, führt validate/mutate aus, prüft PolicyExceptions.
Background-Controller: generate- und mutate-existing-Regeln auf Bestandsressourcen (reconciled UpdateRequests). Reports-Controller: erzeugt und pflegt PolicyReports. Cleanup-Controller: löscht Ressourcen nach Zeitplan.
Kyverno gehört in einen dedizierten
Namespace, nie nach kube-system.
CNCF-Graduated-Projekt (seit März 2026).
Dynamische Webhooks
Kyverno generiert seine Validating-/MutatingWebhookConfigurations selbst aus den match-Blöcken der installierten Policies, nur gematchte Ressourcen erzeugen überhaupt Admission-Calls.
Zertifikate: self-signed, automatische Rotation (CA 1 Jahr, TLS 150 Tage, Renewal ca. 15 Tage vor Ablauf). HA: 3 Replicas für den Admission-Controller; mehr Replicas bedeutet nicht bei jedem Controller mehr Durchsatz.
helm repo add kyverno https://kyverno.github.io/kyverno/ helm install kyverno kyverno/kyverno \ -n kyverno --create-namespace kubectl -n kyverno get deploy # 4 Controller kubectl get validatingwebhookconfigurations | grep kyverno
Policy-Typen (Stand 1.19)
CEL-Typen: policies.kyverno.io/v1
Seit 1.17 stable (v1):
ValidatingPolicy, MutatingPolicy,
GeneratingPolicy, DeletingPolicy,
ImageValidatingPolicy, dazu
PolicyException. Jeder Policy-Typ auch namespaced
(NamespacedValidatingPolicy usw.). Ein CR pro
Zweck, CEL statt JMESPath/Pattern; seit 1.19 Feature-Parität
zu ClusterPolicy.
Storage-Version bleibt bis 1.19
v1beta1, mit 1.20 v1: danach
gespeicherte Objekte per kyverno migrate
umschreiben. v1alpha1 ist deprecated, Manifeste auf
v1 heben.
Legacy: ClusterPolicy / Policy
kyverno.io/v1: validate-, mutate-, generate- und
verifyImages-Regeln in einem CR. ClusterPolicy
cluster-weit, Policy namespaced.
Deprecated: abgekündigt mit 1.17,
offiziell seit 1.19 (Admission-Warnung beim Anlegen/Ändern).
1.19 ist das letzte Release mit vollem Support,
Removal mit 1.20 (geschätzt Nov 2026),
zusammen mit (Cluster)CleanupPolicy und der
Legacy-PolicyException kyverno.io/v2. Bestand nach
Migrations-Guide umziehen.
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata: {name: require-ns-purpose-label}
spec:
rules:
- name: require-ns-purpose-label
match:
any:
- resources: {kinds: [Namespace]}
validate:
failureAction: Enforce # oder Audit
message: "Label `purpose` ist Pflicht."
pattern:
metadata:
labels:
purpose: production
Validieren mit CEL
apiVersion: policies.kyverno.io/v1
kind: ValidatingPolicy
metadata: {name: check-labels}
spec:
validationActions: [Deny]
matchConstraints:
resourceRules:
- apiGroups: [""]
apiVersions: [v1]
operations: [CREATE, UPDATE]
resources: [pods]
validations:
- message: label 'environment' ist Pflicht
expression: >-
'environment' in
object.metadata.?labels.orValue([])
Enforcement & Modi
validationActions: Deny blockt,
Audit protokolliert nur.
spec.evaluation: admission und
background getrennt schaltbar;
mode: JSON prüft beliebige JSON-/YAML-Payloads
auch außerhalb des Clusters (CI-Pipeline).
matchConstraints folgt der API der K8s
ValidatingAdmissionPolicy.
Mutieren & Generieren
MutatingPolicy
patchType: ApplyConfiguration
(Server-Side-Apply-Merge) oder JSONPatch.
Bestandsressourcen:
spec.evaluation.mutateExisting.enabled: true, der
Background-Controller mutiert dann bereits existierende Objekte.
Trigger und Ziel trennen per targetMatchConstraints
(seit 1.17 auch als CEL-expression); ein Trigger
mutiert alle passenden Ziele.
apiVersion: policies.kyverno.io/v1
kind: MutatingPolicy
metadata: {name: add-label}
spec:
matchConstraints:
resourceRules:
- apiGroups: [""]
apiVersions: [v1]
operations: [CREATE]
resources: [pods]
mutations:
- patchType: ApplyConfiguration
applyConfiguration:
expression: >
Object{metadata: Object.metadata{
labels: Object.metadata.labels{
team: "platform"}}}
GeneratingPolicy
Erzeugt oder klont Ressourcen auf Trigger, Klassiker:
Default-NetworkPolicy oder ResourceQuota bei jedem neuen
Namespace. Seit 1.19 auch als YAML:
generate[].template.value, mit
interpolate: cel für
(( ... ))-Platzhalter, und
useServerSideApply: true für SSA. Läuft
über UpdateRequests des Background-Controllers.
Image-Verifikation (Supply Chain)
ImageValidatingPolicy: Sigstore & Notary
Attestors: Cosign (Public Key, Keyless via OIDC issuer/subject, Transparency Log, TUF) und Notary (X.509-Zertifikate, optional TSA).
Attestations: SBOM- und in-toto-Predicates
prüfen via verifyAttestationSignatures() und
extractPayload().
validationConfigurations:
mutateDigest (Tag wird Digest),
verifyDigest, required, alle Default
true. verifyDigest wird seit 1.19
durchgesetzt: mit mutateDigest: false fallen Images
ohne Digest durch.
apiVersion: policies.kyverno.io/v1
kind: ImageValidatingPolicy
metadata: {name: verify-images}
spec:
matchConstraints:
resourceRules:
- apiGroups: [""]
apiVersions: [v1]
operations: [CREATE]
resources: [pods]
matchImageReferences:
- glob: "registry.example.com/*"
attestors:
- name: cosign
cosign:
key:
data: |
-----BEGIN PUBLIC KEY-----
...
-----END PUBLIC KEY-----
validations:
- expression: >-
images.containers.map(image,
verifyImageSignatures(image,
[attestors.cosign])).all(e, e > 0)
message: "Signatur-Check fehlgeschlagen"
Abgrenzung: K8s-native CEL-Policies
Was der API-Server selbst kann
ValidatingAdmissionPolicy: GA seit K8s 1.30. MutatingAdmissionPolicy: GA seit K8s 1.36.
CEL läuft in-process im kube-apiserver: keine Webhooks, keine Zertifikate, keine Verfügbarkeits-Abhängigkeit von einem Policy-Deployment.
Was Kyverno darüber legt
Background-Scans auf Bestandsressourcen, PolicyReports, PolicyExceptions, generate/cleanup, Image-Signatur-Verifikation, JSON-Mode, Autogen.
ValidatingPolicy ist ein Superset
der VAP und generiert via
spec.autogen.validatingAdmissionPolicy.enabled: true
eine native VAP, die im API-Server läuft
(Flag generateValidatingAdmissionPolicy, Default an).
MutatingPolicy analog per
spec.autogen.mutatingAdmissionPolicy.enabled, Flag
generateMutatingAdmissionPolicy (Default aus), MAP
v1 ab K8s 1.36 seit Kyverno 1.19 (K8s 1.36 liegt außerhalb
der offiziellen Testmatrix). Kyverno als Management-Layer,
Enforcement ohne Webhook-Hop.
PolicyException & Autogen
PolicyException
Gezielte Ausnahme statt aufgeweichter Policy. CEL:
policies.kyverno.io/v1, policyRefs
(Name + Kind) plus CEL-matchConditions;
images/allowedValues reicht die
Exception als
exceptions.allowedImages/exceptions.allowedValues
in die CEL-Auswertung, expiresAt seit 1.19. Legacy
kyverno.io/v2 (Policy + Regeln, Wildcard
*): deprecated, Removal mit 1.20.
Default: deaktiviert (Helm
features.policyExceptions.enabled). Aktivierung per
--enablePolicyException +
--exceptionNamespace. Leer wirkt je nach Engine
anders: Legacy-Exceptions greifen dann gar nicht, CEL-Exceptions
aus allen Namespaces (wie *). Also
immer genau einen Namespace setzen, Erstellung per RBAC und
GitOps kontrollieren.
ImageValidatingPolicy vor 1.19.1: eine
passende Exception ignoriert
images/allowedValues und schaltet die
Signaturprüfung für die ganze Ressource ab
(GHSA-5cjf-wwfg-pj4c). Mindestversion siehe Box „Security:
mindestens 1.19.1“.
Autogen für Pod-Controller
Pod-Regeln werden automatisch auf die Pod-Controller
ausgeweitet. CEL: Deployment, DaemonSet, StatefulSet,
ReplicaSet, Job, CronJob, Auswahl über
spec.autogen.podControllers.controllers; seit
1.19.1 auch Workload-CRDs (JobSet, RayJob …) als
<resource>.<version>.<group>.
Legacy zusätzlich ReplicationController, Annotation
pod-policies.kyverno.io/autogen-controllers
(none schaltet ab).
Achtung: greift Pod-Controller-Autogen (bei
Pod-Policies Default, auch ohne podControllers),
erzeugt Kyverno keine native VAP bzw. MAP (Grund
im Policy-Status).
PolicyReports (Compliance)
Audit-Evidenz im Cluster
wgpolicyk8s.io/v1alpha2:
PolicyReport (namespaced) und
ClusterPolicyReport, offenes Format der
Kubernetes Policy WG, nicht Kyverno-proprietär.
Alternative seit 1.15 (Alpha):
openreports.io/v1alpha1 per
--openreportsEnabled (Helm
openreports.enabled, Default aus), soll
wgpolicyk8s langfristig ablösen.
Results: pass / fail / warn / error / skip.
Gefüttert aus Admission-Requests und
Background-Scans (Default: stündlich), deckt auch
Bestandsressourcen ab, die nie durch Admission liefen.
kubectl get policyreport -A # namespaced
kubectl get clusterpolicyreport # cluster-scoped
kubectl get polr -o wide # Kurzform
kubectl get polr <name> -o jsonpath=\
'{.results[?(@.result=="fail")]}'
Webhook-Betrieb
failurePolicy: bewusst entscheiden
Default Fail (fail-closed): ist Kyverno down, lehnt der API-Server alle gematchten Requests ab. Sicher, aber ein Verfügbarkeits-Risiko, HA-Replicas und PDB einplanen.
Fail-open global per
--forceFailurePolicyIgnore, besser pro
Policy abwägen: Security-Gates Fail,
Komfort-Mutationen Ignore.
Neustart-Deadlock:
--excludeBootstrapResources (seit 1.19, Default
aus) nimmt Node und CSR aus den Fail-Webhooks, damit ein Cluster
ohne laufende Kyverno-Pods wieder hochkommt. Policies auf diese
Kinds greifen dann nicht.
Performance-Tuning
Webhook-Timeout: Default 10s (1–30s), knapp halten, hängende Admission bremst jedes Deployment.
Namespace-Filter:
webhooks.namespaceSelector in der Kyverno-ConfigMap;
kube-system und kyverno sind default
ausgenommen. resourceFilters
[Kind,Namespace,Name]: letzte Verteidigungslinie
hinter dem Webhook. Background-Reports ignorieren sie per
Default (--skipResourceFilters=true), CEL-generate
und -mutateExisting beachten sie seit 1.19.
Match-Blöcke eng schneiden: was nicht matcht, erzeugt keinen Admission-Call.
Egress aus Policies: CEL
http.Get/Post und apiCall.service
laufen gegen --httpBlocklist (Default:
Cloud-Metadaten 169.254.169.254,
metadata.google.internal, Loopback; ein eigener Wert
ersetzt die Defaults, also mitführen) und optional
--httpAllowlist (URL-Präfixe). In
Namespaced-Policies ist HTTP per Default aus
(--allowHTTPInNamespacedPolicies=false). Für
Legacy-apiCall und GlobalContextEntry gilt die
Blocklist erst ab 1.19.1.
Upgrade & Support
Security: mindestens 1.19.1
Fünf Advisories vom 10.09.2026, gefixt nur in 1.19.1, kein Fix für 1.18:
GHSA-5qq8-67g6-4h2w (Critical, 9.9): Tenant
mit Create-Recht auf namespaced Policy
(kyverno.io/v1) schreibt per apiCall
method: POST und %2e%2e im
urlPath als Kyverno-SA in beliebige Namespaces, bis
Cluster-Admin.
Dazu High: %2e%2e-Bypass der
Namespace-Isolation bei apiCall
(GHSA-c5qq-7g2q-cpqp), SSRF/SA-Token über
Legacy-apiCall.service und GlobalContextEntry
(GHSA-q825-p383-r9v5), namespace-übergreifendes Lesen von
globalContext aus Namespaced-CEL-Policies
(GHSA-59v6-2x73-wfg4), Exception-Bypass bei
ImageValidatingPolicy (GHSA-5cjf-wwfg-pj4c).
Vor dem Upgrade auf 1.19
K8s-Matrix: Kyverno 1.18.x/1.19.x auf K8s 1.33 bis 1.35, andere Versionen ungetestet.
Support: offiziell nur 1.19 (bis 1.20, geschätzt Nov 2026), Patches nur für kritische Bugs und Critical/High-CVEs.
CRDs: die policies.kyverno.io-Typen
kommen aus der Chart-Abhängigkeit kyverno-api
(seit Chart 3.7), der Rest aus dem Subchart crds,
beide über crds.install; wer CRDs separat
ausrollt, prüft beide Quellen vorher.
kyverno-policies 3.9 tauscht die PSS-Policies
beim Helm-Upgrade gegen ValidatingPolicy
(policyType); bestehende Legacy-Exceptions
kyverno.io/v2 auf diese Policies greifen dann nicht
mehr, vorher als policies.kyverno.io/v1-Exception
neu anlegen oder policyType: ClusterPolicy
pinnen.
1.19.1 ändert Verhalten:
globalContext ist in Namespaced-Policies gesperrt
(Fix GHSA-59v6-2x73-wfg4); solche Policies vor dem Patch-Update
prüfen.
Legacy-Bestand finden: Admission-Warnungen,
Metrik kyverno_deprecated_api_requests_total und
--warnings-as-errors für kyverno
test und kyverno apply in CI (beide ab
1.19.1).
Anti-Patterns
Was du nicht tun solltest
Neue Policies als ClusterPolicy: offiziell deprecated seit 1.19, fällt mit 1.20 weg, Neues gehört in die CEL-Typen.
Enforce ohne Audit-Phase: neue Policies erst im Audit-Modus fahren, PolicyReports lesen, dann auf Deny/Enforce drehen.
Pauschal fail-open: Ignore
überall hebelt Security-Policies bei jedem Kyverno-Ausfall
aus.
Wildcard-Matches: jede Admission geht durch den Webhook, Latenz auf jedem API-Call, maximaler Blast-Radius bei Ausfall.
Exceptions ohne Governance: wer
PolicyExceptions erstellen darf, hebelt Policies aus,
exceptionNamespace + RBAC + Review-Pflicht.
Namespaced Policies als Tenant-Self-Service:
apiCall, generate und mutateExisting aus
Policy und Namespaced*Policy laufen mit
den Rechten der Kyverno-ServiceAccounts. 2026 gab es dafür
zwei Critical-Advisories (CVE-2026-54523, GHSA-5qq8-67g6-4h2w).
Create-Rechte nur für das Plattform-Team bzw. per
GitOps-Review.
Kyverno neben andere Workloads: dedizierter
Namespace ist Vorgabe der Doku, nie nach
kube-system deployen.
Verwandte Cheatsheets
Ebenfalls von OMNI52:
kubernetes-cheatsheet.de, Kubernetes Core
rke2-cheatsheet.de, RKE2-Distribution
rancher-cheatsheet.de, Rancher-Management
istio-cheatsheet.de, Service-Mesh-Layer (Istio in der Tiefe)
Lizenz & Weiterverteilung
Nicht erlaubt: Logo, Marken oder den Eindruck zu vermitteln, dass der Inhalt von dir/euch stammt oder dass OMNI52 GmbH die Weiterverwendung sponsort.
Volltext der Lizenz: creativecommons.org/licenses/by-sa/4.0/deed.de.
Kyverno is a trademark of The Linux Foundation; Kyverno is a Cloud Native Computing Foundation (CNCF) Graduated project. Kubernetes is a registered trademark of The Linux Foundation. OMNI52™ is a trademark of OMNI52 GmbH (filed, not yet registered). This website is operated by OMNI52 GmbH and is not affiliated with, endorsed by, or sponsored by The Linux Foundation, the CNCF, or the Kyverno project. “Kyverno” is used in a nominative / descriptive sense to indicate the technology this cheatsheet documents.