skip to content

Kubernetes Admission Control

You will learn to author the rule an admission request is judged by: the AdmissionReview it sees, the objects it matches, reject versus patch. Most admission accidents are authoring accidents.

on this pageshow

explore

questions

page 1 of 2

When you kubectl apply a Deployment, which admission requests does the API server actually see?

level: juniorimportance: must knowfreq 72%

answer

  1. your apply is not the whole story
  2. count the hops down to the Pod
  3. each hop is its own CREATE
  4. requester is a kube-system service account
  5. kubectl already printed success

basics

~20 s

Three separate ones, not one: your Deployment, then the ReplicaSet the deployment controller creates, then one request per Pod from the ReplicaSet controller. Each is admitted on its own, under the controller's identity rather than yours.

solid answer

~40 s

One `kubectl apply` of a Deployment produces a chain of independent admission requests spread over time. The API server first admits the Deployment itself, with the requester recorded as you. The deployment controller then creates a ReplicaSet — a second CREATE, made as `system:serviceaccount:kube-system:deployment-controller`. The ReplicaSet controller then creates each Pod — one CREATE per replica, made as `system:serviceaccount:kube-system:replicaset-controller`. A CronJob works the same way: the cronjob controller creates a Job, the job controller creates the Pods. The consequence matters more than the trivia: a rule written against Pods does not run while your apply is in flight. It runs seconds later, against an object no human submitted, on a connection your terminal is not holding — so a denial there can never come back as an error from `kubectl apply`.

go deeper

for a junior

Be ready to count the hops out loud: Deployment, then ReplicaSet, then one Pod per replica, each a separate admission request. Know that the last two are made by control-plane controllers, not by you.

for a middle

Explain the mechanics: admission is per-API-request, the requester identity differs at each hop, and the same field lives at a different path on a Pod, a pod template and a CronJob's jobTemplate.

for a senior

Show that you design for the feedback path, not just the enforcement point. Say where a Pod-level denial surfaces, who will never see it, and what you add so the failure is noticed within minutes rather than days.

for a principal

Own the platform consequence: a guardrail that enforces correctly but reports into a controller's event stream generates support load and erodes trust in the whole gate. Decide up front where developers are told no.

## One command, several admission requests Admission control in Kubernetes is per-API-request, not per-intent. Every write that reaches the API server is admitted on its own, and the API server has no notion of "the thing the user was trying to do". So the mental model of "I applied a Deployment, therefore admission looked at my Deployment" is only one third true. Applying a Deployment produces this chain: 1. **CREATE (or UPDATE) Deployment** — submitted by you. The requester in the admission payload is your username and your groups. If a rule denies here, the API server returns the failure on your open connection and `kubectl` prints it and exits non-zero. 2. **CREATE ReplicaSet** — submitted moments later by the deployment controller, running inside the control plane as the service account `system:serviceaccount:kube-system:deployment-controller`. 3. **CREATE Pod, once per replica** — submitted by the ReplicaSet controller as `system:serviceaccount:kube-system:replicaset-controller`. The batch path is the same shape with different actors: a CronJob is admitted when you apply it; the cronjob controller creates a Job on each schedule tick; the job controller creates the Pods. Three kinds, three requests, three requesters. ## Why the chain matters to a policy author **The Pod is the object your rule usually cares about.** Container images, `securityContext`, resource limits, host mounts, host networking — these live on the pod spec. So the natural rule targets Pods. But the Pod is the object *furthest* from the human. Between the developer's editor and the Pod there are two machine-made requests, and by the time the Pod is created the developer's `kubectl apply` has already printed `deployment.apps/checkout configured` and returned zero. **A denial at the Pod hop has nowhere to go.** The requester is a controller. Controllers do not have terminals; they have work queues. When the create fails, the ReplicaSet controller records the failure against the ReplicaSet — an event, and a `ReplicaFailure` condition — and retries with backoff. Nothing about that is printed to anybody. The user sees a Deployment that reports zero ready replicas and no obvious reason. **Each request stands alone.** The admission payload for the Pod carries the Pod, the requester and the operation. It does not carry the Deployment, the ReplicaSet, or any other cluster state. A rule evaluating the Pod cannot ask "which Deployment is this from?" or "did the same team already have three of these?" — that data is simply not in the request, and the engine gets no free lookup. ## What the same field looks like at each hop The same setting exists at several levels with different paths. A memory limit is at `spec.containers[].resources.limits.memory` on a Pod, at `spec.template.spec.containers[].resources.limits.memory` on a Deployment, StatefulSet, DaemonSet, ReplicaSet or Job, and at `spec.jobTemplate.spec.template.spec.containers[].resources.limits.memory` on a CronJob. Choosing which of those to match is the central authoring decision on this material, and the chain above is why: matching Pods is complete but silent, matching the workload kinds is loud but partial. ## Bare Pods, for contrast Applying a Pod directly is the degenerate case: one request, requester is you, and a denial appears immediately in your terminal with the rule's message. That is why rules feel well-behaved in a demo and mysterious in production — the demo used a bare Pod and production uses Deployments. ## What to say in an interview Count the hops, name the requesters, then state the consequence: a Pod-level denial is real enforcement but invisible feedback, because the request that was rejected was never the one the human made.

  • If a rule targeting Pods denies one of those Pods, where does the rejection actually land?
    On the ReplicaSet. The controller records a create failure as an event on the ReplicaSet and sets a `ReplicaFailure` condition, then retries with backoff. The Deployment shows zero ready replicas. Nothing is written to the developer's terminal, and `kubectl get pods` shows no pod at all — because no Pod object was ever admitted.
  • Does applying a bare Pod directly follow the same path?
    No — that is a single request with you as the requester, so a denial comes straight back on your connection and `kubectl` exits non-zero with the rule's message. It is the same rule and the same evaluation; only the feedback path differs, which is why rules behave so differently in a demo than under a Deployment.
  • Can the rule evaluating the Pod look up the Deployment that ultimately caused it?
    Not from the request. The admission payload carries the object, its previous version on an update, the requester and a few request attributes — no other object and no cluster state. Any information you want the Pod-level rule to see has to be present on the Pod itself, for example a label the workload's pod template propagates.

You hand in a form at the counter and it is accepted. A clerk in the back office copies it onto a second form, and another clerk copies that onto a third. If the third form is rejected, the rejection sits on the back-office desk — the counter already told you you were fine.

saying these in an interview costs you the question

  • Thinks one kubectl apply produces one admission request
  • Expects a Pod-level denial to fail the kubectl apply
  • Believes the Pod request names the human who applied
  • Assumes the engine can read the parent Deployment while admitting the Pod
  • Confuses the Pod's own service account with the requester

context

open as a page

In Kubernetes, kubectl printed a 'Warning:' line and still created the object - what happened at admission?

level: juniorimportance: must knowfreq 68%

basics

~20 s

A warning is advisory only. The API server returned it in an HTTP Warning response header alongside a response that succeeded, so the object was admitted. Only a denial, which comes back as a failed status, stops the write.

open as a page

Why do cluster-wide Kubernetes admission policies exclude kube-system from their match scope?

level: juniorimportance: must knowfreq 62%

basics

~20 s

The rule was written for tenant workloads, not cluster infrastructure — and the policy engine's own Pods live in a system namespace, so an engine inside its own scope can block the Pods that would replace it.

open as a page

What does a Kubernetes AdmissionReview request contain, and what cluster information is missing from it?

level: juniorimportance: must knowfreq 70%

basics

~20 s

An AdmissionReview request carries one object under review, its previous version on updates, the requesting user and groups, the operation, resource and subresource, and a dryRun flag. It carries no other objects, no cluster state and no history.

open as a page

When should an admission policy reject a Kubernetes manifest instead of silently patching it?

level: juniorimportance: must knowfreq 70%

basics

~20 s

Patch when the fix is behaviour-neutral and the platform owns the value, like adding a missing default. Reject when the compliant form changes what the process sees, such as moving a secret from an environment variable into a mounted file.

open as a page

Why is a mutating admission rule that injects a sidecar into every Pod riskier than a validating rule?

level: juniorimportance: must knowfreq 60%

basics

~20 s

A validating rule can only accept or reject. A mutating rule rewrites the object that actually runs, so whoever controls it can add a container, volume or environment variable to every Pod it matches, cluster-wide.

open as a page

In a Kubernetes ValidatingAdmissionPolicy, what data can a CEL validation expression see?

level: juniorimportance: must knowfreq 58%

basics

~10 s

Only what the API server hands the expression: the incoming object, the previous object on an update, the request attributes, the request's namespace object, and a bound parameter resource. It cannot fetch anything else.

open as a page

Why can't an admission check enforce at most three LoadBalancer Services per namespace from the request alone?

level: juniorimportance: must knowfreq 62%

basics

~20 s

An admission request carries only the submitted object, its previous version, and the requesting user - not the namespace's other Services. Counting needs those siblings, so the rule must get them from somewhere outside the request.

open as a page

When an admission rule starts requiring a backup-retention label on PersistentVolumeClaims, what happens to the 400 PVCs that already exist?

level: juniorimportance: must knowfreq 64%

basics

~10 s

Nothing happens to them. Admission evaluates API write requests, not stored objects, so the 400 existing PVCs keep running unlabelled and are never checked again unless something submits a write for them.

open as a page

What does a Kubernetes AdmissionReview request actually carry, and what is simply absent from it?

level: juniorimportance: must knowfreq 60%

basics

~20 s

It carries the single object being submitted, the previous version on an update or delete, the requesting user and groups, and a dryRun flag. It carries no other object, no cluster state, no history, and no artifact contents.

open as a page

In a Kubernetes admission policy, what do namespaceSelector, objectSelector and matchConditions each match on?

level: middleimportance: must knowfreq 68%

basics

~20 s

namespaceSelector matches labels on the containing Namespace, objectSelector matches labels on the object itself, and matchConditions are CEL expressions over the whole request. All three narrow a match that resource rules have already made on group, version, resource and operation.

open as a page

Your storageClass admission rule has enforced for a month — why can it still not tell you how many existing volumes violate it?

level: middleimportance: must knowfreq 66%

basics

~20 s

Admission runs only on the write path. It sees objects as they are created or updated, and it was never shown anything already stored in the cluster. Counting today's violations needs a background evaluation that reports on existing objects as data.

open as a page

Your admission rule matches only CREATE on PersistentVolumeClaims — which later changes will it never evaluate?

level: middleimportance: must knowfreq 57%

basics

~20 s

Every subsequent write. A CREATE-scoped rule sees the object once, at birth; any later update by a user, an operator or a provisioner can strip the required label and no request is ever denied, so a compliant object silently becomes non-compliant.

open as a page

Why can't an admission rule reject an image whose bundled dependencies carry a disallowed licence?

level: middleimportance: must knowfreq 50%

basics

~20 s

The admission request carries an image reference string, not the image's dependency list, so the licence fact is not in the payload. Reading it would need an out-of-band fetch of self-asserted metadata. The fact belongs to the build-time inventory instead.

open as a page

Two Ingresses claiming the same host were both admitted within one second - why did the uniqueness rule pass both?

level: seniorimportance: must knowfreq 45%

basics

~20 s

Each request was evaluated on its own, against a view of the cluster that did not yet contain the other. Admission has no lock and no serialisation, so a check-then-act uniqueness rule can pass both halves of a race.

open as a page

Why insist that a policy engine can evaluate one rule against a manifest file without a cluster?

level: juniorimportance: should knowfreq 58%

basics

~20 s

A rule you can only exercise inside a live cluster can only be tested by deploying it. Offline evaluation runs the same rule text against a saved manifest in seconds, in a unit test and in CI.

open as a page

Should a memory-limit rule target Pods or the Deployment and CronJob templates that create them?

level: middleimportance: should knowfreq 58%

basics

~20 s

Target Pods for enforcement — every path ends in a Pod. Target the workload kinds too for feedback: only there does the denial reach the author's terminal. The two views can disagree, so decide which your intent means.

open as a page

In a Kubernetes ValidatingAdmissionPolicy, what does messageExpression give you that a static message cannot?

level: middleimportance: should knowfreq 55%

basics

~20 s

messageExpression is a CEL expression evaluated against the request object, so the failure text can name the specific object, field or value that broke the rule. A static message is one fixed sentence that can only describe the rule.

open as a page

In a Kubernetes AdmissionReview, which of object and oldObject are populated for CREATE, UPDATE and DELETE?

level: middleimportance: should knowfreq 58%

basics

~20 s

On CREATE, object holds the incoming object and oldObject is null. On UPDATE both are populated, new and stored. On DELETE it inverts: object is null and oldObject holds the object about to be removed. userInfo is populated in all three.

open as a page

Why must a Kubernetes mutating admission webhook's patch be idempotent under reinvocation?

level: middleimportance: should knowfreq 48%

basics

~20 s

Because the same webhook can be called again on an object it already patched, once a later mutator changes that object. A patch that sets a field converges; one that appends to a list adds a duplicate every time it runs.

open as a page

In a Kubernetes AdmissionReview, what does the API server actually send an engine whose match includes Secrets?

level: middleimportance: should knowfreq 52%

basics

~20 s

The full object body — for a Secret, its complete data — plus the previous version on an update, the requesting user and groups, the operation and dryRun. It carries no other object and no cluster state.

open as a page

In a ValidatingAdmissionPolicy, how do you feed an approved-value allowlist to CEL without hard-coding it?

level: middleimportance: should knowfreq 45%

basics

~20 s

Declare a paramKind on the policy, point the binding's paramRef at an instance of that kind, and read it in the expression as params. Changing the allowlist then means editing that resource, not the policy.

open as a page

What does an admission engine's replicated copy of cluster objects give a counting rule, and how is it wrong?

level: middleimportance: should knowfreq 48%

basics

~20 s

It supplies the siblings a request does not carry, by watching the API and holding a local copy of chosen kinds. That copy always reflects a slightly earlier moment, and it is empty and filling right after the engine restarts.

open as a page

A CronJob has produced nothing for two days and no kubectl command ever failed — what happened?

level: seniorimportance: should knowfreq 46%

basics

~20 s

Most likely a Pod-level admission rule is rejecting the job's Pods. The CronJob and its Jobs are admitted fine; only the Pod create is denied, by a controller, so the failure lands in a Job event and never in anyone's terminal.

open as a page

Your policy warns on a deprecated Kubernetes API version the server already warns about - what should your text say?

level: seniorimportance: should knowfreq 40%

basics

~20 s

Carry only what the API server cannot know. Its built-in deprecation warning already names the version and its replacement, so your text must add local detail: which template produced the object, which rule fired and who owns it.

open as a page

In Kubernetes, what does scoping an admission rule by objectSelector rather than namespaceSelector grant a developer?

level: seniorimportance: should knowfreq 44%

basics

~20 s

Scoping by objectSelector grants a self-service opt-out. Labels live on the submitted object, so anyone allowed to create that object can also set the label that puts it out of scope, in the same manifest the rule would have judged.

open as a page

Why must an admission rule that blocks downgrading a StatefulSet's encryption-tier annotation compare object with oldObject?

level: seniorimportance: should knowfreq 42%

basics

~20 s

Because the rule forbids a transition, not a state. Only oldObject reveals the previous value, so the rule can tell a harmless edit from a downgrade. On CREATE there is no oldObject, so the rule needs its own branch for that case.

open as a page

Your admission engine may be injecting an undeclared sidecar into every Pod: how do you confirm it and contain it?

level: seniorimportance: should knowfreq 42%

basics

~20 s

Compare live objects with the manifests that produced them: the extra container is in the stored object but not the source. Then remove the mutating registration so the API server stops calling the engine, and roll the workloads.

open as a page

A legacy namespace cannot meet your encrypted-storageClass rule — why express the exception as a cluster object rather than editing the rule?

level: seniorimportance: should knowfreq 56%

basics

~20 s

Editing the rule weakens it for everyone and buries the carve-out in policy source. An exception object keeps one rule text everywhere, states exactly what is excluded and where, and is listable, access-controlled and revocable by deleting it.

open as a page

Can a ValidatingAdmissionPolicy enforce an allowlist that only an external inventory service knows?

level: seniorimportance: should knowfreq 44%

basics

~20 s

Not directly — CEL in an admission policy cannot call anything. Either mirror the inventory into a parameter resource and enforce against the copy, split the rule and keep only the self-contained half in-tree, or move the check to an engine that can do the lookup.

open as a page

showing 1–30 of 42