8/855 min
Security & Scale
Admission Controllers β Request Validation & Mutation
Understand how admission controllers intercept API requests to enforce policies and inject configuration before resources are persisted.
advanced55 minRead β Lab β Quiz β Practice
π§ Brain Warm-Up
π§ Brain Warm-Up: You apply a Pod manifest with no CPU/memory limits in a namespace with a ResourceQuota. The request is rejected. What component rejects it β and at what point in the API request lifecycle? Think before reading.
API Request Lifecycle
Every kubectl apply goes through this pipeline before the object is stored in etcd:
kubectl apply
β
βΌ
kube-apiserver
β
ββ 1. Authentication (AuthN) β who are you?
β
ββ 2. Authorization (AuthZ / RBAC) β are you allowed?
β
ββ 3. Mutating Admission βββ can MODIFY the request
β (built-in + webhooks run in parallel)
β
ββ 4. Schema validation β is the object valid?
β
ββ 5. Validating Admission βββ can only APPROVE or REJECT
β (built-in + webhooks run in parallel)
β
ββ 6. Persist to etcd βMutating runs before Validating so that mutations are visible to validators.
Built-in Admission Controllers
| Controller | What it does |
|---|---|
LimitRanger | Applies default CPU/memory requests/limits from LimitRange objects |
ResourceQuota | Rejects requests that would exceed namespace quotas |
PodSecurity | Enforces Pod Security Standards (privileged/baseline/restricted) |
NamespaceLifecycle | Prevents object creation in terminating namespaces |
DefaultStorageClass | Adds the default StorageClass to PVCs that don't specify one |
ServiceAccount | Auto-injects the default ServiceAccount token into Pods |
PodSecurity Admission (PSA)
PSA replaced PodSecurityPolicy (deprecated in 1.21, removed in 1.25). It is enforced via namespace labels:
# Enforce the restricted standard (rejects violating Pods) kubectl label ns production pod-security.kubernetes.io/enforce=restricted # Warn but allow (useful during migration) kubectl label ns staging pod-security.kubernetes.io/warn=baseline # Also audit to the API audit log kubectl label ns staging pod-security.kubernetes.io/audit=restricted
Pod Security Standards
| Standard | What is blocked |
|---|---|
privileged | Nothing β all capabilities allowed |
baseline | Blocks hostPID, hostIPC, hostNetwork, privileged containers, unsafe sysctls |
restricted | All of baseline + requires non-root, no privilege escalation, drops all capabilities |
Webhook Admission Controllers
The MutatingAdmissionWebhook and ValidatingAdmissionWebhook built-in controllers enable external admission logic. The apiserver calls your HTTPS service with an AdmissionReview request:
kubectl apply
β
βΌ
kube-apiserver ββHTTPSβββΊ your-webhook-service
(receives AdmissionReview JSON)
(returns allowed: true/false + optional patches)Webhook Configuration
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
name: my-validator
webhooks:
- name: validate.example.com
rules:
- apiGroups: ["apps"]
apiVersions: ["v1"]
operations: ["CREATE", "UPDATE"]
resources: ["deployments"]
clientConfig:
service:
name: my-webhook-svc
namespace: default
path: /validate
caBundle: <base64-encoded-CA>
failurePolicy: Fail # Reject if webhook is unreachable
admissionReviewVersions: ["v1"]
sideEffects: NonefailurePolicy
Fail(default): request rejected if webhook is unreachable β safer for security policiesIgnore: request allowed if webhook is unreachable β safer for non-critical checks
β οΈ A webhook with failurePolicy: Fail that crashes takes down all object creation for its matched resources. Always deploy webhooks with redundancy and test failover.Real Example: Istio Sidecar Injection
Istio's automatic sidecar injection is implemented as a MutatingAdmissionWebhook:
- You label a namespace:
kubectl label ns myapp istio-injection=enabled - When a Pod is created in that namespace, apiserver calls the Istio webhook
- The webhook patches the Pod spec to add the
istio-proxysidecar container andistio-initinit container - The mutated Pod spec is stored in etcd β kubectl get pod shows both containers