Kyverno: Kubernetes-native policy engine

Kyverno is een policy engine die speciaal voor Kubernetes is gebouwd. Policies schrijf je als standaard Kubernetes-resources in YAML, niet in een aparte taal, en Kyverno dwingt ze af als admission controller voordat resources je cluster bereiken. Het valideert, muteert, genereert resources en verifieert container-image-signatures. Dit artikel legt uit hoe Kyverno werkt, wat je ermee kunt doen en hoe het zich verhoudt tot OPA/Gatekeeper.

Wat Kyverno is

Kyverno is een policy engine die specifiek voor Kubernetes is ontworpen. Het draait als een set admission controllers in je cluster en onderschept API-requests voordat ze in etcd worden opgeslagen. Het project heeft in maart 2026 de Graduated-status binnen de CNCF bereikt, na toetreding tot de CNCF Sandbox in 2020 en de Incubating-status in 2022.

De bepalende ontwerpkeuze: policies zijn Kubernetes-resources. Je schrijft ze in YAML. Je past ze toe met kubectl. Je versiebeheer ze in Git naast je manifests. Er is geen aparte taal om te leren, geen externe policyserver om te beheren en geen vertaallaag tussen wat je deployt en wat je afdwingt.

Dat is belangrijk, want de drempel om policy-enforcement in te voeren is traditioneel hoog. OPA/Gatekeeper vereist dat je policies schrijft in Rego, een op maat gemaakte logische taal die krachtig is maar een flinke leercurve heeft. Kyverno ruilt een deel van die ruwe expressiviteit in voor directe herkenbaarheid: als je een Kubernetes-manifest kunt schrijven, kun je een Kyverno-policy schrijven.

Hoe Kyverno werkt

Wanneer je Kyverno installeert (meestal via een enkel Helm chart), registreert het twee webhook-configuraties bij de Kubernetes API-server: een MutatingWebhookConfiguration en een ValidatingWebhookConfiguration. Vanaf dat moment stuurt elke resource-aanmaak, -update of -verwijdering die aan een policy matcht een AdmissionReview-request naar Kyverno.

De flow:

  1. Een gebruiker of controller dient een resource in bij de API-server.
  2. De API-server stuurt het request door de admission-chain.
  3. Kyverno's mutating webhook gaat als eerste af. Mutate-regels voegen defaults toe, injecteren sidecars of herschrijven velden.
  4. Kyverno's validating webhook gaat daarna af. Validate-regels controleren de (nu mogelijk gemuteerde) resource tegen policycondities. Als een regel faalt en de policy op Enforce staat, wordt het request afgewezen met een duidelijke foutmelding.
  5. Generate-regels maken nieuwe afhankelijke resources (een NetworkPolicy, een ResourceQuota) op de achtergrond nadat een resource is toegelaten.
  6. Image-verificatieregels controleren container-image-signatures en attestations tegen bekende keys of certificaten.

De componenten

Kyverno wordt gedeployd als meerdere controllers, elk met een eigen verantwoordelijkheid:

  • Admission controller ontvangt AdmissionReview-requests en verwerkt validate-, mutate- en image-verificatieregels. Bevat ook de webhook controller die dynamisch configureert welke resources de webhooks onderscheppen, op basis van de policies die op dat moment geinstalleerd zijn.
  • Background controller verwerkt generate-regels en mutate-existing-regels. Die draaien niet inline met het admission-request maar reconcilen asynchroon.
  • Reports controller verzamelt resultaten van admission-events en periodieke achtergrondscans in PolicyReport en ClusterPolicyReport-resources, volgens de Kubernetes Policy WG-rapportagestandaard.

Policyscope: ClusterPolicy vs. Policy

Een ClusterPolicy geldt voor resources in alle namespaces. Een Policy is namespaced en geldt alleen binnen de namespace waar het is aangemaakt. Dit spiegelt het onderscheid tussen Role en ClusterRole in Kubernetes RBAC.

Audit vs. Enforce

Elke validatieregel heeft een failureAction (of het oudere veld validationFailureAction). Zet het op Audit en Kyverno logt overtredingen in PolicyReport-resources zonder iets te blokkeren. Zet het op Enforce en overtredingen worden direct geweigerd op admission-niveau. Met deze tweefasenaanpak kun je policies veilig uitrollen: deploy in Audit-modus, bekijk de rapporten, los overtredingen op, schakel dan over naar Enforce.

Wat Kyverno doet: de vier regeltypen

Validate: wijs resources af die niet aan je standaarden voldoen

Validatie is de meest voorkomende use case. Je definieert condities waaraan resources moeten voldoen, en Kyverno blokkeert of rapporteert overtredingen.

Deze policy vereist dat elke Deployment een app.kubernetes.io/name-label heeft:

# Kyverno 1.17+ (kyverno.io/v1 ClusterPolicy-syntax)
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: require-app-label
spec:
  validationFailureAction: Enforce
  rules:
  - name: check-app-label
    match:
      any:
      - resources:
          kinds:
          - Deployment
    validate:
      message: "Elke Deployment moet een 'app.kubernetes.io/name'-label hebben."
      pattern:
        metadata:
          labels:
            app.kubernetes.io/name: "?*"  # elke niet-lege waarde

Het "?*"-patroon betekent "minstens een karakter." Een Deployment zonder dit label wordt geweigerd met de melding die je hebt gedefinieerd.

Een andere veelgebruikte validatie: privileged containers verbieden. Deze policy implementeert het Pod Security Standards Baseline-profiel:

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: disallow-privileged-containers
  annotations:
    policies.kyverno.io/category: Pod Security Standards (Baseline)
spec:
  validationFailureAction: Enforce
  rules:
  - name: deny-privileged
    match:
      any:
      - resources:
          kinds:
          - Pod
    validate:
      message: "Privileged containers zijn niet toegestaan."
      pattern:
        spec:
          containers:
          - securityContext:
              privileged: "!true"  # mag niet true zijn
          initContainers:
          - securityContext:
              privileged: "!true"

Kyverno levert een complete policybibliotheek met kant-en-klare policies die aansluiten bij de Kubernetes Pod Security Standards op zowel het Baseline- als het Restricted-profielniveau.

Mutate: stel defaults in en injecteer configuratie

Mutate-regels wijzigen resources voordat ze worden toegelaten. Dit is declaratief en idempotent: dezelfde mutatie twee keer toepassen levert hetzelfde resultaat op.

Deze policy voegt een cost-center: engineering-label toe aan elke nieuwe Namespace die er nog geen heeft:

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: add-default-cost-center
spec:
  rules:
  - name: add-cost-center-label
    match:
      any:
      - resources:
          kinds:
          - Namespace
    mutate:
      patchStrategicMerge:
        metadata:
          labels:
            +(cost-center): engineering  # het +-prefix betekent "voeg toe als niet aanwezig"

De +(key)-syntax is een Kyverno-conventie: het veld wordt alleen toegevoegd als het nog niet bestaat. Als de Namespace al een cost-center-label heeft, slaat de mutatie het over.

Sidecar-injectie werkt volgens hetzelfde principe. In plaats van een op maat gemaakte webhook (zoals Istio's sidecar injector), definieer je een Kyverno mutate-policy die een container in de pod-spec patcht wanneer een specifieke annotation aanwezig is.

Generate: maak automatisch resources aan als er iets gebeurt

Generate-regels maken nieuwe Kubernetes-resources aan als reactie op events. De klassieke use case: wanneer een nieuwe Namespace wordt aangemaakt, genereer automatisch een deny-all NetworkPolicy en een standaard ResourceQuota.

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: namespace-defaults
spec:
  rules:
  - name: generate-default-deny-networkpolicy
    match:
      any:
      - resources:
          kinds:
          - Namespace
    generate:
      apiVersion: networking.k8s.io/v1
      kind: NetworkPolicy
      name: default-deny
      namespace: ""
      data:
        spec:
          podSelector: {}         # matcht alle pods in de namespace
          policyTypes:
          - Ingress
          - Egress               # geen allow-regels = alles weigeren

Dit geeft elke nieuwe namespace een zero-trust-startpunt op netwerkniveau. Teams voegen dan hun eigen NetworkPolicies toe om het specifieke verkeer open te zetten dat hun workloads nodig hebben.

Verify images: supply chain-beveiliging

Kyverno kan verifieren dat container-images zijn gesigneerd met een bekende key voordat ze in het cluster draaien. Dit gebruikt het Sigstore cosign-formaat.

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: verify-image-signatures
spec:
  validationFailureAction: Enforce
  rules:
  - name: verify-cosign-signature
    match:
      any:
      - resources:
          kinds:
          - Pod
    verifyImages:
    - imageReferences:
      - "registry.jouwbedrijf.nl/production/*"
      attestors:
      - entries:
        - keys:
            publicKeys: |-
              -----BEGIN PUBLIC KEY-----
              MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE...
              -----END PUBLIC KEY-----

Als een image in het registry.jouwbedrijf.nl/production/-pad niet is gesigneerd met de bijbehorende private key, wordt de pod geweigerd. Kyverno ondersteunt ook keyless verificatie via Fulcio-certificaten en kan in-toto-attestations valideren voor SLSA-herkomstdata.

Resultaten van image-verificatie worden gecacht met een configureerbare TTL, zodat de netwerkoverhead van het controleren van signatures niet bij elke pod-aanmaak opnieuw optreedt.

De evolutie richting CEL

Kyverno 1.17 (uitgebracht in februari 2026) heeft een nieuwe generatie policytypes naar stable (v1) gepromoveerd: ValidatingPolicy, MutatingPolicy, GeneratingPolicy, ImageValidatingPolicy en DeletingPolicy. Deze gebruiken Common Expression Language (CEL) in plaats van Kyverno's oorspronkelijke JMESPath-gebaseerde pattern matching.

Waarom CEL? Kubernetes zelf heeft CEL overgenomen voor ValidatingAdmissionPolicies vanaf Kubernetes 1.26. Door op CEL af te stemmen, kunnen Kyverno-policies direct converteren naar native Kubernetes admission policies, wat vendor lock-in vermindert.

De legacy ClusterPolicy- en Policy-types (met JMESPath) werken nog in Kyverno 1.17, maar zijn officieel deprecated en worden in een toekomstige release verwijderd. De YAML-voorbeelden in dit artikel gebruiken de legacy-syntax omdat die nog het meest gedeployd en gedocumenteerd is, maar nieuwe installaties doen er goed aan de CEL-gebaseerde types te evalueren.

Hoe Kyverno zich verhoudt tot OPA/Gatekeeper

Zowel Kyverno als OPA/Gatekeeper lossen hetzelfde kernprobleem op: policies afdwingen op Kubernetes-resources bij admission. Beide zijn volwassen CNCF-projecten (OPA graduated in 2021, Kyverno in 2026). De keuze hangt af van je team, je stack en wat je nodig hebt naast validatie.

Criterium Kyverno OPA/Gatekeeper
Policytaal YAML (JMESPath of CEL) Rego
Leercurve Laag als je Kubernetes YAML kent Steiler; Rego is een op maat gemaakte taal
Kubernetes-native Policies zijn CRDs; kubectl apply ConstraintTemplates + Constraints (CRDs, maar met Rego erin)
Validatie Ja Ja
Mutatie Ja (ingebouwd) Beperkt (alpha sinds Gatekeeper 3.10)
Resource-generatie Ja Nee
Image-verificatie Ja (cosign, Sigstore) Nee (vereist externe tooling)
Scope buiten Kubernetes Groeiend (JSON/YAML-validatie voor IaC) Breed (API-autorisatie, CI-pipelines, microservices)
CNCF-status Graduated (maart 2026) OPA graduated (januari 2021); Gatekeeper is een subproject

Kies Kyverno als je policybehoeften Kubernetes-gericht zijn, je team YAML beter kent dan een policytaal, en je mutatie, generatie en image-verificatie wilt zonder extra tooling.

Kies OPA/Gatekeeper als je een enkele policy engine nodig hebt voor je hele stack (niet alleen Kubernetes), je team al in Rego heeft geinvesteerd, of je compliance-eisen de fijnmazige logica van Rego vereisen.

Een hybride aanpak is ook mogelijk. Sommige organisaties gebruiken Kyverno voor eenvoudige Kubernetes-admissionpolicies (label-enforcement, securitycontexts, defaults) en OPA voor complexe cross-system autorisatiebeslissingen.

Wat Kyverno niet is

Kyverno vervangt geen RBAC en geen network policies. Het vult ze aan.

  • RBAC regelt wie acties mag uitvoeren op Kubernetes-resources. Kyverno regelt hoe die resources eruitzien als ze worden aangemaakt. Een gebruiker met toestemming om Deployments te maken (via RBAC) kan toch worden geblokkeerd door Kyverno als de Deployment niet aan de policyvereisten voldoet. Maar Kyverno kan niet beperken welke gebruikers toegang hebben; dat is de taak van RBAC.
  • Network policies regelen verkeer tussen pods. Kyverno kan wel automatisch NetworkPolicy-resources genereren, maar het dwingt zelf geen netwerkverkeer af.
  • Pod Security Standards (de ingebouwde Kubernetes admission controller via PodSecurity) dekken een vaste set beveiligingschecks. Kyverno kan dezelfde checks afdwingen plus alles wat je zelf definieert, maar het draait als een externe webhook, niet als een ingebouwde admission-plugin.

Een belangrijk randgeval: de system:masters-groep in Kubernetes omzeilt alle admission webhooks, inclusief Kyverno. Policies gelden niet voor identiteiten in die groep.

Hoe verder

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.