Kyverno Policies and Rules: KCA practice questions
A Kyverno policy is a list of rules. Every rule has a name, a match block, an optional exclude block, and exactly one action: validate, mutate, generate or verifyImages. Rules are applied in the order they appear, and during admission mutation always happens before validation, so a validate rule should not contradict what a mutate rule just set.
By Ibrahim Yesilay · Published · Updated
Independent community practice, not affiliated with or endorsed by CNCF or The Linux Foundation.
What Kyverno Policies and Rules covers in KCA
A Kyverno policy is a list of rules. Every rule has a name, a match block, an optional exclude block, and exactly one action: validate, mutate, generate or verifyImages. Rules are applied in the order they appear, and during admission mutation always happens before validation, so a validate rule should not contradict what a mutate rule just set. The legacy ClusterPolicy and Policy kinds in kyverno.io are deprecated in Kyverno 1.19; the CEL-based ValidatingPolicy, MutatingPolicy, GeneratingPolicy, DeletingPolicy and ImageValidatingPolicy in policies.kyverno.io/v1 offer full feature parity, and each has a namespaced variant.
Validation has several forms. A pattern mirrors the shape of the resource; fields left out of the pattern act as wildcards, and child values are only checked when the parent matches. Values can use wildcards, where * matches any characters, ? a single one and ?* any non-empty value, and operators such as >, >=, <, <=, ! for negation, | for alternatives, & and ranges written with a dash. Anchors change the meaning of a field: a conditional anchor, field name in parentheses, checks the sibling fields only when it matches; the equality anchor =() checks a field only if it exists; the existence anchor ^() requires at least one list element to match; the negation anchor X() requires that a field is absent; and the global anchor <() skips the whole rule when its condition is false. anyPattern is a logical OR across several patterns and cannot be combined with pattern in the same rule.
A deny rule works the other way round: it blocks the request when its conditions evaluate to true. Conditions go under any or all and can use the full admission request through JMESPath, for example the operation, the requesting user or the old object. foreach applies a check to every element of a list chosen with a JMESPath list expression, such as each container of a Pod, exposing the current item as element, and loops can be nested. There is also a podSecurity subrule that applies the Pod Security Standards baseline or restricted profile at a given version, and a cel subrule.
Mutation uses patchStrategicMerge, an overlay that is good at lists and where the add-if-not-present anchor +() sets a value only when it is missing, or patchesJson6902 for precise add, replace and remove operations, which does not support conditional anchors. Mutate rules can also target existing resources through mutate.targets, processed asynchronously by the background controller. Generate rules create resources either from data written in the rule or by cloning an existing resource, and cloneList copies several kinds from one namespace. With synchronize enabled the generated resource is kept in line with its source.
Variables tie this together. Double braces evaluate JMESPath against the request, as in request.object.metadata.name, request.operation or request.userInfo.username, and against context entries loaded from ConfigMaps or API calls. Variables cannot appear in match or exclude, and preconditions, which use the same operators as deny conditions, decide whether a matched rule is applied at all.
Key points
- Each rule carries exactly one of validate, mutate, generate or verifyImages.
- A deny rule blocks when its conditions are true; a pattern blocks when the resource does not match.
- patchesJson6902 cannot use conditional anchors; patchStrategicMerge can.
- ClusterPolicy and Policy are deprecated in 1.19 in favor of the CEL-based policy types.
Three sample questions
8 KCA questions on Kyverno Policies and Rules, 8 with explanations. How practice works
Question 1
billing namespace and must never be visible or applicable to any other namespace in the cluster, even by accident. Which Kyverno resource kind should you author?- A.
ClusterPolicy, because it is the only kind Kyverno's admission controller watches. - B.
Policywithresources.namespaces: [billing]set in every rule'smatchblock. - C.
ClusterPolicywithresources.namespaces: [billing]set in every rule'smatchblock. - D.
Policy, because it is namespace-scoped and can only ever match resources inside its own namespace.
Correct answer: D
Policy resource is itself namespace-scoped — it lives inside billing and Kyverno restricts its rules to that same namespace automatically. There is no resources.namespaces field needed and no way for it to leak to another namespace, even by a future editing mistake.Question 2
ClusterPolicy rule that must both validate an incoming Pod's labels and, if the labels are missing, add a default label instead of blocking it. How many action blocks (validate, mutate, generate, verifyImages) can you put inside a single rule to do both?- A.Two — one
validateand onemutateblock in the same rule. - B.One — each rule commits to exactly one action type; you need two separate rules (or two separate policies).
- C.Any number, as long as they are listed under
spec.rules[0].actions. - D.Zero — Kyverno rules cannot mutate and validate; only
verifyImagesrules can do both.
Correct answer: B
validate rule, a mutate rule, a generate rule, or a verifyImages rule — never a combination. To validate and mutate related to the same resource, you author two rules (in the same policy or two policies), and mutate rules run before validate rules in the admission flow, so a mutate rule can supply a default that a later validate rule then accepts.Question 3
ClusterPolicy uses match.resources.kinds: [Pod] with no exclude block, and validationFailureAction: Enforce. After applying it, Kyverno's own components in the kyverno namespace start crash-looping because their own Pods are being rejected by the new policy. What should you add to prevent Kyverno from blocking its own control-plane Pods?- A.Change
validationFailureActiontoAuditpermanently. - B.Delete the
ClusterPolicyand recreate it as aPolicyinside thekyvernonamespace. - C.Set
background: falseon the rule. - D.Add an
excludeblock matchingresources.namespaces: [kyverno](or a broader system-namespace exclusion) alongside thematchblock.
Correct answer: D
match decides what a rule looks at; exclude carves out exceptions from that selection. Excluding system namespaces such as kyverno (and typically kube-system) is standard practice for any broadly-scoped policy so the enforcement engine, and other cluster infrastructure, is never at risk of blocking itself.Practice this topic
Focus mode keeps every question on Kyverno Policies and Rules until you leave it. 10 free guest answers, then a free account; no credit card.
Or open KCA practice across all topics.
Sources
The explanation above was checked against these official documents.
- Kyverno docs: ClusterPolicy overview (checked 2026-10-23)
- Kyverno docs: Validate Rules (checked 2026-10-23)
- Kyverno docs: Mutate Rules (checked 2026-10-23)
- Kyverno docs: Generate Rules (checked 2026-10-23)
- Kyverno docs: Variables (checked 2026-10-23)
- Kyverno docs: Policy Types overview (checked 2026-10-23)
Frequently asked questions
How do I require something of every container in a Pod?
Use a foreach in the validate rule with a list expression such as request.object.spec.containers. Each iteration exposes the current container as element, and the nested check can be a pattern, anyPattern or deny.