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:
- Native YAML — Geen Rego, geen nieuwe taal om te leren
- Validatie + Mutatie + Generatie — Eén tool voor alle policy types
- Declaratief — Policies zijn Kubernetes resources
- 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.
