Skip to main content

Admission Controllers: The Final Gatekeepers

In the Kubernetes API request lifecycle, Admission Controllers sit between Authorization and Persistence. While RBAC determines "Who" can perform an action, Admission Controllers determine "What" that action contains and whether it complies with cluster-wide governance.


1. ARCHITECTURAL POSITIONING

An Admission Controller intercepts requests to the API server only after the request is Authenticated and Authorized.

1.1 The Request Pipeline

Admission Control is strictly for Write operations (CREATE, UPDATE, DELETE, CONNECT). It has no visibility into Read operations (GET, LIST, WATCH).

.


2. THE TWO-PHASE LIFECYCLE

Kubernetes executes admission controllers in a strict, two-phase serial sequence.

Phase 1: Mutating Admission

  • Purpose: To "patch" or modify the object before it is validated.
  • Examples: Injecting an Istio sidecar, adding default resource limits, or attaching node affinity rules.
  • Internal Detail: If a mutating controller changes the object, Phase 1 may trigger Reinvocation, ensuring that all mutating controllers see the "final" intended state.

Phase 2: Validating Admission

  • Purpose: To "Accept" or "Reject" the request based on hard policies.
  • Examples: Ensuring no privileged containers are used, checking ResourceQuotas, or validating that labels exist.
  • Constraint: Validating controllers cannot modify the object.

3. CRITICAL BUILT-IN CONTROLLERS

While there are over 30 built-in plugins, these are the architectural pillars:

PluginTypeRole
NodeRestrictionValidatingLimits a Kubelet to only modify its own Node and Pods. Prevents cluster-wide lateral movement if a node is compromised.
PodSecurityValidatingImplements Pod Security Standards (Privileged, Baseline, Restricted). Replaces the deprecated PSP.
ResourceQuotaValidatingChecks the incoming request against the Namespace's ResourceQuota budget.
LimitRangerDualInjects default requests/limits (Mutation) and enforces min/max boundaries (Validation).
ServiceAccountMutatingInjects the default ServiceAccount if none is specified.

4. DYNAMIC ADMISSION: WEBHOOKS

When built-in logic is insufficient, Kubernetes uses Admission Webhooks to call external services (e.g., OPA Gatekeeper, Kyverno).

4.1 How Webhooks Work

The API Server sends an AdmissionReview JSON object to the webhook service. The service responds with a uid and an allowed: true/false status.

4.2 JSON Patching (Mutation Mechanics)

Mutating webhooks use JSON Patch (RFC 6902). Instead of sending back the whole object, the webhook sends a list of operations.

Example Patch Response:

"patch": [
{"op": "add", "path": "/spec/containers/1", "value": {"name": "sidecar", "image": "log-agent:v1"}},
{"op": "replace", "path": "/metadata/labels/managed-by", "value": "policy-engine"}
]

5. BIBLE-GRADE YAML: WEBHOOK CONFIGURATION

This manifest defines how the API Server should interact with an external security service.

apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
name: security-policy-checker
webhooks:
- name: check-privileged-containers.company.com
rules:
- apiGroups: [""]
apiVersions: ["v1"]
operations: ["CREATE", "UPDATE"]
resources: ["pods"]
scope: "Namespaced"
clientConfig:
service:
namespace: "security-system"
name: "policy-webhook-svc"
path: "/validate"
caBundle: <BASE64_CA_BUNDLE> # API Server needs this to verify Webhook Cert

# PRODUCTION SETTINGS:
admissionReviewVersions: ["v1"]
sideEffects: None
timeoutSeconds: 5

# FAILSAFE LOGIC:
# Fail: Reject request if Webhook is down (Secure)
# Ignore: Allow request if Webhook is down (Available)
failurePolicy: Fail

namespaceSelector:
matchExpressions:
- key: kubernetes.io/metadata.name
operator: NotIn
values: ["kube-system"] # Do not block critical system pods

6. PRODUCTION HAZARDS & BEST PRACTICES

6.1 The Circular Dependency (The "Deadlock")

Scenario: You have a ValidatingWebhook that checks all Pods. The Webhook itself runs as a Pod in the cluster.

  1. The Cluster reboots.
  2. The API Server tries to start the Webhook Pod.
  3. The API Server calls the Webhook to validate the Webhook Pod.
  4. The Webhook is not running yet.
  5. Result: The Cluster cannot start.
  • Solution: Use namespaceSelector to exclude the kube-system or the webhook's own namespace from the policy.

6.2 Latency Overhead

Every admission webhook adds an HTTP round-trip to every write request.

  • Strategy: Keep webhooks lightweight. Use matchExpressions to only trigger webhooks for specific namespaces or labels to reduce API latency.

6.3 Idempotency

Mutating webhooks must be idempotent. If a request is retried, applying the same patch twice must not result in a corrupted object.


7. TROUBLESHOOTING & NINJA COMMANDS

7.1 Auditing Enabled Plugins

You can see which internal plugins are active by inspecting the API Server process.

kubectl get pods -n kube-system -l component=kube-apiserver -o yaml | grep -i admission-plugins

7.2 Debugging Webhook Failures

If kubectl apply hangs or returns a 500 Internal Server Error, the webhook is likely failing.

# 1. Check if the webhook service has endpoints
kubectl get endpoints -n security-system policy-webhook-svc

# 2. Check the logs of the policy engine
kubectl logs -n security-system -l app=policy-engine

# 3. Bypass a broken webhook (Emergency only - requires API Server access)
# Edit the ValidatingWebhookConfiguration and set failurePolicy: Ignore

7.3 Verifying OPA/Gatekeeper Constraints

If using Gatekeeper, you don't use standard YAML; you use ConstraintTemplates.

# Check for policy violations already in the cluster
kubectl get constraints

8. SUMMARY: AUTHORIZATION VS. ADMISSION

AspectAuthorization (RBAC)Admission Control
FocusSubject (Who is calling?)Object (What is being created?)
ContextUser/Group/Namespace.Full YAML/JSON specification.
ModificationCannot change the request.Mutating can change the request.
ExecutionBefore Admission.After Authorization.