Where does Kyverno live in your organization? I don’t mean which cluster! On which team’s slide deck does it show up? Whose budget line?
For most companies I’ve talked to, the answer is security. Kyverno is evaluated alongside OPA/Gatekeeper, approved by the security team, deployed with a bundle of Pod Security Standard policies, and then… mostly sits there, blocking the occasional root container.
Meanwhile, the teams actually getting interesting value out of Kyverno are the ones doing things with it that make me stop and take notes. These are almost never security teams. They are platform teams. And I don’t think that’s a coincidence. I think we’ve filed Kyverno in the wrong mental category, and that miscategorization is costing us access to most of what the tool can do.
I’ve been circling this observation for a while. My first Kyverno conference talk, back at KCD Munich 2023, was literally titled “Securing Your Kubernetes Workloads with Kyverno” — I was filing it in the security drawer myself. Three years of production work later, my talks are about governance, CEL, and platform self-service, and my post on the Platform Engineering blog argued that Kyverno has outgrown “policy engine” as a description entirely. This post is me finally putting the underlying claim in one sentence, and it’s the opening argument of a longer series on policy-driven platform engineering: Kyverno is a platform primitive. Not a security tool that platform teams happen to use. A building block for platforms, in the same sense that Pods and Services are building blocks, that happens to also be useful for security.
The problem with the security framing
Let me be clear about what I’m not saying. Kyverno absolutely does security work. It blocks insecure configs, it enforces PSS, it verifies image signatures. If your CISO asks whether it helps with compliance, the answer is yes, genuinely.
But “security tool” carries a specific mental model with it: policy as a gate. Something bad shows up, the gate stops it. The primary verb is deny. Success gets measured in blocked deployments.
Now look at what Kyverno actually does. Four things: validate, mutate, generate, verify images. Only the first one fits the gate model. Mutation changes resources on their way into the cluster. Generation creates entirely new resources in response to things happening. Image verification is about establishing trust more than blocking threats, if you squint.
Three out of four verbs are constructive. They add things, change things, build things. And yet if you look at how most organizations deploy Kyverno, it’s validation policies wall to wall. That’s the security framing expressing itself in the config. When your mental model is “policy = deny,” you end up using a quarter of the tool.
Okay, so what’s a “platform primitive”
I should define the term since I’m hanging the whole post on it. When I say primitive, I mean it the way programming languages mean it: a small, well-understood building block that you compose bigger things out of. For a platform, I’d say a primitive needs four properties:
- It abstracts complexity. Developers use it without understanding the machinery underneath.
- It provides guarantees. Using it means certain properties hold automatically.
- It composes. You combine it with other primitives to build higher-level stuff.
- It’s self-service. You get it from the platform, not from a ticket queue.
Pods, Services, ConfigMaps: primitives. Crossplane compositions: primitives. And I want to convince you Kyverno policies belong on that list too.
What platform teams actually do with it
The best way I know to make this concrete is just to list the things I’ve seen platform teams build with Kyverno once they stopped thinking of it as a security scanner with opinions.
Namespace furnishing. A developer creates a namespace, and Kyverno generates the default NetworkPolicy, ResourceQuota, LimitRange, RoleBindings, and others. Nobody reads a wiki page listing the six things you’re supposed to remember. The namespace shows up furnished.
Sidecar injection. Observability agents, mesh proxies, secret sync containers – they’re all mutated into Pod specs at admission. The developer’s Deployment manifest stays clean and boring. The platform’s requirements get met anyway. Nobody negotiated anything.
Image reference rewriting. This one’s my favorite because it’s so simple and saves so much aggravation. Your platform wants images pulled through an internal mirror. You could ask every developer to remember mirror.internal/ prefixes forever, and they won’t, and you’ll have flaky builds when Docker Hub rate-limits you. Or Kyverno rewrites nginx:1.25 to mirror.internal/nginx:1.25 at admission and the whole problem just… stops existing. Developers write the natural thing. The right thing happens.
Default resource requests. Instead of blocking Pods without CPU/memory requests, which is technically correct but practically infuriating, inject workload-appropriate defaults. The scheduler gets what it needs. Developers deal with it when they actually need to tune something, not before.
Ownership labels. Team, cost center, environment. Enforce them where ambiguity is real, default them where it isn’t.
Read that list again and notice: none of it is security. It’s developer experience and operational hygiene—the boring, load-bearing work of running a platform.
What ties it together is that each one takes a belief the organization holds about how things should work and turns it into automatic, invisible enforcement. Nobody has to remember. That’s what a primitive does: it makes a guarantee so you don’t have to think about it.
Policy is how the platform expresses intent
Every organization has beliefs about how things should run. Some are security beliefs, like no root containers and only signed images. Some are operational, like everything has resource limits. Some are financial, like everything has a cost-center label. Some are honestly just cultural, like every deployment traces back to a catalog entry somewhere.
The traditional home for these beliefs is documentation. Wikis, onboarding decks, PR checklists, that one senior engineer who reviews everything. Which means enforcement is uneven, knowledge is tribal, and the platform team ends up as a human bottleneck because nothing works without someone in the loop.
Policy as code, versioned in Git, delivered by your GitOps tooling, and enforced by Kyverno is how those beliefs stop being documentation and become infrastructure. The platform’s rules stop living in people’s heads and start living in the system.
That’s the reframe, compressed: policy is the platform’s API for organizational intent.
What falls out of this
If you buy the reframe, some useful things follow, and they’re roughly the roadmap for the rest of this series.
The four verbs stop being a flat feature list and turn into a hierarchy of platform capabilities. Validation is guardrails. Mutation is paved roads. Generation is scaffolding. Verification is trust. Mutation in particular is wildly underused relative to how powerful it is. That gets its own post because I have a lot to say about it.
Policies start looking like products: versions, users, deprecation cycles, exception processes. Progressive rollout (auditing, then warning, then enforcing) stops being an advanced technique and becomes just how you ship a policy. Exceptions become tracked debt instead of quiet approvals buried in Slack threads.
And GitOps gets bigger. If policy is code and policy is how the platform expresses intent, the policy repo matters as much as the app manifests it governs. Your Argo CD or Flux isn’t just deploying workloads anymore. It’s deploying the rules that shape workloads. Which, by the way, opens up some genuinely tricky reconciliation questions when a policy mutates a resource that Argo CD thinks it owns. Also a future post. It’s a fun one if your idea of fun is sync loops.
The takeaway
Next time you’re in the Kyverno docs, try reading them as a platform SDK instead of a security manual. The API surface is bigger than the security framing suggests, and the things you can build on it are more interesting than “block bad Pods.”
Kyverno isn’t a bouncer standing at the door of your cluster. It’s connective tissue. It’s how the platform’s opinions become the platform’s behavior. Once that clicks, it’s hard to unsee — and the rest of this series is about what you do after it clicks.