Why another policy engine
Pod Security Admission has only three fixed levels. Organisations usually need more: "images only from registry.example.com", "every Deployment has a team label", "no latest tag", "images must be signed". Kyverno (a CNCF project) does this with policies written in YAML, with no Rego to learn.
helm repo add kyverno https://kyverno.github.io/kyverno/
helm install kyverno kyverno/kyverno -n kyverno --create-namespace
Four rule types
| Type | What it does | Example |
|---|---|---|
| validate | Block or report violating objects | Ban the latest image tag |
| mutate | Change an object before it is stored | Add imagePullPolicy: Always or default labels |
| generate | Create companion objects | A default-deny NetworkPolicy for each new namespace |
| verifyImages | Check cosign signatures and attestations | Only run images signed by example-org's pipeline |
A validate example
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: restrict-registries
spec:
validationFailureAction: Audit # switch to Enforce when ready
background: true
rules:
- name: only-internal-registry
match:
any:
- resources: { kinds: [Pod] }
validate:
message: "Images must come from registry.example.com"
pattern:
spec:
containers:
- image: "registry.example.com/*"
Kyverno automatically extends Pod rules to Deployments, StatefulSets, Jobs and so on (auto-gen), so the error appears as soon as you kubectl apply the Deployment rather than silently at the ReplicaSet.
Audit first, then Enforce
flowchart LR P["New policy"] --> A["Audit<br/>writes PolicyReports"] A --> R["Review violations, fix workloads"] R --> E["Enforce<br/>block on create"]
kubectl get clusterpolicy
kubectl get policyreport -A
kubectl kyverno apply restrict-registries.yaml --resource deploy.yaml # try offline with the CLI
background: true makes Kyverno scan existing resources too and write PolicyReports. The community Kyverno policies library includes Pod Security Standards, best practices and many other samples.
Kyverno or Gatekeeper
| Kyverno | OPA Gatekeeper | |
|---|---|---|
| Language | YAML, JMESPath | Rego |
| Mutate, generate | Built in | Limited mutation, no generate |
| Reuse outside K8s | Mostly Kubernetes | Rego shared with Terraform, APIs |
Traps: turning on Enforce straight away on a running cluster; forgetting to exclude system namespaces such as kube-system, breaking the CNI or Kyverno itself; a webhook with failurePolicy: Fail and a single Kyverno replica, so nothing can be created when that Pod dies.