KubeCon India 2026 (Mumbai) — Day 1 Deep Dives

06 · The Kyverno Five — Policy-as-Code, Boarding to Production

Deep dive 6 of 17 · Security, policy & identity

Jun 18, 2026 · conferences · 19 min read · 4400 words intermediate

The Kyverno Five — policy-as-code from check-in to turnaround.

conferences kubecon kyverno policy-as-code security

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 wrongThe consequence
Unsigned images slip inanyone's container can board — no provenance, no trust.
Missing labels & defaultsnothing is tagged or owned — chaos for cost, ops, and security.
New namespaces, no guardrailstenants land with nothing in place — no quotas, secrets, or NetworkPolicies.
Stale jobs & configs pile upthe 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

A resource's journey through the Kyverno Five 1 · Mutatingcheck-in: shape 2 · ImageValidatingsecurity: verify 3 · Validatinggate: allow/deny 4 · Generatingground: provision 5 · Deletingturnaround: clear

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"}]
The philosophy in one line: fix it for them — don't reject them. Mutation is the friendliest form of governance: instead of bouncing a developer's deployment for a missing label, you add it. Most "compliance" can be achieved by quietly completing resources rather than refusing them, which keeps developers moving.

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])
This is the cure for "new namespaces, no guardrails." Every new tenant is born with guardrails — a default-deny NetworkPolicy, a resource quota, an image-pull secret cloned in — without anyone remembering to apply them. It's the policy-as-code version of the toleration-injection guardrail from the shared-first platforms talk: make the safe state automatic.

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:

PrincipleWhat it means
One languagePolicies are written in CEL — the same expression language Kubernetes itself adopted for admission. No bespoke DSL to learn.
Same runwaysValidating & Mutating policies compile to native admission controllers — the same machinery the API server already runs.
No turf warThey work with RBAC and the API server, not around them — policy complements authorization, it doesn't replace it.
Why CEL matters here. Kubernetes standardized on CEL for its built-in ValidatingAdmissionPolicy (the very feature the IBM operators talk used). By writing policies in the same language, Kyverno gives you a richer, lifecycle-spanning toolkit without making you learn something that diverges from the platform. Your validation expressions look the same whether they live in a native VAP or a Kyverno ValidatingPolicy.

The full lifecycle, one team

Mapped to the airport, the five policies cover a resource from arrival to departure to cleanup:

Policy typeAirport crewJob
MutatingPolicyCheck-inModify resources to meet your standards.
ImageValidatingPolicySecurityEnsure only trusted images are deployed.
ValidatingPolicyBoarding gateCheck and block non-compliant resources.
GeneratingPolicyGround crewAutomate creation of companion resources.
DeletingPolicyTurnaroundClean 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

← prev: beyond the primary CR next: root without risk →
© cvam — written in plaintext, served warm