CKA Certification Course - Certified Kubernetes Administrator

Scheduling

2025 Updates Solution Validating and Mutating Admission Controllers

In this lesson, we walk through a lab designed to demonstrate the concepts of validating and mutating admission controllers in Kubernetes. You will learn how these controllers operate and how to deploy configurations that enforce security policies.

Distinguishing Admission Controllers

The lab begins with a question on the differences between mutating and validating admission controllers. The correct answer is that the "namespace auto-provision" admission controller is mutating because it creates or modifies a resource, while the "namespace exists" admission controller is validating since it checks for the presence of a namespace. This distinction is key to understanding how admission controllers intercept and process Kubernetes API requests.

The image shows a KodeKloud practice test interface with a terminal and a question about mutating and validating admission controllers.

Next, the lab explores the invocation flow of admission controllers. The mutating controller is invoked first, followed by the validating controller, establishing a clear processing order for API requests.

The image shows a KodeKloud practice test interface with a terminal and a multiple-choice question about the flow of invocation of admission controllers.

Step 1: Creating the Namespace

Begin by creating a new namespace called "webhook-demo". This namespace will isolate all resources related to the webhook demo. Use the command below:

kubectl create ns webhook-demo

To confirm that the namespace was created successfully, list all namespaces:

kubectl get ns

Example output:

root@controlplane ~ ➜ kubectl create ns webhook-demo
namespace/webhook-demo created

root@controlplane ~ ➜ kubectl get ns
NAME              STATUS   AGE
default           Active   37m
kube-node-lease   Active   37m
kube-public       Active   37m
kube-system       Active   37m
webhook-demo      Active   3s

Step 2: Creating the TLS Secret

A TLS secret is required for secure webhook communication. Create the secret "webhook-server-tls" in the "webhook-demo" namespace with the certificate and key located at the specified paths:

kubectl -n webhook-demo create secret tls webhook-server-tls \
  --cert "/root/keys/webhook-server-tls.crt" \
  --key "/root/keys/webhook-server-tls.key"

After execution, you should receive a confirmation that the secret has been created.

Step 3: Deploying the Webhook

Deploy the Webhook Server

Apply the provided deployment definition in "webhook-deployment.yaml" as follows:

kubectl apply -f webhook-deployment.yaml

Create the Service for the Webhook

Next, deploy the service that will enable communication with the webhook server. Use the configuration in "webhook-service.yaml":

kubectl apply -f webhook-service.yaml

Configure the Webhook

A mutating webhook configuration is specified in "webhook-configuration.yaml". This configuration sets up the webhook to intercept CREATE operations on pods. An excerpt of the configuration is shown below:

webhooks:
  - name: webhook-server.webhook-demo.svc
    clientConfig:
      service:
        name: webhook-server
        namespace: webhook-demo
        path: "/mutate"
      caBundle: LS0tLS1CRUdJTiBDRVJUUzJ0QFUrS0tLS0tck1JSURqekNDQWl1Z0F3UJBZ0lV...
    rules:
      - operations: [ "CREATE" ]
        apiGroups: [""]
        apiVersions: [ "v1" ]
        resources: ["pods"]

Apply the webhook configuration:

kubectl apply -f webhook-configuration.yaml

Webhook Behavior

The demo webhook enforces the following rules:

  • Denies pod requests where the container runs as root if no security context is provided.
  • Automatically mutates pods by setting runAsNonRoot to true and runAsUser to 1234 when not explicitly specified.
  • Permits running as root only if the security context explicitly sets runAsNonRoot to false.

Step 4: Testing the Webhook with Different Pod Configurations

Pod with Default Security Settings

Deploy a pod without any security context using the "pod-with-defaults.yaml" definition. Without the webhook, this pod would run as the root user. The webhook mutates the pod to enforce best practices.

# A pod with no securityContext specified.
# Without the webhook, it would run as user root (0). The webhook mutates it.
apiVersion: v1
kind: Pod
metadata:
  name: pod-with-defaults
  labels:
    app: pod-with-defaults
spec:
  restartPolicy: OnFailure
  containers:
    - name: busybox
      image: busybox
      command: ["sh", "-c", "echo I am running as user $(id -u)"]

Deploy the pod:

kubectl apply -f pod-with-defaults.yaml

Inspect the pod configuration to ensure that runAsNonRoot is set to true and runAsUser is set to 1234:

kubectl get pods pod-with-defaults -o yaml

Pod with an Explicitly Overridden Security Context

Next, test a pod configured to allow running as root. The "pod-with-override.yaml" file has its security context explicitly set to allow root execution by setting runAsNonRoot to false:

apiVersion: v1
kind: Pod
metadata:
  name: pod-with-override
  labels:
    app: pod-with-override
spec:
  restartPolicy: OnFailure
  securityContext:
    runAsNonRoot: false
  containers:
    - name: busybox
      image: busybox
      command: ["sh", "-c", "echo I am running as user $(id -u)"]

Deploy the pod:

kubectl apply -f pod-with-override.yaml

Pod with Conflicting Security Context

Finally, demonstrate the validation process by deploying a pod that conflicts with the established security policies. The "pod-with-conflict.yaml" file sets runAsNonRoot to true while specifying runAsUser as 0, which should be rejected by the webhook:

apiVersion: v1
kind: Pod
metadata:
  name: pod-with-conflict
  labels:
    app: pod-with-conflict
spec:
  restartPolicy: OnFailure
  securityContext:
    runAsNonRoot: true
    runAsUser: 0
  containers:
    - name: busybox
      image: busybox
      command: ["sh", "-c", "echo I am running as user $(id -u)"]

Deploy the pod:

kubectl apply -f pod-with-conflict.yaml

Deployment Rejection

If a pod conflicts with the security context policy, the creation request will be rejected with an error message similar to:

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 verifies that the validating admission controller is actively enforcing the security policy by rejecting pods with invalid configurations.


This concludes the lab session on validating and mutating admission controllers in Kubernetes. For more detailed information, please refer to the Kubernetes Documentation.

Watch Video

Watch video content

Previous
2025 Updates Validating and Mutating Admission Controllers