skip to content

Matching and Deciding

A validate rule picks the objects it applies to, then decides with a declarative pattern or an explicit deny block. Interviewers start here because most policies never leave this shape.

on this pageshow

explore

questions

25

In Kyverno, what does a validate.deny conditions block do that validate.pattern cannot?

level: juniorimportance: must knowfreq 62%

answer

  1. shape versus boolean test
  2. one describes required, one forbidden
  3. operators, sets, cross-field
  4. key, operator, value under any or all
  5. conditions true means blocked

basics

~20 s

A deny block evaluates boolean conditions with operators over the admission request and blocks when they are true. A pattern only asserts the shape a resource must match, so it cannot use operators, compare two fields, or read request metadata.

solid answer

~50 s

`validate.pattern` is declarative: you write a fragment of the desired resource and the incoming object must satisfy it, so it reads like the manifest a developer would write. `validate.deny.conditions` is a boolean test instead: a list of `key` / `operator` / `value` conditions grouped under `any` or `all`, where the key is normally a JMESPath expression in `{{ }}` substituted from the admission request. If the conditions come out true, the request is denied with the rule's message — so a deny block describes the forbidden state, while a pattern describes the required one. Only the deny form gives you operators such as `AnyNotIn` or `GreaterThan`, comparison between two fields, and access to things outside the object like `request.operation` or `request.userInfo.groups`. When the rule is simply "this field must be present and look like this", the pattern reads better.

go deeper

for a junior

Be ready to state the polarity out loud: a pattern says what the resource must look like, a deny block says what is forbidden and blocks when its conditions are true. Know that a condition is a key, an operator and a value.

for a middle

Expect to explain why the key is a JMESPath expression in braces and what that buys you — operators, set membership, and fields of the admission request such as the operation, that a pattern cannot reach at all.

for a senior

Show judgment about which form a given rule should use, and defend it on reviewability rather than expressiveness: a wildcard pattern that the governed team can read beats a correct deny block nobody dares patch.

for a principal

Own the house style. Decide which form is the default for policies your organisation ships, what a rule must look like before it is allowed to use the more powerful form, and how a bad patch to each form fails.

## Two ways to say no inside one Kyverno validate rule A Kyverno policy object holds rules; each rule selects resources with a `match` block and then decides. A `validate` rule expresses that decision in one of two main shapes: `validate.pattern` or `validate.deny`. Knowing which one a rule should use is the first thing an interviewer probes, because most real policies never leave this shape. ### validate.pattern — a shape the resource must satisfy A pattern is a fragment of a resource. Kyverno overlays it on the incoming object and the object must satisfy every part of it. It reads like the YAML the developer already writes: - `storageClassName: "encrypted-*"` — the field must exist and its value must match the wildcard. - A key with no wildcard means an exact literal. - Anchor syntax exists for conditional, existence and negation checks (a topic of its own). The pattern's virtue is reviewability. Someone who has never read a policy language can look at it and see the manifest they are expected to produce, and the diff of a change to it is small and obvious. ### validate.deny — boolean conditions that block when true `validate.deny.conditions` is a different thing entirely. It is a list of conditions, each `{ key, operator, value }`, grouped under `any` (at least one true) or `all` (every one true). The key is normally a JMESPath expression wrapped in `{{ }}`, substituted against the admission request before the operator runs. If the block evaluates to **true**, the request is **blocked** and `validate.message` is returned to the user. That polarity is the single most common source of confusion. A deny block enumerates the state you refuse to admit, not the state you want. A rule written as "storage class is in the encrypted set" under a deny block blocks exactly the compliant resources and admits everything else. ### What a pattern genuinely cannot do 1. **Operators.** A pattern has wildcards and anchors, not a general comparison vocabulary. "The value must be one of these four names" is `AnyIn` in a deny condition; there is no clean pattern equivalent when the names share no common prefix. 2. **Cross-field comparison.** Comparing one field of the resource against another is not expressible as a shape — a pattern is matched positionally against the object, so it has nothing to hold the other field's value in. 3. **Anything outside the resource.** A pattern is applied to the object. A deny condition's key is a JMESPath expression over the whole admission request, so it can read `request.operation` to apply only on CREATE, `request.userInfo.groups` to exempt a break-glass group, or `request.namespace`. None of that is part of the object being submitted. 4. **Combining a looked-up value with an operator.** A rule that must compare the object against a value fetched into the rule's context needs a condition to do the comparing. ### Worked example — restricting storage to encrypted classes Suppose PersistentVolumeClaims may only name a StorageClass from an approved encrypted set. If those classes all share a prefix, the pattern is genuinely the better rule: ``` pattern: spec: storageClassName: "encrypted-*" ``` One line, self-explanatory to the team it governs. But if the approved set is an arbitrary list of names, or the rule must apply only on CREATE and exempt the platform team's own service account, the pattern cannot express it and you move to a deny block with `AnyNotIn` over the list plus a condition on `request.operation`. The same contrast shows up with a Service of type LoadBalancer that must carry an internal-only annotation. As a shape, that is "if the type is LoadBalancer, then this annotation must be set" — expressible with a conditional anchor, but it reads awkwardly. As a deny block it is two plain conditions under `all`: type equals LoadBalancer, and the annotation is not the value we require. Most reviewers find the second version easier to argue about. ### How to choose Ask what the rule is really saying. "The resource must look like this" is a pattern. "This combination of facts is forbidden" — especially when the facts involve operators, sets, several fields, or the requester — is a deny block. A single Kyverno policy can hold rules of both kinds, and mixing them by fit rather than by habit produces policies people can actually read.

  • When would you still reach for validate.pattern over a deny block?
    When the rule is a shape: a required field, a literal value, or a wildcard match such as `storageClassName: "encrypted-*"`. The pattern looks like the manifest the developer writes, so it survives review by people who do not author policy, and a patch to it is easy to read. Reach for deny only when you need operators, set membership, several fields compared together, or request metadata.
  • Can a deny condition look at something that is not part of the submitted resource?
    Yes — that is one of its main advantages. The key is a JMESPath expression over the admission request, so it can read `request.operation` to scope the rule to CREATE, or `request.userInfo.groups` to let a named break-glass group through. A pattern is only ever matched against the object itself and has no access to any of that.
  • What happens when a deny block's conditions evaluate to false?
    Nothing visible: the rule does not deny, the request continues through the rest of admission, and the validate message is never shown. A deny rule is silent unless it fires, which is why an inverted condition list is so easy to ship — the policy looks installed and healthy while admitting exactly what it was meant to stop.

A pattern is a stencil you lay over the resource to see whether it fits. A deny block is a checklist of yes/no questions, and a checklist that comes back yes stops the change.

saying these in an interview costs you the question

  • Thinks a deny block describes the allowed resource
  • Believes a pattern can compare two fields to each other
  • Assumes conditions evaluating true means the request passes
  • Claims a pattern can read request.operation or the requesting user
  • Uses a deny block for a rule that is just a required literal

context

open as a page

In a Kyverno policy, what does the context block do and how do you use its value?

level: juniorimportance: must knowfreq 64%

basics

~20 s

A Kyverno rule's context block fetches data the request itself does not carry - a ConfigMap, a live API call, or image registry metadata - binds each source to a name, and the rule then references it as a double-brace variable.

open as a page

In Kyverno, a validate rule matches only Pods - why does it still refuse a Deployment?

level: juniorimportance: must knowfreq 72%

basics

~20 s

Kyverno's Pod controller autogen copies a Pod rule into equivalent rules for Deployment, StatefulSet, DaemonSet, Job and CronJob, rewriting field paths into each one's Pod template. The Deployment is refused by a generated rule, not the one you wrote.

open as a page

In a Kyverno verifyImages rule, what does imageReferences select and what happens to an image it does not match?

level: juniorimportance: must knowfreq 60%

basics

~20 s

imageReferences is a list of glob patterns matched against every image string in the pod spec, including initContainers and ephemeral containers. An image matching no pattern is never evaluated by that rule, so it is admitted unverified.

open as a page

In a Kyverno validate.pattern, what happens if a field in the pattern is missing from the resource?

level: juniorimportance: must knowfreq 70%

basics

~10 s

An unanchored field in a Kyverno validate.pattern is mandatory: if the resource does not have it, the pattern fails and the request is rejected. Give it the value ?* to demand any non-empty value.

open as a page

What is the difference between a Kyverno Policy and a ClusterPolicy?

level: juniorimportance: must knowfreq 68%

basics

~10 s

A 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.

open as a page

In a Kyverno validate.deny block, how do the any and all condition lists decide whether a request is blocked?

level: middleimportance: must knowfreq 55%

basics

~20 s

Under all, every condition must be true; under any, at least one must be true. When the block comes out true the request is denied with the rule's message. If both lists appear in the same block, both have to be satisfied.

open as a page

In a Kyverno pattern, why does an anchored (resources) key let every container through?

level: middleimportance: must knowfreq 62%

basics

~10 s

A conditional anchor is a condition, not an assertion. (resources) only says: if resources matches, check my peer keys. With no peer keys there is nothing to check, so every container is admitted.

open as a page

In a Kyverno rule, how do the match and exclude blocks decide which resources it applies to?

level: middleimportance: must knowfreq 74%

basics

~10 s

The match block selects which resources and requesters a Kyverno rule applies to; the exclude block subtracts from that set. Anything matching both is skipped, so exclude always wins.

open as a page

In Kyverno, how do you block an image whose vulnerability-scan attestation is older than 14 days?

level: seniorimportance: must knowfreq 45%

basics

~10 s

Add an attestations entry naming the scan predicate type, give it the attestors whose signature you accept, and condition on the predicate's timestamp field. No verifiable attestation of that type blocks the image.

open as a page

In a Kyverno variable, why does an unquoted nodeSelector key containing dots fail to resolve?

level: middleimportance: should knowfreq 47%

basics

~20 s

Kyverno substitutes double-brace expressions with JMESPath, which reads every dot as a step into a nested field. A key like topology.kubernetes.io/zone is parsed as three nested lookups that do not exist, so quote the whole key inside the path.

open as a page

In a Kyverno autogen rule, what replaces spec.containers for a Deployment and for a CronJob?

level: middleimportance: should knowfreq 55%

basics

~20 s

For a Deployment, StatefulSet, DaemonSet or Job the path becomes spec.template.spec.containers. For a CronJob it becomes spec.jobTemplate.spec.template.spec.containers, because the Pod template sits under a Job template. That extra depth is why CronJob gets its own generated rule.

open as a page

In a Kyverno pattern over spec.containers, how many containers must match the sub-pattern?

level: middleimportance: should knowfreq 45%

basics

~20 s

All of them. A Kyverno list pattern is applied to every element of the resource array, so one container without a memory limit fails the rule. The existence anchor on the array key relaxes it to at least one element.

open as a page

Why does a Kyverno deny condition break when the JMESPath field it reads is absent?

level: seniorimportance: should knowfreq 42%

basics

~20 s

Kyverno substitutes the JMESPath expression into the condition before evaluating it. An absent field does not resolve to false; it fails substitution, so the rule errors instead of denying. Supply a default with the JMESPath or-operator, as in field || ''.

open as a page

A Kyverno rule stopped blocking after its ConfigMap was renamed - how would you have caught it?

level: seniorimportance: should knowfreq 43%

basics

~20 s

Alert on rule results, not on violations. A failed context lookup produces an error result and a skipped precondition produces a skip - both show up as zero violations, so watch error and skip counts and run a deliberately non-compliant canary against the cluster.

open as a page

A Kyverno Pod rule blocks Deployments, but the same violation in a CronJob is admitted. Why?

level: seniorimportance: should knowfreq 47%

basics

~20 s

Most likely the policy carries a pod-policies.kyverno.io/autogen-controllers annotation that narrows generation to a subset of kinds, so no CronJob variant was ever derived. Read the policy back from the cluster: if no autogen-cronjob- rule exists, CronJobs are outside the control.

open as a page

Your Kyverno verifyImages rule rewrote a tag to a digest and GitOps now reports permanent drift — why?

level: seniorimportance: should knowfreq 38%

basics

~10 s

verifyImages mutates the admitted object by default, appending the resolved digest to the tagged reference. Git still says only the tag, so a GitOps controller diffing desired against live reports permanent drift.

open as a page

How do you prove a Kyverno validate.pattern actually blocks, given that a bad anchor fails open?

level: seniorimportance: should knowfreq 38%

basics

~20 s

Test with resources that must be rejected, not only ones that must pass. A bad anchor makes a Kyverno pattern assert nothing and report no violation, so green runs prove nothing until a non-compliant fixture is rejected.

open as a page

When do you split Kyverno rules across separate policies instead of one ClusterPolicy?

level: seniorimportance: should knowfreq 46%

basics

~20 s

Split when rules have different owners, review paths or lifecycles, because the policy object is the unit of creation, deletion and RBAC. Do not split merely to give rules different failure actions — that is already per-rule.

open as a page

Your Kyverno verifyImages rule gates scan freshness — what can it prove to an auditor about workloads already running?

level: principalimportance: should knowfreq 30%

basics

~10 s

Only that workloads admitted after the rule went live met the condition at that moment. It says nothing about pods admitted earlier, whether attestations are still fresh, or images no pattern selected.

open as a page

Kyverno refuses your Deployment with two near-identical messages - what causes the duplication?

level: middleimportance: nice to knowfreq 30%

basics

~20 s

Two rules matched the same object: the rule Kyverno derived from a Pod rule for Deployments, and a separately maintained rule that matches Deployment directly. Kyverno reports every failing rule, so the same control is stated twice.

open as a page

In a Kyverno verifyImages rule, how do you require signatures from two of three named attestors?

level: middleimportance: nice to knowfreq 42%

basics

~20 s

Put the three attestors as entries in one attestors set and give that set count: 2. Inside a set, count is a threshold over entries; omitting it requires all of them. Separate sets are ANDed.

open as a page

Which Kyverno validate form do you standardise on when dozens of teams will patch the policy?

level: principalimportance: nice to knowfreq 26%

basics

~20 s

Choose on reviewability, not expressiveness. Make the declarative pattern the default because governed teams can read it, allow deny conditions where operators or request fields are genuinely needed, and reserve the CEL form for teams already fluent in it.

open as a page

Your Kyverno allow lists live in ConfigMaps - who should be able to change them, and how?

level: principalimportance: nice to knowfreq 29%

basics

~20 s

Update rights on that ConfigMap are equivalent to amending the policy, so govern it like policy: platform-owned namespace, the same repository and review as the rule, alerting on writes, and a pre-agreed emergency path that is reconciled back into git.

open as a page

Should tenants own Kyverno Policy objects in their own namespaces on a shared cluster?

level: principalimportance: nice to knowfreq 31%

basics

~20 s

Usually yes, with limits. A namespaced Kyverno Policy can only add constraints inside its own namespace and cannot relax a platform ClusterPolicy, so the security downside is small. The real cost is operational: tenants can block themselves.

open as a page