- Create a webhook namespace and TLS secret.
- Deploy a webhook server and service.
- Apply a MutatingWebhookConfiguration that injects
runAsNonRoot: trueandrunAsUser: 1234when a Pod has no security context. - Verify behavior across three Pod test cases: default (mutated), explicit override, and conflicting settings (rejected).
- Identify which admission controllers are mutating vs validating
- NamespaceAutoProvision is a mutating admission controller (it creates or modifies resources, e.g., auto-creating a namespace).
- namespace-exists (or similar) is a validating admission controller (it checks whether a namespace exists and rejects requests if validation fails).
Mutating admission webhooks run before validating admission webhooks. Any mutation applied by the mutating webhook is what validating webhooks will evaluate.
- Create the webhook namespace
webhook-demo:
- Create a TLS secret for the webhook server
webhook-demo using those files:
- Deploy the webhook server Deployment and Service
- Inspect and apply the provided MutatingWebhookConfiguration
CREATE operations and routes to the webhook-server service at /mutate. The important rule and clientConfig look like:
The example manifest may use
admissionregistration.k8s.io/v1beta1. On modern Kubernetes clusters, update your manifests to admissionregistration.k8s.io/v1 to avoid deprecation and compatibility issues. See the Kubernetes admission webhook docs for details.- What the webhook does (behavior summary)
- If a Pod is created without
securityContextsettings (runAsNonRoot/runAsUser), the webhook mutates the Pod spec to set:runAsNonRoot: truerunAsUser: 1234
- If a Pod explicitly sets
runAsNonRoot: false(allow root), the webhook respects that explicit setting and does not override it. - If a Pod has conflicting settings (e.g.,
runAsNonRoot: trueandrunAsUser: 0), the webhook rejects the request because the configuration is logically inconsistent.
- Test 1 — Pod with no securityContext (mutating webhook applies defaults)
pod-with-defaults.yaml (no securityContext):
runAsNonRoot: truerunAsUser: 1234
- Test 2 — Pod with explicit override allowing root
pod-with-override.yaml explicitly allows root:
runAsNonRoot: false, the mutating webhook does not inject defaults—explicit configuration wins. Behavior is the same with or without the webhook for this case.
- Test 3 — Pod with conflicting settings (rejected by validation)
pod-with-conflict.yaml intentionally conflicts:
runAsNonRoot: true conflicts with runAsUser: 0:
Summary
- Mutating admission webhooks can inject secure defaults (e.g., non-root UID and
runAsNonRoot: true) to resources that omit them. - Validating admission webhooks (or validation logic within the webhook) detect and reject logically inconsistent or insecure configurations.
- Always use
admissionregistration.k8s.io/v1for admission webhook configuration manifests on modern Kubernetes clusters to avoid deprecation issues.
- Kubernetes admission controllers overview
- MutatingAdmissionWebhook and ValidatingAdmissionWebhook docs
When developing or deploying admission webhooks, remember to:
- Keep TLS certificates current and load the CA bundle into your webhook configuration.
- Test webhook ordering: mutating first, validating second.
- Use
admissionregistration.k8s.io/v1manifests for compatibility with recent Kubernetes versions.