Solution Validating and Mutating Admission Controllers 2025 Updates
This article explores validating and mutating admission controllers, including their configuration, deployment, and testing in a Kubernetes environment.
In this lesson, we will explore the lab on validating and mutating admission controllers. You will learn how these controllers work together, create a namespace and TLS secret, deploy the webhook server with corresponding configurations, and test pod security contexts.
root@controlplane ~ ➜ kubectl get nsNAME STATUS AGEdefault Active 37mkube-node-lease Active 37mkube-public Active 37mkube-system Active 37mwebhook-demo Active 3s
For secure webhook communication, you need to create a TLS secret named webhook-server-tls in the webhook-demo namespace. This secret uses a certificate and key from specific file paths:
Next, configure the mutating webhook with the settings provided in webhook-configuration.yaml. This file defines a webhook that intercepts pod creation events. For instance, it uses the following rule to match create operations for pods:
Warning: admissionregistration.k8s.io/v1beta1 MutatingWebhookConfiguration is deprecated in v1.16+ and will be unavailable in v1.22+. Please use admissionregistration.k8s.io/v1 MutatingWebhookConfiguration.
The webhook is designed to reject any pod request that attempts to run as root without a proper security context. If no runAsNonRoot value is specified, the webhook mutates the pod by setting runAsNonRoot to true and defaults the user ID to 1234. However, if the security context explicitly sets runAsNonRoot to false, the webhook will not override it.
First, test the webhook by deploying a pod without a security context. The file pod-with-defaults.yaml contains a pod definition that, by default, would run as root. However, the webhook mutates it:
Copy
Ask AI
# A pod with no securityContext specified.# Without the webhook, it would run as user root (0). The webhook mutates it.apiVersion: v1kind: Podmetadata: name: pod-with-defaults labels: app: pod-with-defaultsspec: restartPolicy: OnFailure containers: - name: busybox image: busybox command: ["sh", "-c", "echo I am running as user $(id -u)"]
After deployment, inspect the pod configuration (or use kubectl describe pod pod-with-defaults) to confirm that the security context has been mutated — runAsNonRoot should be true and runAsUser should be set to 1234.
Now, deploy a pod that explicitly permits running as root. The file pod-with-override.yaml contains the configuration that sets runAsNonRoot to false, preventing the webhook from applying its defaults:
Copy
Ask AI
# A pod with a securityContext explicitly allowing it to run as root.# The effect of deploying this with and without the webhook is the same.# The explicit setting prevents the webhook from applying more secure defaults.apiVersion: v1kind: Podmetadata: name: pod-with-override labels: app: pod-with-overridespec: restartPolicy: OnFailure securityContext: runAsNonRoot: false containers: - name: busybox image: busybox command: ["sh", "-c", "echo I am running as user $(id -u)"]
Deploying a Pod with a Conflicting Security Context
The final test involves deploying a pod with a conflicting security context. In this scenario, the pod configuration requires the container to run as a non-root user by setting runAsNonRoot to true while explicitly requesting a user ID of 0 (root). Without the webhook, this could lead to a CreateContainerConfigError. With the webhook enabled, the pod creation is rejected:
Copy
Ask AI
# A pod with a conflicting securityContext setting:# It has to run as a non-root user, but we explicitly request a user id of 0 (root).# Without the webhook, the pod could be created but would fail to launch due to an unenforceable# security context, leading to a 'CreateContainerConfigError' status.# With the webhook, the creation of this pod is outright rejected.apiVersion: v1kind: Podmetadata: name: pod-with-conflict labels: app: pod-with-conflictspec: restartPolicy: OnFailure securityContext: runAsNonRoot: true runAsUser: 0 containers: - name: busybox image: busybox command: ["sh", "-c", "echo I am running as user $(id -u)"]
Error from server: error when creating "pod-with-conflict.yaml": admission webhook "webhook-server.webhook-demo.svc" denied the request: runAsNonRoot specified, but runAsUser set to 0 (the root user)
This confirms that the webhook correctly rejected the pod due to the conflicting security settings.