What is the difference between a Kyverno Policy and a ClusterPolicy?
answer
- one is namespaced, one is not
- same spec.rules in both objects
- a boundary the match block cannot cross
- cluster-scoped kinds need the cluster-scoped object
- who may create it is an RBAC call
basics
~10 sA Kyverno ClusterPolicy is cluster-scoped: its rules can match resources in any namespace and cluster-scoped kinds. A namespaced Policy applies only inside its own namespace. The rule syntax is identical in both.
solid answer
~50 sKyverno ships two policy resources with the same `spec` shape. `ClusterPolicy` is cluster-scoped, so its rules can match resources in every namespace and can also match cluster-scoped kinds such as Namespace or CustomResourceDefinition. `Policy` is created inside a namespace and only ever applies to resources in that namespace — naming other namespaces in its match block does not widen it, and it cannot match cluster-scoped kinds at all. Everything else is the same: `spec.rules`, each rule with a name, a match block, an optional exclude block, and one rule type. The two stack rather than override: for a given request every matching rule from every policy is evaluated, so a namespaced Policy can only add constraints, never relax a ClusterPolicy. In practice the platform team owns ClusterPolicy objects and a team may own a Policy in its own namespace.
go deeper
Be ready to state the scope difference in one sentence and to say that the rule syntax is the same in both objects. Knowing that a namespaced Policy cannot reach outside its namespace is the whole screening answer.
Explain the mechanics: cluster-scoped kinds are only matchable from a ClusterPolicy, a namespaced Policy's match block can narrow but not widen, and results from both accumulate for the same request rather than one overriding the other.
Show the operational judgment: which guardrails you keep as platform-owned ClusterPolicy objects, which you push down to a namespaced Policy, and how the exclude block has to change when a rule is promoted from one namespace to the whole cluster.
Own the delegation model. The scope split is really an RBAC and ownership boundary — who may create a cluster-wide blocking rule, what a team may author for itself, and why an additive-only constraint model makes that delegation safe.
## Two objects, one rule schema Kyverno stores policies in two custom resources: **`Policy`**, which is namespaced, and **`ClusterPolicy`**, which is cluster-scoped. Their `spec` has the same shape, so a rule can be copied from one to the other unchanged: - `spec.rules` is a list; - each rule has a `name`, a `match` block that selects what it applies to, an optional `exclude` block that subtracts from that selection, and exactly one rule type (a `validate`, `mutate`, `generate` or `verifyImages` block). If you already know how to write a rule, you already know how to write both objects. The choice between them is purely about **reach**. ## The difference is reach, not syntax **ClusterPolicy** rules can match resources in every namespace, and can match kinds that do not live in a namespace at all — Namespace, ClusterRole, CustomResourceDefinition, PersistentVolume. This is the object a platform team uses for a guardrail that must hold everywhere. **Policy** is created inside one namespace and its rules apply only to resources in that namespace. Two consequences trip people up: 1. Listing other namespaces in the rule's match block does not widen it. The namespace boundary of the object wins; the match block can only narrow within it. 2. It cannot match cluster-scoped kinds. Those objects do not belong to any namespace, so there is no namespaced policy that could plausibly own them. ## They stack; they do not override For a single admission request, Kyverno evaluates **every** matching rule from **every** installed policy — cluster-scoped and namespaced alike. There is no precedence order, no "more specific wins", and no allow rule that cancels a deny. The result is an accumulation of constraints: if any rule running in Enforce fails, the request is rejected with that rule's message. That property is what makes delegation safe. Giving a team the ability to create `Policy` objects in its own namespace lets that team make its own workloads *stricter*. It cannot be used to escape a platform `ClusterPolicy` that also matches those workloads. ## Where results are recorded When a rule's action is Audit rather than Enforce, the resource is admitted and the failure is written to a policy report instead. Results for namespaced resources land in a `PolicyReport` in the same namespace as the resource; results for cluster-scoped resources land in a `ClusterPolicyReport`. So the object split shows up again on the reporting side, and "where do I look for the finding" has the same answer as "where does the resource live". ## A worked example Say the availability guardrail is: *every Deployment with more than one replica must declare a readiness probe*. If that is the platform's expectation of all tenants, it belongs in a `ClusterPolicy` — one object, owned by the platform team, matching Deployments everywhere and excluding the namespaces the platform's own components live in. Now one tenant decides that in their namespace a multi-replica Deployment must additionally reference a PodDisruptionBudget. That is a local, stricter rule with no bearing on anyone else, and no reason for the platform team to carry it. It belongs in a `Policy` in the tenant's namespace. Both are evaluated for that tenant's Deployments; the tenant's rule adds to the platform's rather than replacing it. ## RBAC, which is the reason this is an interview question Creating a `ClusterPolicy` is a cluster-level privilege: whoever holds it can write a rule that blocks every namespace on the cluster, so it sits with the platform team. Creating a `Policy` can be granted per namespace, which is exactly what a tenant needs to author rules for their own workloads. Deciding which of those grants a team gets is the real decision hiding behind the syntax difference. ## Common mistakes - Assuming a namespaced Policy can reach another namespace by naming it in `match`. It cannot. - Trying to guard a cluster-scoped kind, such as requiring a label on new Namespaces, from a namespaced Policy. - Expecting a namespaced Policy to override or soften a ClusterPolicy. Constraints accumulate; nothing overrides. - Believing the two objects have different rule syntax and rewriting a rule when promoting it from one namespace to the whole cluster.
- Can a namespaced Kyverno Policy match a Namespace object?No. A Namespace is cluster-scoped, so it does not belong to any namespace and a namespaced Policy cannot own it. A rule that matches Namespace — for example to require a label on newly created ones — has to live in a ClusterPolicy.
- A ClusterPolicy and a namespaced Policy both match the same Deployment. Which one wins?Neither — both are evaluated. Kyverno runs every matching rule from every policy and accumulates the results, so the Deployment must satisfy both. If either rule is in Enforce and fails, the request is rejected. There is no precedence and no way for the namespaced Policy to relax the cluster one.
- You wrote a rule in a namespaced Policy and now want it everywhere. What changes?Only the object it lives in. Move the same rule into a ClusterPolicy — the `spec.rules` schema is identical. What you should revisit is the exclude block, because a rule that was implicitly limited to one namespace now reaches system namespaces and other teams' workloads too.
A ClusterPolicy is a house rule posted at the front door; a namespaced Policy is a rule taped to one flat's door. The flat can add rules, never repeal the building's.
saying these in an interview costs you the question
- Says a namespaced Policy reaches other namespaces if match lists them
- Thinks Policy and ClusterPolicy have different rule syntax
- Believes a namespaced Policy can override or relax a ClusterPolicy
- Assumes Kyverno only has the cluster-scoped object
- Tries to match a cluster-scoped kind from a namespaced Policy