Kyverno
Kyverno is a CNCF-graduated policy engine for Kubernetes. It runs as a dynamic admission webhook plus background controllers, and it validates, mutates, generates and cleans up resources from policies written as Kubernetes YAML with CEL expressions, with no separate policy language to learn. Apache 2.0 and free. It fits clusters that need guardrails such as pod security, required labels and allowed image registries, with results recorded as PolicyReports.
Kyverno is a policy engine for Kubernetes. It sits in the API server's admission path and checks or changes each object before the object is stored. A background scan applies the same policies to objects that already exist. Policies are Kubernetes resources, so they are written, reviewed and delivered with the same tools as the workloads they govern.
What it is
Kyverno ("govern" in Greek) is an Apache 2.0 project started at Nirmata. It joined the CNCF in November 2020, moved to Incubating in July 2022, and graduated in March 2026 after a third-party security audit and a governance review.
The current line is v1.19. v1.19.0 shipped on 20 August 2026 and v1.19.1 on 10 September 2026, and a v1.19.2 release candidate is in testing. The project gives about three months of community patch support per minor. The releases page lists Kubernetes v1.33 to v1.35 as the tested range for 1.19.
v1.19 is a transition release. The 1.19 announcement declares full feature parity between the new CEL-based policy types and the legacy types. It deprecates ClusterPolicy, Policy, CleanupPolicy, ClusterCleanupPolicy and the legacy kyverno.io PolicyException, with removal planned for v1.20 (estimated November 2026; a tracking issue shows the exact scope is still under discussion). The replacements are in the policies.kyverno.io group:
| Legacy rule or type | CEL-based replacement |
|---|---|
validate rule |
ValidatingPolicy |
mutate rule |
MutatingPolicy |
generate rule |
GeneratingPolicy |
verifyImages rule |
ImageValidatingPolicy |
CleanupPolicy |
DeletingPolicy |
kyverno.io PolicyException |
policies.kyverno.io PolicyException |
Each new type also has a namespaced variant, for example NamespacedValidatingPolicy. The CEL types follow the shape of Kubernetes' own ValidatingAdmissionPolicy, so a team that learns one can read the other.
Related projects in the same family: the Kyverno CLI (kyverno apply, kyverno test) runs policies outside a cluster, the kyverno-policies chart ships the Pod Security Standards as ready-made policies, and the optional Reports Server moves report storage out of etcd.
How it works
A Helm install runs four Deployments in a dedicated kyverno namespace:
- Admission controller (required). It receives
AdmissionReviewcallbacks from the API server and runs the policy engine for validation, mutation and exceptions. Its webhook controller rewrites the webhook configurations so that the API server sends only the resource kinds that policies match. A cert renewer keeps the webhook's TLS certificate current. - Background controller. It handles generate rules and mutate-existing rules through intermediate
UpdateRequestresources. - Reports controller. It turns admission reports and background scan reports into
PolicyReportandClusterPolicyReportobjects. - Cleanup controller. It deletes resources that match cleanup (now deleting) policies on a schedule.
Webhooks default to failurePolicy: Fail with a 10-second timeout. If Kyverno cannot answer, the API server rejects the request instead of letting it through. The figure shows the two paths a policy result takes: one at admission time, one for objects that already exist.
Step 1 of 6. A client creates a Pod. Authentication and authorization pass, and mutating webhooks run first.
Admission runs inline on every matching write; the background scan reports on objects that already exist.
Mutation happens in the same admission call, before validation, and generation runs asynchronously in the background controller. Policy exceptions are separate resources that exempt named objects from named policies, so a policy can stay strict while one known workload is excused in review.
When to use it
Reach for it when:
- You need guardrails on every cluster: Pod Security Standards, required labels, allowed image registries, no
latesttags, resource limits present. - You want policies in plain Kubernetes YAML, reviewed in Git and synced with Argo CD like any other manifest.
- You need mutation or generation as well as validation, for example default labels, or a NetworkPolicy and quota created for each new namespace.
- You want image signature and attestation checks (Cosign or Notary) at admission time.
- You want an audit view first: run policies in Audit mode, read the PolicyReports, then switch to Deny.
Skip it when:
- The built-in Pod Security Admission labels cover the whole need. That adds no pods and no webhook.
- A few simple validations are all that is required. Kubernetes' native
ValidatingAdmissionPolicyruns inside the API server with no extra service. - The organization already standardizes on Rego and OPA across services, where Gatekeeper reuses that skill set.
- The cluster cannot tolerate another fail-closed webhook in the write path and the team cannot run it in HA.
At a glance
Core concepts
- Policy type — one CRD per job (
ValidatingPolicy,MutatingPolicy,GeneratingPolicy,ImageValidatingPolicy,DeletingPolicy), cluster-wide or namespaced. - matchConstraints — which API groups, versions, operations and resources a policy applies to, in the same shape as Kubernetes admission policies.
- validations — CEL
expressionplusmessage.messageExpressionbuilds the message in CEL. - validationActions —
Denyblocks,Auditrecords only,Warnreturns a warning to the client. - evaluation —
mode: Kubernetes(default) ormode: JSONfor arbitrary payloads such as a Terraform plan, through the CLI;background.enabledturns on scans of existing objects. - PolicyException — exempts specific resources from specific policies.
- PolicyReport — the standard report CRD (from the Kubernetes policy working group) holding results.
Key facts (v1.19)
| Item | Value |
|---|---|
| Licence | Apache 2.0 |
| Foundation status | CNCF Graduated (2026) |
| Tested Kubernetes | v1.33 to v1.35 |
| Install | Helm chart kyverno/kyverno, dedicated namespace |
| Controllers | admission (required), background, reports, cleanup |
| HA guidance | admission controller at least 2 replicas, 3 per controller for full HA |
| Webhook defaults | failurePolicy: Fail, 10 s timeout (1 to 30 s allowed) |
| Default exclusions | kyverno, kube-system, kube-public namespaces; Events and other system kinds |
| Patch support | about 3 months per minor |
Kyverno vs OPA Gatekeeper
| Aspect | Kyverno | OPA Gatekeeper |
|---|---|---|
| Policy language | YAML with CEL expressions | Rego in ConstraintTemplates |
| Validate | Yes | Yes |
| Mutate | Yes | Yes (Assign, AssignMetadata) |
| Generate resources | Yes | No |
| Image verification | Built in (Cosign, Notary) | Through external data providers |
| Reports | PolicyReport CRDs | Audit results on constraint status |
| Outside Kubernetes | CLI with JSON mode | OPA itself runs anywhere |
How to integrate
Install with Helm
helm repo add kyverno https://kyverno.github.io/kyverno/
helm repo update
# Production: HA replicas per controller
helm install kyverno kyverno/kyverno -n kyverno --create-namespace \
--set admissionController.replicas=3 \
--set backgroundController.replicas=2 \
--set cleanupController.replicas=2 \
--set reportsController.replicas=2
kubectl -n kyverno get deploy
From v1.19 the CRDs come from a kyverno-api chart dependency, still controlled by the crds.install value. Read the upgrade notes before a minor upgrade.
A first validating policy
Start in Audit, read the reports, then move to Deny:
apiVersion: policies.kyverno.io/v1
kind: ValidatingPolicy
metadata:
name: require-environment-label
spec:
validationActions:
- Audit # switch to Deny once reports are clean
evaluation:
background:
enabled: true
matchConstraints:
resourceRules:
- apiGroups: ['']
apiVersions: [v1]
operations: [CREATE, UPDATE]
resources: [pods]
validations:
- message: "label 'environment' is required"
expression: "'environment' in object.metadata.?labels.orValue({})"
kubectl get policyreports -A
kubectl get validatingpolicies
Test policies before they reach a cluster
# Apply a policy to local manifests
kyverno apply ./policies/ --resource ./manifests/
# Run the test suite; fail the CI job on deprecation warnings
kyverno test ./policies/ --warnings-as-errors
The --warnings-as-errors flag is the simple way to find legacy ClusterPolicy objects before v1.20 removes them.
In the GL stack
Kyverno v1.19.1 runs on the beta and prod clusters, two of the three K3s clusters behind builddaily.io, paiddaily.io and the other products.
- What it enforces. Admission and background policies cover pod security, required labels and image registry rules. Admission stops a non-compliant object at write time, and the background scan reports on objects that were already in the cluster.
- Rancher's webhook. Both clusters are imported into Rancher, and Rancher's own admission webhook guards the namespace Pod Security Admission labels. A change to a
pod-security.kubernetes.iolabel needs Rancher'supdatepsapermission, so that part of pod security sits with Rancher and the workload-level rules sit with Kyverno. - Neighbours. Falco watches runtime behaviour on the same two clusters, and Trivy Operator scans running images and configs on beta. Kyverno is the gate at admission time, before either of them sees the workload.
Gotchas
- Legacy types end at v1.19.
ClusterPolicyandPolicystill work but return an admission warning, and thekyverno_deprecated_api_requests_totalcounter records each request that uses them. Thekyverno_legacy_policies_totalgauge counts legacy policies still stored in the cluster. Migrate with the CEL migration guide before v1.20.podSecuritysubrules have no direct equivalent: each Pod Security control becomes one entry inspec.validations. - Storage version moves in v1.20. The
policies.kyverno.iotypes store asv1beta1in 1.19 and move tov1in 1.20. After the upgrade,kyverno migraterewrites stored objects. - Fail-closed by default. With
failurePolicy: Fail, a crashed or unreachable admission controller blocks every write that a policy matches. Run at least two admission replicas and keep thekyvernonamespace excluded so Kyverno can always restart itself. - Kubernetes version range. 1.19 is tested on Kubernetes v1.33 to v1.35. Newer clusters "may work, but are not tested," so test a cluster minor upgrade on a non-production cluster first.
- Report volume. PolicyReports are stored in the cluster datastore. Many policies times many objects means many large objects. The optional Reports Server moves them out.
- 1.19.1 tightens exceptions. It validates CEL match conditions on
PolicyException, deniesglobalContextin namespaced policies, and fixes an exception scope bypass for image verification (GHSA-5cjf-wwfg-pj4c). Exceptions that loaded before may be rejected after the upgrade. - Rancher PSA labels. On Rancher-managed clusters, a Kyverno policy that mutates namespace
pod-security.kubernetes.iolabels is rejected by Rancher's webhook unless the Kyverno service account hasupdatepsa. Granting that verb lets Kyverno set privileged PSA levels, which Rancher's docs flag as a risk.
Risks
- Write-path dependency. Kyverno is in the API path for every matched resource. A slow policy or a bad deploy of Kyverno affects every team on the cluster.
- Migration churn. The move from the legacy types to the CEL types is a rewrite for any large policy library, and the removal date is an estimate.
- Project health. CNCF graduation came with a third-party audit and a governance review, and the project releases roughly every quarter. Nirmata offers commercial support but does not own the project.
- Lock-in. Low. The CEL types are close to Kubernetes' native admission policies, and PolicyReport is a shared format. Generate and image-verify rules have no native equivalent.
- Privilege. The background controller needs write access to every resource kind that it generates or mutates. Review its ClusterRoles when adding generate policies.
Alternatives
- OPA Gatekeeper — choose it when Rego and OPA are already the standard for policy across services.
- ValidatingAdmissionPolicy (built in) — choose it for a few CEL validations with no extra service in the cluster.
- Pod Security Admission (built in) — choose it when namespace-level Pod Security Standards are the only requirement.
- Kubewarden — choose it for policies compiled to WebAssembly from general-purpose languages, a CNCF project started at SUSE that installs from Rancher.
Related
- Rancher and K3s — the management plane whose webhook guards PSA labels, and the clusters Kyverno runs on.
- Falco and Trivy — runtime detection and image scanning beside the admission gate.
- Distribution registry — the private registry in the stack, relevant to image registry rules.
- Security layer — the overview of the services Kyverno sits beside.
- cert-manager and Prometheus — webhook certificates elsewhere in the stack, and the metrics Kyverno exposes.
- Official: Kyverno docs, kyverno/kyverno releases, Kyverno 1.19 announcement, Rancher webhook reference.
