Regels die alleen in documentatie bestaan worden niet gevolgd. Regels die door computers worden afgedwongen wel.

Kubernetes geeft je ongelofelijke flexibiliteit. Elk team kan deployen wat ze willen, geconfigureerd zoals ze willen. Deze vrijheid wordt chaos zonder vangrails.

Kyverno is een policy engine voor Kubernetes. Het valideert, muteert en genereert resources gebaseerd op policies die je definieert — als Kubernetes-native YAML.

Waarom Kyverno?

Er zijn meerdere policy engines: Open Policy Agent (OPA) met Gatekeeper, Kyverno, Kubewarden. Ik koos Kyverno omdat:

  1. Native YAML — Geen Rego, geen nieuwe taal om te leren
  2. Validatie + Mutatie + Generatie — Eén tool voor alle policy types
  3. Declaratief — Policies zijn Kubernetes resources
  4. GitOps-vriendelijk — Beheer policies zoals elk ander manifest

OPA/Gatekeeper is krachtig maar vereist het leren van Rego. Kyverno laat je direct policies schrijven als je YAML kent.

Kernconcepten

Kyverno policies kunnen drie dingen doen:

Valideren — Resources blokkeren die niet aan criteria voldoen

"Je kunt niet deployen zonder resource limits"

Muteren — Resources automatisch aanpassen

"Alle pods krijgen automatisch dit label"

Genereren — Nieuwe resources maken wanneer anderen worden aangemaakt

"Elke namespace krijgt een default NetworkPolicy"

Kyverno Installeren

helm repo add kyverno https://kyverno.github.io/kyverno/
helm repo update

helm install kyverno kyverno/kyverno \
  --namespace kyverno \
  --create-namespace

Voor GitOps met ArgoCD:

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: kyverno
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://kyverno.github.io/kyverno/
    chart: kyverno
    targetRevision: 3.1.4
    helm:
      values: |
        admissionController:
          replicas: 3
        backgroundController:
          replicas: 2
        cleanupController:
          replicas: 2
        reportsController:
          replicas: 2
  destination:
    server: https://kubernetes.default.svc
    namespace: kyverno
  syncPolicy:
    automated:
      prune: true
      selfHeal: true

Je Eerste Policy: Vereis Labels

Een klassieke start policy — vereis dat alle pods specifieke labels hebben:

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: require-labels
spec:
  validationFailureAction: Enforce
  rules:
    - name: require-team-label
      match:
        any:
          - resources:
              kinds:
                - Pod
      validate:
        message: "Het label 'team' is verplicht."
        pattern:
          metadata:
            labels:
              team: "?*"

Probeer nu een pod te maken zonder het label:

kubectl run test --image=nginx
# Error: Het label 'team' is verplicht.

Validation Failure Actions

Twee modes:

Enforce — Blokkeer niet-compliant resources (productie)

validationFailureAction: Enforce

Audit — Sta toe maar rapporteer non-compliance (testen)

validationFailureAction: Audit

Begin met Audit om te zien wat zou falen, schakel dan over naar Enforce.

Veelvoorkomende Validatie Policies

Vereis Resource Limits

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: require-resource-limits
spec:
  validationFailureAction: Enforce
  rules:
    - name: require-limits
      match:
        any:
          - resources:
              kinds:
                - Pod
      validate:
        message: "CPU en memory limits zijn verplicht."
        pattern:
          spec:
            containers:
              - resources:
                  limits:
                    memory: "?*"
                    cpu: "?*"

Verbied Privileged Containers

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: disallow-privileged
spec:
  validationFailureAction: Enforce
  rules:
    - name: deny-privileged
      match:
        any:
          - resources:
              kinds:
                - Pod
      validate:
        message: "Privileged containers zijn niet toegestaan."
        pattern:
          spec:
            containers:
              - securityContext:
                  privileged: false

Verbied Latest Tag

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: disallow-latest-tag
spec:
  validationFailureAction: Enforce
  rules:
    - name: require-image-tag
      match:
        any:
          - resources:
              kinds:
                - Pod
      validate:
        message: "Gebruik van ':latest' tag is niet toegestaan. Specificeer een versie tag."
        pattern:
          spec:
            containers:
              - image: "!*:latest"

Beperk Image Registries

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: restrict-registries
spec:
  validationFailureAction: Enforce
  rules:
    - name: allowed-registries
      match:
        any:
          - resources:
              kinds:
                - Pod
      validate:
        message: "Images moeten van goedgekeurde registries komen."
        pattern:
          spec:
            containers:
              - image: "registry.example.com/* | gcr.io/my-project/*"

Mutatie Policies

Pas resources automatisch aan om standaarden af te dwingen:

Voeg Default Labels Toe

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: add-default-labels
spec:
  rules:
    - name: add-managed-by
      match:
        any:
          - resources:
              kinds:
                - Pod
                - Deployment
                - Service
      mutate:
        patchStrategicMerge:
          metadata:
            labels:
              managed-by: kyverno
              environment: "{{request.namespace}}"

Voeg Default Security Context Toe

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: add-security-context
spec:
  rules:
    - name: add-run-as-nonroot
      match:
        any:
          - resources:
              kinds:
                - Pod
      mutate:
        patchStrategicMerge:
          spec:
            securityContext:
              runAsNonRoot: true
              seccompProfile:
                type: RuntimeDefault

Voeg Image Pull Secrets Toe

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: add-imagepullsecret
spec:
  rules:
    - name: add-registry-secret
      match:
        any:
          - resources:
              kinds:
                - Pod
      mutate:
        patchStrategicMerge:
          spec:
            imagePullSecrets:
              - name: registry-credentials

Generatie Policies

Maak automatisch resources wanneer anderen worden aangemaakt:

Default NetworkPolicy per Namespace

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: generate-default-networkpolicy
spec:
  rules:
    - name: generate-deny-all
      match:
        any:
          - resources:
              kinds:
                - Namespace
      exclude:
        any:
          - resources:
              namespaces:
                - kube-system
                - kyverno
      generate:
        apiVersion: networking.k8s.io/v1
        kind: NetworkPolicy
        name: default-deny
        namespace: "{{request.object.metadata.name}}"
        data:
          spec:
            podSelector: {}
            policyTypes:
              - Ingress
              - Egress

Elke nieuwe namespace krijgt een default-deny NetworkPolicy. Teams moeten expliciet traffic toestaan.

Default ResourceQuota per Namespace

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: generate-resourcequota
spec:
  rules:
    - name: generate-quota
      match:
        any:
          - resources:
              kinds:
                - Namespace
      exclude:
        any:
          - resources:
              namespaces:
                - kube-system
                - kyverno
      generate:
        apiVersion: v1
        kind: ResourceQuota
        name: default-quota
        namespace: "{{request.object.metadata.name}}"
        data:
          spec:
            hard:
              requests.cpu: "4"
              requests.memory: 8Gi
              limits.cpu: "8"
              limits.memory: 16Gi
              persistentvolumeclaims: "10"

Variabelen Gebruiken

Kyverno ondersteunt JMESPath expressies voor dynamische waarden:

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: add-namespace-label
spec:
  rules:
    - name: add-ns-to-pods
      match:
        any:
          - resources:
              kinds:
                - Pod
      mutate:
        patchStrategicMerge:
          metadata:
            labels:
              namespace: "{{request.namespace}}"
              created-at: "{{time_now_utc()}}"

Nuttige variabelen:

  • {{request.namespace}} — Namespace van de resource
  • {{request.object.metadata.name}} — Naam van de resource
  • {{request.userInfo.username}} — Gebruiker die het request maakte
  • {{time_now_utc()}} — Huidige timestamp

Resources Uitsluiten

Pas policies niet toe op systeem componenten:

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: require-labels
spec:
  rules:
    - name: require-team-label
      match:
        any:
          - resources:
              kinds:
                - Pod
      exclude:
        any:
          - resources:
              namespaces:
                - kube-system
                - kube-public
                - kyverno
          - subjects:
              - kind: ServiceAccount
                name: system:*

Policy Reports

Kyverno genereert policy reports die compliance tonen:

kubectl get policyreport -A
kubectl get clusterpolicyreport

Voorbeeld report:

apiVersion: wgpolicyk8s.io/v1alpha2
kind: PolicyReport
metadata:
  name: polr-ns-default
  namespace: default
results:
  - message: "validation rule 'require-team-label' passed."
    policy: require-labels
    result: pass
    source: kyverno
  - message: "validation rule 'require-limits' failed."
    policy: require-resource-limits
    result: fail
    source: kyverno

Integreer met Prometheus voor alerting op policy violations:

# ServiceMonitor voor Kyverno metrics
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: kyverno
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: kyverno
  endpoints:
    - port: metrics

Policy Sets

Kyverno onderhoudt curated policy sets:

# Installeer Pod Security Standards (Baseline)
kubectl apply -f https://raw.githubusercontent.com/kyverno/policies/main/pod-security/baseline/

# Installeer Pod Security Standards (Restricted)
kubectl apply -f https://raw.githubusercontent.com/kyverno/policies/main/pod-security/restricted/

Deze implementeren Kubernetes Pod Security Standards als Kyverno policies.

Mijn Productie Policy Set

Hier zijn de policies die ik op elk cluster draai:

# require-probes.yaml
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: require-probes
spec:
  validationFailureAction: Enforce
  rules:
    - name: require-readiness-probe
      match:
        any:
          - resources:
              kinds:
                - Deployment
      exclude:
        any:
          - resources:
              namespaces:
                - kube-system
                - kyverno
      validate:
        message: "Readiness probe is verplicht voor alle deployments."
        pattern:
          spec:
            template:
              spec:
                containers:
                  - readinessProbe:
                      "?*": "?*"
---
# disallow-default-namespace.yaml
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: disallow-default-namespace
spec:
  validationFailureAction: Enforce
  rules:
    - name: deny-default
      match:
        any:
          - resources:
              kinds:
                - Pod
                - Deployment
                - Service
              namespaces:
                - default
      validate:
        message: "Gebruik van de 'default' namespace is niet toegestaan."
        deny: {}
---
# require-requests.yaml
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: require-requests
spec:
  validationFailureAction: Enforce
  rules:
    - name: require-cpu-memory-requests
      match:
        any:
          - resources:
              kinds:
                - Pod
      exclude:
        any:
          - resources:
              namespaces:
                - kube-system
      validate:
        message: "CPU en memory requests zijn verplicht."
        pattern:
          spec:
            containers:
              - resources:
                  requests:
                    memory: "?*"
                    cpu: "?*"

Policies Testen

Gebruik de Kyverno CLI om policies te testen voor het toepassen:

# Installeer CLI
brew install kyverno

# Test policy tegen een resource
kyverno apply policy.yaml --resource pod.yaml

# Test alle policies in een directory
kyverno apply ./policies/ --resource ./manifests/

Maak een test suite:

# test/values.yaml
policies:
  - policy.yaml
resources:
  - resources/valid-pod.yaml
  - resources/invalid-pod.yaml
results:
  - policy: require-labels
    resource: valid-pod.yaml
    result: pass
  - policy: require-labels
    resource: invalid-pod.yaml
    result: fail

Draai tests:

kyverno test ./test/

Background Scanning

Kyverno kan bestaande resources scannen, niet alleen nieuwe:

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: audit-existing
spec:
  validationFailureAction: Audit
  background: true  # Enable background scanning
  rules:
    - name: check-labels
      match:
        any:
          - resources:
              kinds:
                - Pod
      validate:
        message: "Label 'team' ontbreekt."
        pattern:
          metadata:
            labels:
              team: "?*"

Dit genereert reports voor alle bestaande pods, niet alleen nieuwe.

Uitzonderingen

Soms moet je policies omzeilen:

apiVersion: kyverno.io/v1
kind: PolicyException
metadata:
  name: allow-privileged-monitoring
  namespace: monitoring
spec:
  exceptions:
    - policyName: disallow-privileged
      ruleNames:
        - deny-privileged
  match:
    any:
      - resources:
          kinds:
            - Pod
          namespaces:
            - monitoring
          names:
            - node-exporter*

Documenteer waarom elke uitzondering bestaat. Uitzonderingen zouden zeldzaam moeten zijn.

Integratie met CI/CD

Valideer manifests in je pipeline voordat ze het cluster bereiken:

# .gitlab-ci.yml
validate-policies:
  stage: test
  image: ghcr.io/kyverno/kyverno-cli:latest
  script:
    - kyverno apply ./policies/ --resource ./k8s/
  rules:
    - if: $CI_MERGE_REQUEST_ID

Vang policy violations voor merge, niet tijdens deployment.

Waarom Dit Ertoe Doet

Policies zijn documentatie die zichzelf afdwingt.

Zonder policy engines:

  • Standaarden bestaan in wiki’s die niemand leest
  • Reviews vangen issues soms, inconsistent
  • Non-compliance accumuleert stilletjes

Met Kyverno:

  • Standaarden zijn code, geversioned in Git
  • Afdwinging is automatisch, direct
  • Violations zijn zichtbaar in reports

Dit is low-friction governance. Niet omdat het minder streng is, maar omdat compliance automatisch gebeurt. Developers hoeven niet elke regel te onthouden — het systeem onthoudt het voor hen.


De beste policies zijn degene waar je nooit over hoeft na te denken. Kyverno verandert je Kubernetes standaarden in zelf-afdwingende code.