Why can a shape-matching policy rule not express 'every multi-replica workload needs a PodDisruptionBudget'?
answer
- one shape describes one object
- for every X there exists a Y
- a pattern cannot name a second document
- compare against pod template labels
basics
~20 sA match document describes the shape of one resource. This requirement is a relation between two — for each multi-replica Deployment, some PodDisruptionBudget must select the same pods — and quantifying across sibling documents needs a logic language.
solid answer
~50 sBecause a shape describes one object, and the requirement is a relation between two. Even when the rendered output contains both documents, the rule has to say: for every Deployment with `replicas` greater than one, there exists a PodDisruptionBudget in the same output whose selector matches that Deployment's pod template labels. That is a universal quantifier with an existential inside it, plus a selector comparison — and a pattern has no way to refer to a second document at all. A single expression can technically state it with quantifier macros over the whole output, but the join and the label comparison collapse into one nested expression nobody can check. A logic language states it directly, because you can name the budgets that cover a given label set and then write the top-level rule in terms of that name.
code
yaml · 21 linesapiVersion: apps/v1
kind: Deployment
metadata:
name: checkout
spec:
replicas: 3
template:
metadata:
labels:
app: checkout
# ...
---
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: checkout-pdb
spec:
minAvailable: 1
selector:
matchLabels:
app: checkoutgo deeper
Remember the shape of the limit: a pattern describes one object, so any requirement mentioning two objects at once is outside what a pattern alone can say.
Be able to restate the requirement as for every… there exists…, then point at exactly which part each style can and cannot carry, including the pod template label detail.
Show judgment about what to ship when the style falls short: a narrower proxy rule declared as a proxy, or one rule moved to a style that quantifies — never a rule that only looks like the standard.
Frame the ceiling as a platform decision: how many rules in your backlog need quantification decides whether you keep a second style at all, and who then has to review them.
## The requirement, stated precisely The written standard says: *a workload that declares more than one replica must be covered by a PodDisruptionBudget*. Turning that English into a rule exposes exactly where each language style stops. Formally the rule is: > for **every** object of kind Deployment with `spec.replicas > 1`, there **exists** an object of kind PodDisruptionBudget in the same evaluated output whose `spec.selector` matches the labels on that Deployment's `spec.template.metadata.labels`. Three things are going on: a universal quantifier, an existential quantifier nested inside it, and a comparison between two different fields of two different objects. ## Note what is *not* the problem It is tempting to say the rule is hard because the engine cannot see the PodDisruptionBudget. In the setup that matters here it can: the rendered Helm or Kustomize output is a single stream of documents, and the whole stream is the input. Both objects are right there. So the difficulty is purely a property of the **language** — what the rule can say about data it already has. ## What a match document can do A match document states the shape one resource must have and the engine compares the object against that shape field by field. Given a Deployment, a pattern can require `spec.replicas` to be `1`, or require a particular annotation, or forbid a field. What it cannot do is reference a *different* object: there is no syntax for *and somewhere else in this stream there is another document such that…*, because the pattern's whole coordinate system is the single object being compared. So the honest match-document rule is a **proxy**: for example, require every multi-replica Deployment to carry an annotation naming its budget. That is a different rule. It checks that somebody wrote a name down, not that a budget exists and covers the pods. Proxies are legitimate — they are cheap and reviewable — but a reviewer must be told that the rule enforces the proxy, not the standard. ## What a single expression can do An expression language with quantifier macros can, in principle, state the real rule when the whole stream is the input: *all objects of kind Deployment with replicas above one satisfy that some object of kind PodDisruptionBudget has a selector matching this Deployment's pod template labels*. The power is there. The problem is shape rather than power. There is nowhere to name the intermediate idea *the budgets covering these labels*, so the join, the kind filters and the label comparison nest into one long expression. The reviewer's job is to hold that whole expression in their head at once and compare it with the standard. In practice that is where subtle errors hide — an inverted comparison, a filter that never matches, a quantifier that vacuously succeeds over an empty list. ## What a logic language does A logic language quantifies naturally and, more importantly, lets you name the parts: - the set of workloads in this output with more than one replica; - the budgets whose selector matches a given label set; - the violation: a workload in the first set for which the second set is empty. Each name maps to one clause of the written standard, so review becomes a line-by-line comparison instead of an act of concentration. That is why cross-object requirements gravitate to this style, and why a repository of otherwise simple shape rules often keeps one escape hatch for them. ## The correctness trap inside the rule Whichever style you use, the selector comparison is where rules quietly go wrong. A PodDisruptionBudget selects **pods**, so its selector must be compared against the Deployment's `spec.template.metadata.labels` — the labels the pods will carry — not the Deployment's own `metadata.labels`. Many workloads label both identically, so a rule comparing the wrong one passes today and silently stops meaning anything the day somebody labels the Deployment differently from its template. A selector may also use `matchExpressions` rather than a plain `matchLabels` map; a rule that only understands the map form will report *not covered* for a workload that is in fact covered, and the team will learn to route around the gate. ## The reviewable answer When you are asked this in an interview, say the ceiling out loud and then say what you would ship: state the requirement as *for every… there exists…*, name the style that can express it, and if the platform's chosen style cannot, either move this one rule to a style that can or write the narrower proxy rule and label it honestly as a proxy. What you must not do is write a rule that looks like the standard, cannot actually be checked against it, and gets approved anyway.
- Could a single expression with quantifier macros express it after all?Technically yes, if the whole rendered stream is the input: every Deployment with replicas above one satisfies that some document is a PodDisruptionBudget whose selector matches its pod labels. The obstacle is not power but shape — the join and the label comparison collapse into one nested expression with no way to name the budgets covering these labels, so the reviewer has to verify the whole thing in one go.
- Which labels must the budget's selector be compared against, and why does it matter?Against the Deployment's `spec.template.metadata.labels`, because a PodDisruptionBudget selects pods, not Deployments. Many teams label the Deployment and its template identically, so a rule comparing the Deployment's own labels passes today and silently stops meaning anything the moment somebody diverges them. That is a rule that stays green while enforcing nothing.
- If the platform's style cannot express it, what do you ship?Either move this single rule to a style that can quantify, or ship the honest proxy — every multi-replica workload must declare the name of its budget — and label it in the rule and the standard as a proxy. The failure mode is shipping a proxy that reads like the real control, so an auditor and the next engineer both believe coverage is being checked.
saying these in an interview costs you the question
- Claims any rule can be written in any style with enough YAML
- Compares the Deployment's own labels, not its pod template labels
- Assumes a match pattern can reference a second document
- Treats any PodDisruptionBudget in the namespace as covering everything