Skip to content

2.14 Validating and Mutating Admission Controllers

Admission Controllers are policy checkpoints inside the Kubernetes API server.
They run after Authentication and Authorization and before an object is finally created.

Their job is simple:

  • βœ… Mutating controllers β†’ can CHANGE the request
  • πŸ›‘οΈ Validating controllers β†’ can ALLOW or REJECT the request

Think of them as a final quality + security gate for every Kubernetes object.


πŸ”„ Where They Sit in the Request Flow

Kubernetes API Server Flow

When you run:

kubectl apply -f pod.yaml

The API server processes it in this order:

  1. Authentication β€” Who are you?
  2. Authorization (RBAC) β€” Are you allowed?
  3. Mutating Admission Controllers β€” Modify request if needed
  4. Validating Admission Controllers β€” Approve or reject
  5. etcd β€” Object stored

Info

Mutation happens first, then validation checks the final modified object.


πŸ§ͺ Two Types β€” Quick Comparison

  • Can modify objects
  • Add missing fields
  • Inject defaults
  • Add labels / sidecars
  • Runs first
  • Example: DefaultStorageClass
  • Cannot modify objects
  • Only allow or reject
  • Enforce rules
  • Block unsafe configs
  • Runs after mutation
  • Example: NamespaceLifecycle

🧬 Mutating Admission Controllers β€” Easy Example

A mutating controller can auto‑fill missing fields.

Example: DefaultStorageClass

You create a PVC without storageClassName:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: data-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi

Mutating controller updates it internally to:

spec:
  storageClassName: standard

Example

You didn’t specify it β€” Kubernetes adds it automatically using a mutating controller.


πŸ›‘οΈ Validating Admission Controllers β€” Easy Example

Validating controllers do not change anything β€” they only approve or reject.

Example: NamespaceLifecycle

kubectl run nginx --image=nginx -n blue

Result:

Error: namespace "blue" not found

Why?

  • AuthN βœ…
  • AuthZ βœ…
  • Validation ❌ (namespace does not exist)

Note

The request is rejected β€” nothing is modified.


⚠️ Why Mutation Runs Before Validation

Consider two rules:

  • Mutating controller β†’ create namespace if missing
  • Validating controller β†’ reject if namespace missing

Correct order:

Mutate β†’ namespace created
Validate β†’ now it exists β†’ pass

Wrong order would always fail.

Tip

Kubernetes always runs mutating first, validating second.


🌐 External Admission Controllers (Webhooks)

You can create your own custom admission logic using webhooks.

Two webhook types:

  • MutatingAdmissionWebhook
  • ValidatingAdmissionWebhook

Kubernetes sends the request to your webhook server β†’ your code decides.


πŸ—οΈ Webhook Flow (Concept)

API Server
   β”‚
Built‑in Admission Controllers
   β”‚
Webhook Call β†’ Your Webhook Service
   β”‚
Allow / Reject / Patch

Abstract

Your webhook server can run inside the cluster or externally.


🧾 Mutating Webhook β€” YAML Example

apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
  name: add-label-webhook
webhooks:
  - name: add-label.example.com
    clientConfig:
      service:
        name: webhook-service
        namespace: default
        path: /mutate
      caBundle: <BASE64_CA_CERT>
    rules:
      - operations: ["CREATE"]
        apiGroups: [""]
        apiVersions: ["v1"]
        resources: ["pods"]

Use cases:

  • Add labels automatically
  • Inject sidecars
  • Add security context
  • Set defaults

🧾 Validating Webhook β€” YAML Example

apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
  name: validate-image-webhook
webhooks:
  - name: validate.example.com
    clientConfig:
      service:
        name: webhook-service
        namespace: default
        path: /validate
      caBundle: <BASE64_CA_CERT>
    rules:
      - operations: ["CREATE"]
        apiGroups: [""]
        apiVersions: ["v1"]
        resources: ["pods"]

Use cases:

  • Block latest tag
  • Block root user containers
  • Enforce labels
  • Restrict registries

🧠 What Your Webhook Server Receives

Webhook receives an AdmissionReview JSON with:

  • user info
  • operation type
  • object spec
  • resource type

It must reply:

Allow

{ "allowed": true }

Reject

{
  "allowed": false,
  "status": { "message": "Policy violation" }
}

Mutating webhooks can also return a JSON patch.


πŸ§ͺ Mutation Patch Concept

Example patch instruction:

add β†’ /metadata/labels/user β†’ "john"

Result:

Pod gets label automatically before creation.


βœ… Key Takeaways

Summary

  • Admission Controllers = final policy gate
  • Two types: Mutating and Validating
  • Mutating = modify requests
  • Validating = allow or reject only
  • Mutation runs before validation
  • Webhooks enable custom logic
  • Used for security, defaults, and governance