Kubernetes Admission Controllers
Admission controllers are the enforcement gate at the end of the kube-apiserver request pipeline: after a request is authenticated and authorized, they validate or mutate the object before it is persisted to etcd. They are the mechanism behind Kubernetes governance — from built-in quota enforcement to dynamic policy engines like Kyverno. Source: Enforce Kubernetes Security with Kyverno Source: CKA Day 22
Position in the Request Pipeline
Every request to the API server flows through a strict pipeline (see Kubernetes Authentication & Authorization):
Client Request → TLS Termination → Authentication → Authorization → Admission Control → etcd
Admission control is the last gate before persistence. Authentication answered “who are you?”, authorization answered “may you do this?”, and admission control answers “does this object conform to policy?” A request can be fully authenticated and RBAC-authorized and still be rejected here — this is what makes admission control the natural home for organizational compliance rules.
Two Flavours: Validating and Mutating
| Type | What It Does | Ordering |
|---|---|---|
| Mutating | Modifies the object before persistence (inject defaults, patch fields) | Runs first |
| Validating | Accepts or rejects the object as-is | Runs after mutation, so it sees the final object |
Mutating always precedes validating: validators must evaluate the object exactly as it will be stored.
Built-In Admission Controllers
Kubernetes ships with many compiled-in controllers, enabled via --enable-admission-plugins on the API server:
| Controller | Purpose |
|---|---|
ResourceQuota | Rejects objects that would exceed the Namespace’s ResourceQuota |
LimitRanger | Applies default/ min/ max requests and limits from a LimitRange |
PodSecurity | Enforces Pod Security Standards (replaced PodSecurityPolicy in 1.25+) — see Container Security |
ServiceAccount | Auto-injects the default ServiceAccount and token into Pods |
MutatingAdmissionWebhook / ValidatingAdmissionWebhook | Delegate decisions to external HTTP webhooks — the extensibility point |
Dynamic Admission Control: Webhooks
The two webhook controllers turn admission control into an extension mechanism. Instead of recompiling the API server, you register a ValidatingWebhookConfiguration or MutatingWebhookConfiguration pointing at an HTTPS endpoint; the API server then POSTs an AdmissionReview object to that endpoint for every matching request and honours its allow/deny/patch response.
This is how tools like Kyverno, OPA Gatekeeper, and service meshes (sidecar injection) work: the engine registers its own webhook configurations, and the API server defers policy decisions to it. Webhook endpoints require TLS — the API server validates the serving certificate, which is why admission webhooks consume kubernetes.io/tls Secrets (see TLS Fundamentals).
The Governance Scaling Problem
Writing custom admission webhooks by hand is the “classic” way to enforce organizational rules — but it scales poorly:
- Language barrier — webhook servers are typically written in Go; most DevOps engineers are not Go developers.
- One webhook per rule — a rule for resource requests/limits, another for image tags, another for labels… each needs its own service, TLS, and deployment.
- Constant churn — compliance rules change as the organization evolves; every change means code, review, and redeploy.
At the scale of hundreds of teams and thousands of applications, maintaining bespoke webhook controllers consumes disproportionate engineering time. This is precisely the gap that dynamic admission controllers fill: a single engine (Kyverno, OPA Gatekeeper) that reads declarative policies and generates webhook configurations automatically — the DevOps engineer writes YAML, not Go. Source: Enforce Kubernetes Security with Kyverno
What a Rejection Looks Like
When a validating webhook (or built-in controller) denies a request, the API server returns an error before anything touches etcd:
$ kubectl create deployment nginx --image=nginx
# error: failed to create deployment: admission webhook "validate.kyverno.svc" denied the request:
# resource requests and limits are requiredNothing is persisted, no Pods are scheduled — the policy violation is stopped at the front door. This is the deploy-time control tier of Shift Left Security: non-compliant manifests never become running workloads.
See Also
- Kyverno — the dynamic admission controller that automates webhook generation from YAML policies
- Kubernetes Authentication & Authorization — the pipeline stages before admission control
- Kubernetes Architecture — the kube-apiserver component hosting admission plugins
- Kubernetes Namespaces — ResourceQuota and LimitRange enforcement boundary
- Kubernetes Resource Requests and Limits — the classic policy target
- Container Security — PodSecurity admission controller and Pod Security Standards
- DevSecOps Fundamentals — policy enforcement in the DevSecOps pipeline
- Shift Left Security — admission control as the deploy-time gate
- GitOps Security — GitOps-managed policy lifecycle with Argo CD
- Enforce Kubernetes Security with Kyverno — the scaling-problem narrative and Kyverno demo
Tags: kubernetes admission-controller security governance api-server webhooks devops