What Are Admission Controllers in Kubernetes?
Admission controllers are plugins that intercept API requests after authentication and authorization but before the object is persisted to etcd. They can validate or mutate requests. Kubernetes includes many built-in controllers, and you can add custom ones via webhooks.
Detailed Answer
The API Request Pipeline
Every request to the Kubernetes API server passes through this pipeline:
Client Request
-> Authentication (who are you?)
-> Authorization (are you allowed?)
-> Mutating Admission (modify the request)
-> Schema Validation (is the object valid?)
-> Validating Admission (apply policy checks)
-> Persistence to etcd
Admission controllers operate in the two admission phases. If any admission controller rejects a request, the API server returns an error and the object is not created.
Built-in Admission Controllers
Kubernetes ships with numerous compiled-in admission controllers. Important ones include:
| Controller | Type | Purpose | |---|---|---| | NamespaceLifecycle | Validating | Prevents operations in terminating or non-existent namespaces | | LimitRanger | Mutating | Applies default resource requests/limits from LimitRange objects | | ServiceAccount | Mutating | Auto-mounts service account tokens and sets default SA | | DefaultStorageClass | Mutating | Assigns default StorageClass to PVCs without one | | ResourceQuota | Validating | Enforces resource quotas per namespace | | PodSecurity | Validating | Enforces Pod Security Standards | | MutatingAdmissionWebhook | Mutating | Calls external mutating webhooks | | ValidatingAdmissionWebhook | Validating | Calls external validating webhooks |
# View enabled admission controllers
kubectl -s https://<api-server>:6443 api-versions
# Check API server flags:
# --enable-admission-plugins=NamespaceLifecycle,LimitRanger,...
Mutating Admission Webhooks
Mutating webhooks modify API requests before they are validated. The most common use case is sidecar injection (e.g., Istio's envoy proxy).
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
name: sidecar-injector
webhooks:
- name: inject.sidecar.io
admissionReviewVersions: ["v1"]
clientConfig:
service:
name: sidecar-injector
namespace: sidecar-system
path: /inject
caBundle: <base64-encoded-CA>
rules:
- operations: ["CREATE"]
apiGroups: [""]
apiVersions: ["v1"]
resources: ["pods"]
namespaceSelector:
matchLabels:
sidecar-injection: enabled
failurePolicy: Fail
sideEffects: None
timeoutSeconds: 10
This webhook intercepts Pod creation in namespaces labeled sidecar-injection: enabled and can modify the Pod spec to add a sidecar container.
Validating Admission Webhooks
Validating webhooks check requests against policies and accept or reject them. They cannot modify the request.
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
name: image-policy
webhooks:
- name: validate.images.io
admissionReviewVersions: ["v1"]
clientConfig:
service:
name: image-validator
namespace: policy-system
path: /validate
caBundle: <base64-encoded-CA>
rules:
- operations: ["CREATE", "UPDATE"]
apiGroups: [""]
apiVersions: ["v1"]
resources: ["pods"]
failurePolicy: Fail
sideEffects: None
timeoutSeconds: 5
ValidatingAdmissionPolicy (Native CEL-based)
Kubernetes 1.30+ supports ValidatingAdmissionPolicy, which allows writing validation rules directly in CEL (Common Expression Language) without deploying a webhook server:
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:
name: require-non-root
spec:
failurePolicy: Fail
matchConstraints:
resourceRules:
- apiGroups: [""]
apiVersions: ["v1"]
operations: ["CREATE"]
resources: ["pods"]
validations:
- expression: "object.spec.securityContext.runAsNonRoot == true"
message: "Pods must set runAsNonRoot: true"
- expression: "object.spec.containers.all(c, c.securityContext.allowPrivilegeEscalation == false)"
message: "All containers must set allowPrivilegeEscalation: false"
---
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicyBinding
metadata:
name: require-non-root-binding
spec:
policyName: require-non-root
validationActions:
- Deny
matchResources:
namespaceSelector:
matchLabels:
environment: production
OPA Gatekeeper
OPA (Open Policy Agent) Gatekeeper is a popular third-party admission controller that uses Rego policies:
# Install Gatekeeper
kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper/v3.15.0/deploy/gatekeeper.yaml
# Define a constraint template
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
name: k8srequiredlabels
spec:
crd:
spec:
names:
kind: K8sRequiredLabels
validation:
openAPIV3Schema:
type: object
properties:
labels:
type: array
items:
type: string
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package k8srequiredlabels
violation[{"msg": msg}] {
provided := {label | input.review.object.metadata.labels[label]}
required := {label | label := input.parameters.labels[_]}
missing := required - provided
count(missing) > 0
msg := sprintf("Missing required labels: %v", [missing])
}
---
# Apply the constraint
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequiredLabels
metadata:
name: require-team-label
spec:
match:
kinds:
- apiGroups: [""]
kinds: ["Namespace"]
parameters:
labels:
- "team"
- "environment"
Webhook Best Practices
- High availability: Run webhook servers with multiple replicas and proper health checks.
- Timeouts: Keep timeouts short (5-10 seconds). Long timeouts slow down all API operations.
- Failure policy: Use
Failfor security-critical webhooks,Ignorefor non-critical ones. - Namespace selectors: Exclude
kube-systemfrom webhooks to prevent locking yourself out. - Dry-run support: Implement
sideEffects: Noneto supportkubectl --dry-run=server.
# Always exclude kube-system to avoid breaking the cluster
namespaceSelector:
matchExpressions:
- key: kubernetes.io/metadata.name
operator: NotIn
values:
- kube-system
Why Interviewers Ask This
Interviewers ask this to assess your understanding of the Kubernetes API request pipeline and your ability to implement custom policies and governance at the cluster level.
Common Follow-Up Questions
Key Takeaways
- Admission controllers sit between authorization and persistence in the API pipeline
- Mutating webhooks run before validating webhooks
- Built-in controllers handle defaults; webhooks enable custom policy enforcement