Kubernetes admission controllers en policy engines: Kyverno vs OPA Gatekeeper vs CEL

Elk API-verzoek aan een Kubernetes-cluster passeert admission controllers na authenticatie en RBAC-autorisatie. Policy engines zoals Kyverno en OPA Gatekeeper haken in op deze pipeline om resources te valideren, muteren en genereren. Kubernetes 1.30 voegde een ingebouwde optie toe, ValidatingAdmissionPolicy (CEL), die eenvoudige validatie afhandelt zonder draaiende services. Dit artikel vergelijkt alle drie zodat je de juiste kunt kiezen voor jouw cluster.

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

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:

  1. ValidatingAdmissionPolicy definieert de CEL-validatielogica.
  2. ValidatingAdmissionPolicyBinding scoped het beleid naar namespaces of resources en stelt de actie in: Deny, Warn of Audit.
  3. 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:

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:

  1. ConstraintTemplate: definieert een herbruikbare policyclass met Rego-logica en een getypeerd parameterschema (openAPIV3Schema). Elk template maakt zijn eigen CRD-kind aan.
  2. 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): AssignMetadata voor labels/annotaties, Assign voor willekeurige velden, ModifySet voor lijstoperaties, AssignImage voor imagecomponenten. Beperkter dan Kyverno's mutatie: AssignMetadata kan 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.inventory bevragen 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 de K8sNativeValidation CEL-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 openAPIV3Schema op 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.

Terugkerende server- of deploymentproblemen?

Ik help teams productie betrouwbaar maken met CI/CD, Kubernetes en cloud—zodat fixes blijven en deploys geen stress meer zijn.

Bekijk DevOps consultancy

Doorzoek deze site

Begin met typen om te zoeken, of blader door de kennisbank en blog.