Mutating vs Validating Webhooks in Kubernetes

Published: (February 12, 2026 at 02:00 AM EST)
4 min read
Source: Dev.to

Source: Dev.to

Admission Controller Phases

What Are Admission Controllers?

An Admission Controller is code that intercepts requests to the Kubernetes API server after authentication and authorization, but before the object is persisted in etcd.

In simpler terms: they’re middleware for the Kubernetes API.

If you run:

kubectl apply -f deployment.yaml

the request flow looks like this:

Request → Authentication → Authorization → Mutating Admission → Schema Validation → Validating Admission → etcd

Admission controllers sit right in the middle of this pipeline.

Two Main Types of Admission Controllers

Mutating Admission Controllers

These can modify incoming requests before they are stored.

Common examples:

  • Adding default labels
  • Injecting sidecar containers (e.g., with Istio)
  • Adding default resource limits
  • Overriding missing fields

Mutating controllers run first. They take your original object and are allowed to change it.

Validating Admission Controllers

These cannot modify the request; they only decide:

  • Allow
  • Reject

Examples:

  • Blocking privileged containers
  • Enforcing image‑registry policies
  • Validating required labels
  • Enforcing naming standards

Validating controllers run after mutation, meaning they see the final version of the object. That ordering is important.

Static vs. Dynamic Admission Controllers

Static (Built‑in)

These ship with Kubernetes and are enabled via the API‑server flag:

--enable-admission-plugins

Common built‑in plugins:

  • NamespaceLifecycle
  • LimitRanger
  • ResourceQuota
  • ServiceAccount

For example, NamespaceLifecycle prevents you from creating new resources in a namespace that is being terminated. Many features people assume are “core Kubernetes behavior” are actually implemented using these built‑in admission controllers.

Dynamic (Webhook‑Based)

These are far more flexible and include:

  • MutatingAdmissionWebhook
  • ValidatingAdmissionWebhook

Instead of embedding logic directly in the API server, Kubernetes calls an external HTTPS service (a webhook) and asks:

  • “Is this request okay?”
  • “Do you want to change anything?”

You can implement custom logic in any language capable of serving HTTPS (Go, Python, Node, etc.). This is where things get powerful.

Why Admission Controllers Matter

In real‑world clusters, most use cases fall into two categories: security and governance.

Security

Admission controllers can enforce a security baseline across your cluster.

Examples:

  • Block containers running as root
  • Allow images only from trusted registries
  • Enforce read‑only root filesystems
  • Prevent hostPath usage

For instance, you can reject any deployment that includes:

securityContext:
  privileged: true

That alone can prevent serious security risks.

Governance & Compliance

They also help enforce organizational standards:

  • Naming conventions
  • Required labels
  • Resource limits
  • Replica restrictions

For example, you can enforce that every deployment must include:

labels:
  environment: production

No label? No deploy. Simple. Effective.

Real‑World Example: Ingress Controllers

When installing an ingress controller like F5 NGINX Ingress Controller, you’ll notice it creates:

  • MutatingWebhookConfiguration
  • ValidatingWebhookConfiguration

Why? Because Kubernetes doesn’t understand NGINX‑specific configuration logic.

The webhook:

  • Validates ingress annotations
  • Prevents invalid configurations
  • Stops broken NGINX reloads
  • Protects production traffic

Without this layer, a bad Ingress definition could generate an invalid NGINX config and impact live traffic. The webhook is your safety net.

How Mutating and Validating Work Together

Suppose you create a Deployment like this:

replicas: 1

What might happen:

  1. A mutating webhook changes replicas to 3.
  2. A validating webhook checks that replicas is not greater than 5.
    • If valid → the object is stored in etcd.

This layered approach ensures:

  • Defaults are applied
  • Policies are enforced
  • Broken configurations never reach the cluster state

Enabling Admission Controllers

On the API server, enable them using:

--enable-admission-plugins=MutatingAdmissionWebhook,ValidatingAdmissionWebhook

To verify webhook support:

kubectl api-versions | grep admissionregistration.k8s.io

If you see:

admissionregistration.k8s.io/v1

you’re good to go.

Writing Your Own Admission Controller

If you want to build one yourself, here’s the high‑level flow:

  1. Build an HTTPS service
  2. Accept AdmissionReview objects
  3. Return
    • allowed: true/false
    • Optional: JSON patch (for mutation)
  4. Register it using
    • MutatingWebhookConfiguration or
    • ValidatingWebhookConfiguration

Your webhook must:

  • Use TLS
  • Be reachable inside the cluster
  • Include a CA bundle in its configuration

Once configured, Kubernetes will call your service every time matching resources are created, updated, or deleted.

Final Thoughts

Admission Controllers are one of the most powerful — and often overlooked — features in Kubernetes.
They give you a programmable control layer inside the API server.

If you’re running Kubernetes in production and not leveraging admission controllers, you’re relying entirely on developers to “do the right thing.” And we all know how that usually goes.

Use them wisely — your cluster becomes significantly safer and more predictable.

0 views
Back to Blog

Related posts

Read more »

Cast Your Bread Upon the Waters

!Cover image for Cast Your Bread Upon the Watershttps://media2.dev.to/dynamic/image/width=1000,height=420,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fdev-t...