Vergelijking in een oogopslag
| Criterium | ValidatingAdmissionPolicy (CEL) | Kyverno | OPA Gatekeeper |
|---|---|---|---|
| Policytaal | CEL | YAML-patronen, CEL, JMESPath | Rego, optioneel CEL |
| Leercurve | Laag | Laag | Hoog |
| Mutatie | Nee | Volledig | Gedeeltelijk (Assign, AssignMetadata, ModifySet) |
| Resource generation | Nee | Ja | Nee |
| Imageverificatie | Nee | Ja (Cosign, Notary, in-toto) | Nee (externe provider nodig) |
| Referentiële constraints | Nee | Gedeeltelijk (context.apiCall) |
Ja (data.inventory) |
| Externe data | Nee | Gedeeltelijk (K8s API-calls) | Ja (willekeurige HTTP-providers) |
| Audit bestaande resources | Nee | Ja (PolicyReports) | Ja (constraint .status) |
| Policy-uitzonderingen | Alleen binding-selectors | PolicyException CRD | Alleen constraint match-exclusions |
| CLI-testing | Geen | kyverno test, Chainsaw |
gator test, gator verify |
| CNCF-volwassenheid | Ingebouwd (K8s 1.30+) | Graduated (maart 2026) | Graduated (OPA, februari 2021) |
| Operationele overhead | Nul | Laag (1-4 controllers) | Gemiddeld (webhook + audit-pods) |
Kort gezegd. Voor teams die dagelijks Kubernetes-YAML schrijven en mutatie, resource generation of imageverificatie nodig hebben: Kyverno. Voor organisaties die OPA al gebruiken over meerdere systemen of referentiële constraints en externe dataproviders nodig hebben: Gatekeeper. Voor simpele veldvalidatie zonder operationele overhead op K8s 1.30+: ValidatingAdmissionPolicy.
Inhoudsopgave
- Vergelijking in een oogopslag
- Hoe admission controllers werken
- ValidatingAdmissionPolicy: de ingebouwde optie
- Kyverno: YAML-native policy engine
- OPA Gatekeeper: Rego-aangedreven policy engine
- Hetzelfde beleid, drie manieren
- Diepere vergelijking per criterium
- Operationele aandachtspunten voor beide engines
- Wanneer kies je welke
- Aanbeveling
Hoe admission controllers werken
De Kubernetes API-server verwerkt elk muterend verzoek (create, update, delete) via een tweefasige admissionpipeline die afvuurt na authenticatie en RBAC-autorisatie. De mutatiefase draait eerst: controllers passen het binnenkomende object in serie aan. Daarna draait de validatiefase: controllers keuren goed of wijzen af. Wijst ook maar een validerende controller af, dan faalt het hele verzoek.
Zowel Kyverno als OPA Gatekeeper registreren zich als dynamische admission webhooks (MutatingWebhookConfiguration en ValidatingWebhookConfiguration). Ze draaien als in-cluster services die admission review requests ontvangen over HTTPS. ValidatingAdmissionPolicy slaat de webhook over en draait CEL-expressies in-process binnen kube-apiserver zelf.
Leesoperaties (get, list, watch) triggeren nooit admission controllers. Alleen muterende operaties doen dat.
ValidatingAdmissionPolicy: de ingebouwde optie
ValidatingAdmissionPolicy (VAP) bereikte GA-status in Kubernetes 1.30 (april 2024). Geen installatie nodig, geen draaiende services, en nul extra latency buiten de CEL-expressie-evaluatie in het API-serverproces.
Een VAP-setup gebruikt drie resources:
ValidatingAdmissionPolicydefinieert de CEL-validatielogica.ValidatingAdmissionPolicyBindingscoped het beleid naar namespaces of resources en stelt de actie in:Deny,WarnofAudit.- Param-resource (optioneel) levert runtime-parameters via een ConfigMap of custom CRD.
CEL geeft je toegang tot het ingediende object, de vorige versie via oldObject en de request-metadata. Het ondersteunt .all(), .exists(), .filter(), .has(), optional chaining (?.) en regex-operaties. Het .status.typeChecking-veld vangt zelfs typfouten in veldnamen op bij het aanmaken van het beleid.
Wat VAP niet kan: mutatie, resource generation, imagesignatuurverificatie, referentiële constraints (andere clusterresources controleren), externe dataquery's en gestructureerd uitzonderingenbeheer. Als je een van die dingen nodig hebt, heb je Kyverno of Gatekeeper nodig.
Kyverno: YAML-native policy engine
Kyverno (Grieks voor "besturen") schrijft beleid als Kubernetes custom resources in YAML. Geen aparte taal nodig. Het werd een CNCF Graduated-project op 16 maart 2026.
Kyverno deployt tot vier ontkoppelbare controllers: de admissioncontroller (verplicht), een backgroundcontroller voor asynchrone generatie en mutatie, een reportscontroller voor PolicyReport-CRD's, en een cleanupcontroller voor tijdgebonden verwijdering. In een minimale setup draait alleen de admissioncontroller.
De policymogelijkheden beslaan vijf gebieden:
- Validate: blokkeer of audit resources die regels overtreden. Ondersteunt YAML-patroonmatching (legacy API) en CEL-expressies (nieuwe
policies.kyverno.ioAPI, Kyverno 1.14+). - Mutate: pas resources aan met strategic merge patches, JSON Patch (RFC 6902) en foreach-loops. Stel securitycontext-defaults in, injecteer labels, voeg sidecars toe.
- Generate: maak nieuwe resources aan als bijeffect. Creeer automatisch een default-deny NetworkPolicy per namespace, kloon secrets over namespaces, maak RoleBindings aan.
- Imageverificatie: verifieer Cosign-handtekeningen, Notary-handtekeningen en in-toto/SLSA-attestaties voor admission. Kyverno muteert imageverwijzingen om geverifieerde digests op te nemen, wat tag-drift voorkomt.
- Uitzonderingen: een namespaced PolicyException-CRD laat specifieke resources toe om benoemd beleid te omzeilen. Standaard uitgeschakeld; moet expliciet worden ingeschakeld en tot toegestane namespaces worden beperkt.
De Kyverno CLI (kyverno apply, kyverno test) valideert beleid tegen lokale YAML zonder cluster. Chainsaw voegt declaratieve end-to-end testing toe tegen een live cluster.
OPA Gatekeeper: Rego-aangedreven policy engine
OPA Gatekeeper bouwt voort op Open Policy Agent, een CNCF Graduated-project sinds februari 2021. De primaire policytaal is Rego, een speciaal ontwikkelde declaratieve taal voor policylogica.
Het policymodel van Gatekeeper werkt met twee CRD-lagen:
- ConstraintTemplate: definieert een herbruikbare policyclass met Rego-logica en een getypeerd parameterschema (
openAPIV3Schema). Elk template maakt zijn eigen CRD-kind aan. - Constraint: een instantie van een template, geparametriseerd en gescoped naar specifieke resource-types en namespaces.
Dit tweestapsmodel is uitgebreider dan Kyverno's enkelvoudige resourcebenadering, maar geeft je API-server-niveau parametervalidatie. De gatekeeper-library biedt kant-en-klare templates voor veelvoorkomende scenario's.
Belangrijke mogelijkheden naast validatie:
- Mutatie (stabiel sinds v3.10):
AssignMetadatavoor labels/annotaties,Assignvoor willekeurige velden,ModifySetvoor lijstoperaties,AssignImagevoor imagecomponenten. Beperkter dan Kyverno's mutatie:AssignMetadatakan labels alleen toevoegen, niet wijzigen. - Externe dataproviders (v3.11+): roep willekeurige in-cluster HTTP-services aan voor imagescanning, compliancechecks of identiteitslookups. Noch VAP, noch Kyverno biedt dit.
- Referentiële constraints: Rego kan
data.inventorybevragen om bestaande clusterresources te controleren. "Weiger deze Ingress als een andere Ingress al deze hostname claimt" is een eenvoudige Rego-regel. - VAP-integratie: Gatekeeper kan native
ValidatingAdmissionPolicy-resources genereren uit templates die deK8sNativeValidationCEL-engine gebruiken, waardoor je in-process enforcement krijgt naast de webhook.
De gator CLI (gator test, gator verify) handelt offline testen af. Enforcement-acties per constraint: deny (standaard), warn of dryrun.
Hetzelfde beleid, drie manieren
Een app-label verplichten op elke pod is de "Hello World" van Kubernetes-beleid. Zo pakt elke aanpak het aan.
ValidatingAdmissionPolicy (CEL):
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:
name: require-app-label
spec:
matchConstraints:
resourceRules:
- apiGroups: [""]
apiVersions: ["v1"]
operations: ["CREATE", "UPDATE"]
resources: ["pods"]
validations:
- expression: "has(object.metadata.labels) && has(object.metadata.labels.app)"
message: "Pod must have an 'app' label"
Zeven regels spec. Geen draaiende service nodig.
Kyverno (ClusterPolicy):
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-app-label
spec:
validationFailureAction: Enforce
rules:
- name: check-app-label
match:
any:
- resources:
kinds: ["Pod"]
validate:
message: "Pod must have an 'app' label"
pattern:
metadata:
labels:
app: "?*"
Het "?*"-patroon betekent "elke niet-lege string." Leesbaar zonder kennis van een policytaal.
OPA Gatekeeper (ConstraintTemplate + Constraint):
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}] {
provided := {label | input.review.object.metadata.labels[label]}
required := {label | label := input.parameters.labels[_]}
missing := required - provided
count(missing) > 0
msg := sprintf("missing required labels: %v", [missing])
}
---
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequiredLabels
metadata:
name: pods-must-have-app
spec:
enforcementAction: deny
match:
kinds:
- apiGroups: [""]
kinds: ["Pod"]
parameters:
labels: ["app"]
Het tweefasemodel is uitgebreider, maar het getypeerde parameters-schema betekent dat de API-server constraintparameters valideert bij het aanmaken. En het template is herbruikbaar: een tweede constraint kan andere labels verplichten op Deployments zonder nieuwe Rego te schrijven.
Diepere vergelijking per criterium
Mutatie
ValidatingAdmissionPolicy kan niet muteren. Punt.
Kyverno biedt het rijkste mutatiemodel: strategic merge patches voegen velden toe zonder bestaande te overschrijven, JSON Patch (RFC 6902) richt zich op precieze paden, en foreach-loops itereren over containers. De conditionele +(field)-syntax voegt een veld alleen toe als het nog niet bestaat, wat mutaties idempotent maakt. securityContext.readOnlyRootFilesystem: true instellen op elke container, een Istio sidecar-label injecteren op namespaces, imagetags pinnen aan digests na verificatie: dat zijn allemaal operaties van een enkele regel.
Gatekeeper's mutatie (stabiel sinds v3.10) werkt via vier CRD-types: AssignMetadata, Assign, ModifySet, AssignImage. Het dekt de meeste mutatiegebruikscases maar met beperkingen. AssignMetadata kan labels en annotaties alleen toevoegen, niet wijzigen. Meerdere mutaties op hetzelfde object worden alfabetisch op naam van de mutator toegepast, wat zorgvuldige naamgeving vereist.
Winnaar voor mutatie: Kyverno, met ruime voorsprong.
Resource generation
Alleen Kyverno ondersteunt dit. Generate-regels maken nieuwe resources aan als bijeffecten van admission of achtergrondscanning. Het standaardvoorbeeld: automatisch een default-deny NetworkPolicy aanmaken in elke nieuwe namespace. Met synchronize: true blijft de gegenereerde resource in sync met het policytemplate. Met generateExisting: true maakt Kyverno de resource aan in al bestaande namespaces wanneer het beleid voor het eerst wordt uitgerold.
Noch VAP, noch Gatekeeper kan resources genereren. Als je dit nodig hebt zonder Kyverno, schrijf je een custom controller.
Imageverificatie en supply chain security
Kyverno verifieert Sigstore Cosign-handtekeningen, Notary-handtekeningen en in-toto-attestaties (inclusief SLSA-provenance) direct bij admission. Als een verifyImages-regel slaagt, muteert Kyverno de imageverwijzing om de geverifieerde digest op te nemen (nginx:1.25 wordt nginx@sha256:abc...), wat tag-drift na verificatie voorkomt.
Gatekeeper heeft geen ingebouwde imageverificatie. Je kunt iets vergelijkbaars bereiken met een externe dataprovider die een signatuurverificatieservice aanroept, maar dan bouw en onderhoud je die service zelf.
VAP heeft geen imageverificatiemogelijkheid.
Referentiële constraints
Referentiële constraints controleren de ingediende resource tegen andere bestaande resources in het cluster. "Weiger deze Ingress als een andere Ingress al deze hostname claimt." "Weiger deze PVC als de gerefereerde StorageClass niet bestaat."
Gatekeeper handelt dit native af via data.inventory in Rego, dat een cache van clusterresources blootstelt. Dit is Gatekeeper's sterkste onderscheidend vermogen.
Kyverno kan referentiële checks uitvoeren via context.apiCall-aanroepen naar de Kubernetes API, maar dat is een runtime API-call per admission request, geen gecachte lookup. Het werkt, maar het is minder efficient en minder ergonomisch dan Gatekeeper's data.inventory.
VAP heeft helemaal geen ondersteuning voor referentiële constraints.
Externe data
Gatekeeper's externe dataproviders (v3.11+) staan Rego-policies toe om willekeurige in-cluster HTTP-services aan te roepen. Imagekwetsbaarheidscanning, compliancesysteem-lookups, tag-naar-digest-resolutie: het HTTP-endpoint ontvangt een lijst sleutels en retourneert gestructureerde resultaten. TLS 1.3+ is vereist, mTLS wordt ondersteund en responses kunnen worden gecachet (v3.13+).
Kyverno's context.apiCall is beperkt tot de Kubernetes API-server. Het kan geen willekeurige externe HTTP-endpoints aanroepen.
VAP kan geen externe calls maken.
Policy-uitzonderingen
Kyverno biedt een dedicated PolicyException-CRD die specifieke resources vrijstelt van benoemd beleid en regels. Uitzonderingen zijn namespaced, standaard uitgeschakeld, en moeten via controllervlaggen tot toegestane namespaces worden beperkt. Dit is een gestructureerde uitzonderingsworkflow.
Gatekeeper gebruikt match-exclusions op constraints (namespace-selectors, label-selectors). Er is geen dedicated uitzonderingsresource. Bredere vrijstellingen vereisen aanpassing van de constraint zelf.
VAP gebruikt binding-selectors. Dezelfde beperking als Gatekeeper: geen dedicated uitzonderingsmechanisme.
Policytaal en leercurve
VAP gebruikt CEL. Als je al CEL-expressies hebt geschreven voor Kubernetes (of Google Cloud IAM), ken je de syntax al.
Kyverno's legacy API gebruikt YAML-patroonmatching en JMESPath. De nieuwe API (policies.kyverno.io, Kyverno 1.14+) gebruikt CEL. Hoe dan ook, het beleid ziet eruit als Kubernetes-resources. Een platformengineer die dagelijks YAML schrijft, kan Kyverno-beleid opstellen zonder een nieuwe taal te leren.
Gatekeeper vereist Rego. Rego is krachtig: setoperaties, willekeurige berekeningen, referentiële lookups. Maar het is een aparte taal met een eigen evaluatiemodel. Teams hebben dedicated leertijd nodig. De tradeoff: als je organisatie OPA al gebruikt voor microservice-autorisatie, API-gatewaybeleid of CI/CD-checks, is Rego een gedeelde taal door de hele stack.
Audit van bestaande resources
Zowel Kyverno als Gatekeeper auditen bestaande resources die er al waren voor het beleid werd uitgerold. Kyverno's backgroundcontroller genereert PolicyReport-CRD's. Gatekeeper's auditcontroller schrijft violations naar het .status.violations-veld van elke constraint.
VAP heeft geen auditmogelijkheid. Het evalueert resources alleen op het moment van admission.
Testen in CI
Kyverno: kyverno test draait policy-unittests met verwachte pass/fail-uitkomsten. Chainsaw biedt end-to-end testing tegen een live cluster.
Gatekeeper: gator test valideert resources tegen templates en constraints offline. gator verify draait suite-gebaseerde tests.
VAP: geen officiele CLI-testtool.
Zowel de Kyverno- als Gatekeeper-CLI's zijn te integreren in GitHub Actions, GitLab CI of Jenkins. Beleid moet tegen manifests worden getest in CI voordat het een cluster bereikt.
Operationele aandachtspunten voor beide engines
Beide engines registreren admission webhooks, wat betekent dat een falende policy engine clusteroperaties kan blokkeren. Deze operationele praktijken zijn niet onderhandelbaar voor productie:
Failure policy. failurePolicy: Fail betekent dat een onbereikbare webhook alle matchende API-verzoeken afwijst. Beide engines gebruiken dit standaard voor validatiewebhooks. Het garandeert compliance, maar het kan het hele cluster blokkeren als de policy engine down is. Draai met hoge beschikbaarheid of accepteer het risico.
Namespace-exclusions. Sluit kritieke systeemnamespaces uit van webhookregels: kube-system, kube-public, kube-node-lease en de namespace van de policy engine zelf (kyverno of gatekeeper-system). Zonder dit kan een falende engine zichzelf niet herstarten omdat de API-server zijn eigen podcreatie blokkeert. Kyverno 1.12+ sluit kube-system standaard uit op EKS.
Hoge beschikbaarheid. Kyverno: productie-installaties moeten --replicas=3 gebruiken voor de admissioncontroller. Gatekeeper: deploy meerdere webhookreplica's met een PodDisruptionBudget.
Timeouts. Houd webhook timeoutSeconds laag (1-5 seconden). Lange timeouts cascaderen tot cluster-brede API-latency.
Geleidelijke uitrol. Beide engines ondersteunen niet-blokkerende modes. Kyverno: stel validationFailureAction: Audit in. Gatekeeper: stel enforcementAction: dryrun in. Rol nieuw beleid altijd uit in audit/dryrun-modus, observeer violations, schakel dan over naar enforcement.
Wanneer kies je welke
Kies ValidatingAdmissionPolicy (CEL) wanneer:
- Je minimale clusterversie Kubernetes 1.30+ is.
- Je alleen validatie nodig hebt (geen mutatie, geen generatie, geen imageverificatie).
- Beleid eenvoudige veldcontroles betreft: labelhandhaving, naamconventies, replicalimits.
- Nul operationele overhead belangrijker is dan featurebreedte.
Kies Kyverno wanneer:
- Je team dagelijks in Kubernetes-YAML werkt en beleid in dezelfde taal wil.
- Je mutatie nodig hebt (securitycontext-defaults, labelinjectie, sidecarinjectie).
- Je resource generation nodig hebt (default-deny NetworkPolicies, secretkloning, RoleBinding-provisioning).
- Je imagesignatuurverificatie nodig hebt (Cosign, Notary, SLSA-provenance).
- Je gestructureerde policy-uitzonderingen wilt met namespace-scoped controls.
- Je migreert van PodSecurityPolicy. Kyverno heeft een gedocumenteerd PSP-migratiepad. Voor de ingebouwde PSP-vervanger, zie mijn gids over Pod Security Standards.
Kies OPA Gatekeeper wanneer:
- Je organisatie OPA al gebruikt voor beleid over meerdere systemen (microservices, API-gateways, CI/CD) en Rego een gedeelde taal is.
- Je referentiële constraints nodig hebt die resources controleren tegen gecachte clusterstatus.
- Je externe dataproviders nodig hebt om willekeurige HTTP-services aan te roepen bij admission.
- Je diep getypeerde parameterschema's wilt (het
openAPIV3Schemaop ConstraintTemplates).
Hybride aanpak. Sommige organisaties draaien Kyverno voor Kubernetes-native zaken (mutatie, generatie, imageverificatie) en OPA voor cross-stack beleid. Dit werkt, maar verdubbelt wel het operationele oppervlak.
Aanbeveling
Voor het meest voorkomende geval, een platformteam dat voor het eerst policy enforcement invoert: begin met Kyverno. De leercurve is het laagst. YAML-native beleid verwijdert de drempel van een nieuwe taal. Mutatie, generatie en imageverificatie dekken de features die teams in de praktijk nodig hebben. Het werd in maart 2026 een CNCF Graduated-project, waarmee de volwassenheidsvraag is beantwoord.
Als je organisatie al OPA- en Rego-expertise heeft over meerdere systemen, is Gatekeeper de logische keuze. De investering in Rego betaalt zich terug door een uniforme policytaal van API-gateway tot Kubernetes-admission tot CI/CD-pipeline. Referentiële constraints en externe dataproviders zijn mogelijkheden die Kyverno niet kan evenaren.
Voor eenvoudige validatie-only use cases op Kubernetes 1.30+, begin met ValidatingAdmissionPolicy. Je kunt later altijd Kyverno of Gatekeeper toevoegen wanneer je mutatie of generatie nodig hebt. Beide engines kunnen VAP-resources genereren uit hun eigen policydefinities, dus beleid migreren is een beheerd proces in plaats van een herschrijving.