Deep dive 6 of the KubeCon Mumbai 2026 series. Neha Jaju (Senior Software Engineer, Nirmata) used a single sustained metaphor — a busy airport — to make the five Kyverno policy types click. A cluster is an airport; thousands of workloads board and depart every minute; and just as an airport runs on specialist crews (check-in, security, boarding gate, ground crew, turnaround), Kyverno gives you exactly five policy types that own the full resource lifecycle: MutatingPolicy, ImageValidatingPolicy, ValidatingPolicy, GeneratingPolicy, and DeletingPolicy. All written in CEL, all compiling to native Kubernetes admission control.
This is the first of the security cluster, and it pairs beautifully with deep dive 05: that talk ended on Validating Admission Policies enforced at the API server; this one is the full policy-as-code platform built on the same admission foundation. Where DD05 was one operator protecting its own resources, Kyverno is cluster-wide governance for everything.
Every cluster is a busy airport
The framing: thousands of workloads arrive and depart every minute, and without a crew coordinating it, four things go wrong — fast:
| What goes wrong | The consequence |
|---|---|
| Unsigned images slip in | anyone's container can board — no provenance, no trust. |
| Missing labels & defaults | nothing is tagged or owned — chaos for cost, ops, and security. |
| New namespaces, no guardrails | tenants land with nothing in place — no quotas, secrets, or NetworkPolicies. |
| Stale jobs & configs pile up | the gates never get cleared — you pay for zombies. |
Kyverno, the framing goes, is your specialized ground crew for Kubernetes safety — and crucially, not a single hero but a brigade, each crew owning one job, handed off in sequence from check-in to take-off and back. Each crew maps to exactly one Kyverno policy type. So the talk walks the whole journey of a resource through five gates.
The five policy types — the resource lifecycle
Fig 1 — shape it, verify the image, allow/deny, provision companions, then clean up. Full lifecycle.
1 · MutatingPolicy — the check-in desk
Shapes each resource on the way in: adds labels, defaults, sidecars. The check-in desk tags your bags and prints your boarding pass so you leave flight-ready.
apiVersion: policies.kyverno.io/v1
kind: MutatingPolicy
metadata: { name: add-default-labels }
spec:
matchConstraints:
resourceRules:
- resources: ["deployments"]
operations: ["CREATE","UPDATE"]
mutations: # add what's missing
- patchType: JSONPatch
jsonPatch:
expression: >-
[JSONPatch{op:"add", path:"/metadata/labels/team", value:"pay"}]
2 · ImageValidatingPolicy — security & passport control
Verifies image signatures and provenance before anything runs. Like checking your passport is genuine: no valid ID, no entry.
apiVersion: policies.kyverno.io/v1
kind: ImageValidatingPolicy
metadata: { name: verify-signatures }
spec:
matchImageReferences: # which images
- glob: "ghcr.io/myorg/*"
attestors: # who we trust
- name: cosign
cosign:
keyless:
identities:
- issuer: "https://token.actions..."
validations: # must be signed
- expression: >-
images.containers.map(i, verifyImageSignatures(i,[attestors.cosign])>0).all(v, v)
Prove the image is who it claims to be. This is supply-chain security at admission — keyless Cosign verification tied to a trusted OIDC issuer (e.g. a GitHub Actions identity), so only images your pipeline actually built and signed can run. Note this is its own dedicated policy kind, separate from generic validation, because image verification has special machinery (registries, attestors, signatures).
3 · ValidatingPolicy — the boarding gate
The gatekeeper: allow or deny the resource against the rules. Valid boarding pass for this flight? You're on. If not, you're turned away at the door.
apiVersion: policies.kyverno.io/v1
kind: ValidatingPolicy
metadata: { name: require-labels }
spec:
matchConstraints:
resourceRules:
- resources: ["pods"]
operations: ["CREATE","UPDATE"]
validations: # the gate
- expression: >-
has(object.metadata.labels.app) && has(object.metadata.labels.version)
message: "Pods need app + version labels"
The guardrail at the door. This is the classic admission-control deny: a hard requirement enforced before the resource is admitted. Pair it with the MutatingPolicy above and you get a humane system — mutation fills in what it safely can, validation rejects only what it genuinely must.
4 · GeneratingPolicy — the ground crew
On each new namespace, provision its companions — secrets, quotas, NetworkPolicies. Every new flight gets fuel, catering, and baggage carts staged automatically, before it's needed.
apiVersion: policies.kyverno.io/v1
kind: GeneratingPolicy
metadata: { name: clone-pull-secret }
spec:
matchConstraints: # trigger: new namespace
resourceRules:
- resources: ["namespaces"]
operations: ["CREATE"]
generate: # provision it
- expression: generator.Apply(variables.ns, [variables.src])
5 · DeletingPolicy — the turnaround crew
On a schedule, retire what's done: old jobs, stale configs, expired clutter. Once a flight lands, the crew clears the cabin and frees the gate for the next departure.
apiVersion: policies.kyverno.io/v1
kind: DeletingPolicy
metadata: { name: cleanup-completed-jobs }
spec:
schedule: "0 1 * * *" # nightly at 1 AM
matchConstraints:
resourceRules:
- resources: ["jobs"]
operations: ["*"]
conditions: # only finished ones
- name: isOld
expression: >-
time.now() - timestamp(object.metadata.creationTimestamp) > duration("72h")
Stop paying for zombies. Completed jobs, expired configs, and stale resources accumulate silently and cost money and clutter. A scheduled DeletingPolicy is the janitor that keeps the cluster (and the bill) clean — the one lifecycle stage most governance tools forget.
Flying in formation with Kubernetes
The closing argument was about how Kyverno fits the platform, and it's the part that matters for adoption. The Kyverno Five don't fight Kubernetes — they fly in formation with it:
| Principle | What it means |
|---|---|
| One language | Policies are written in CEL — the same expression language Kubernetes itself adopted for admission. No bespoke DSL to learn. |
| Same runways | Validating & Mutating policies compile to native admission controllers — the same machinery the API server already runs. |
| No turf war | They work with RBAC and the API server, not around them — policy complements authorization, it doesn't replace it. |
The full lifecycle, one team
Mapped to the airport, the five policies cover a resource from arrival to departure to cleanup:
| Policy type | Airport crew | Job |
|---|---|---|
| MutatingPolicy | Check-in | Modify resources to meet your standards. |
| ImageValidatingPolicy | Security | Ensure only trusted images are deployed. |
| ValidatingPolicy | Boarding gate | Check and block non-compliant resources. |
| GeneratingPolicy | Ground crew | Automate creation of companion resources. |
| DeletingPolicy | Turnaround | Clean up stale or unneeded resources. |
The summary line ties it together: "Kyverno is the airport operations team making sure every resource is trusted, compliant, correctly tagged, supported, and eventually cleared out." That's the pitch — not a single gate, but a coordinated crew owning the whole lifecycle.
FAQ
Why a separate ImageValidatingPolicy instead of just ValidatingPolicy?
Image verification needs specialized machinery — resolving image references, talking to registries, evaluating attestors and signatures (e.g. keyless Cosign tied to an OIDC issuer). Splitting it into its own kind keeps generic validation simple and gives supply-chain checks first-class support.
Mutate or validate — which should I reach for?
Prefer mutation when you can safely complete the resource (add a missing label, inject a default, attach a sidecar) — it keeps developers unblocked. Reserve validation (hard deny) for things you genuinely cannot auto-fix and must not allow, like an unsigned image or a privileged pod.
What does GeneratingPolicy give me that an init script doesn't?
It's declarative and event-driven: the moment a namespace is created, its companions (NetworkPolicy, quota, pull secret) are generated and kept in sync — no human step, no drift. New tenants are born compliant rather than retrofitted.
Is this the same Kyverno I used a few years ago?
The lifecycle idea is the same, but these are the newer CEL-based policy kinds under policies.kyverno.io/v1 (MutatingPolicy, ValidatingPolicy, ImageValidatingPolicy, GeneratingPolicy, DeletingPolicy), aligned with Kubernetes' own CEL admission direction — "same runways" as the platform.
Takeaways
- Five policy types cover the whole resource lifecycle — shape, verify-image, allow/deny, provision, clean up.
- Mutate before you reject. Fix resources for developers where you safely can; deny only what you must.
- Verify image provenance at admission with keyless Cosign — only pipeline-signed images board.
- Generate guardrails on namespace creation so every tenant is born compliant.
- Schedule cleanup — a DeletingPolicy stops you paying for zombies.
- Fly in formation: CEL + native admission + RBAC-friendly means Kyverno extends the platform instead of fighting it.
Next in the series — Deep dive 07: Root Without Risk, which moves from cluster-wide policy to the privilege model of individual workloads.
References
- KubeCon Mumbai 2026 — Day 1 index · the rest of the series
- Kyverno · Kyverno docs · the five policy types and CEL syntax
- Cosign / Sigstore · keyless image signing & verification
- CEL in Kubernetes · the shared expression language