Search across all documentation pages
background reporting for existing objects.:latest) without learning Rego.Install Kyverno with Helm, then apply a ClusterPolicy in audit mode, watch reports, and switch to enforce.
helm repo add kyverno https://kyverno.github.io/kyverno/
helm install kyverno kyverno/kyverno -n kyverno --create-namespacekubectl apply -f require-limits.yaml
kubectl get clusterpolicy
kubectl get policyreport -AThis ClusterPolicy requires every container to set CPU and memory limits and to define a readiness probe. It starts in Audit so it does not break existing workloads.
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-limits-and-probes
spec:
validationFailureAction: Audit # switch to Enforce after review
background: true
rules:
- name: require-resource-limits
match:
any:
- resources:
kinds: ["Pod"]
validate:
message: "CPU and memory limits are required."
pattern:
spec:
containers:
- resources:
limits:
memory: "?*"
cpu: "?*"
- name: require-readiness-probe
match:
any:
- resources:
kinds: ["Pod"]
validate:
message: "A readinessProbe is required."
pattern:
spec:
containers:
- readinessProbe:
"?*": "?*"Apply it, create a Deployment without limits, and inspect the generated report.
kubectl apply -f require-limits-and-probes.yaml
kubectl get policyreport -A -o wideOnce reports are clean, flip validationFailureAction to Enforce and reapply. Now violating writes are rejected at admission time.
A single policy can hold many rules, and each rule is one of four types.
validate accepts or rejects. mutate patches incoming objects. generate creates companion resources. verifyImages checks signatures and attestations.
The pattern block is a declarative overlay: ?* means "any non-empty value" and * means "any value including empty."
For richer logic, Kyverno supports deny conditions and CEL expressions, letting you compare fields or count elements.
validate:
message: "Image must not use the latest tag."
deny:
conditions:
any:
- key: "{{ images.containers.*.tag }}"
operator: AnyIn
values: ["latest", ""]Mutate rules add defaults so authors do not have to. This example injects a default runAsNonRoot.
- name: default-non-root
match:
any:
- resources:
kinds: ["Pod"]
mutate:
patchStrategicMerge:
spec:
securityContext:
runAsNonRoot: trueWith background: true, Kyverno evaluates existing objects on a schedule and writes PolicyReport and ClusterPolicyReport results.
This surfaces drift in workloads created before the policy existed, without blocking them.
validationFailureAction: Audit reports only; Enforce rejects at admission. You can also set actions per rule with validationFailureActionOverrides scoped by namespace.
This lets you enforce strictly in payments while auditing in sandbox from one policy.
Generate rules create objects automatically when a trigger appears, such as a default NetworkPolicy or ResourceQuota for every new namespace.
- name: default-deny-netpol
match:
any:
- resources:
kinds: ["Namespace"]
generate:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
name: default-deny
namespace: "{{ request.object.metadata.name }}"
synchronize: true
data:
spec:
podSelector: {}
policyTypes: ["Ingress", "Egress"]With synchronize: true, Kyverno keeps the generated object in step with the rule and recreates it if someone deletes it.
Kyverno rejects writes only through its webhook, so if the Kyverno Pods are unhealthy, enforcement stops or writes block depending on the webhook failurePolicy.
Run Kyverno with multiple replicas and resource requests so it stays available under load.
pattern matching is easy to get subtly wrong: ?* requires a non-empty value, but a field set to 0 or false still counts as present. Test edge cases.
Policies apply to the object as the API server sees it after other mutations. If another mutating webhook runs later, your validate rule may see different data than the final object; keep policy ordering in mind.
Background scan does not enforce - it only reports. Do not assume a clean report means writes are blocked; check validationFailureAction.
Pod-level policies do not automatically cover Pod controllers. Kyverno auto-generates rules for Deployments, Jobs, and similar from a Pod rule, but confirm autogen is enabled if you disabled it.
OPA Gatekeeper uses Rego and constraint templates; pick it when you need a full policy language and a central constraint library.
ValidatingAdmissionPolicy (CEL) is built into the API server with no add-on to run; pick it for simple, high-volume checks where you want zero extra infrastructure.
Pod Security Admission covers the specific Pod Security Standards with no engine at all; use it as a baseline and layer Kyverno on top for custom rules.
Do I need to learn a new language for Kyverno? No. Policies are YAML with pattern overlays and optional CEL expressions, which is why teams often start here.
Can Kyverno fix existing non-compliant workloads? It can report them via background scans and mutate them on their next write, but admission never rewrites already-stored objects retroactively.
How do I test policies before applying to a cluster? Use the kyverno CLI's apply and test commands against manifests in CI, then dry-run against a real cluster.
Does a Pod rule cover Deployments? Yes, through Kyverno's autogen feature, which derives equivalent rules for Pod controllers unless you disable it.
What happens if Kyverno is down? Behavior follows the webhook failurePolicy. With Fail, matching writes are blocked; with Ignore, they pass unchecked.
Can one policy enforce in some namespaces and audit in others? Yes, with validationFailureActionOverrides keyed by namespace selectors.
Stack versions: This page was written for Kubernetes 1.36.2, Docker Engine 29.6.1 (BuildKit default), containerd (CRI runtime on nodes), Helm 3, Compose v2, Argo CD (latest - verify at build), and Gateway API (GA - verify controller support at build).
Reviewed by Chris St. John·Last updated Jul 16, 2026