Introduction
In a Kubernetes environment, ensuring compliance with security and operational policies is critical. Admission controllers provide a mechanism to enforce organizational policies at the API level before resources are created, modified, or deleted.
In this post, we will build a simple admission controller in Minikube. Instead of using a custom image, we will leverage a lightweight existing image (busybox) to demonstrate the webhook concept.
Why Use Admission Controllers?
Admission controllers help organizations enforce policies such as:
Blocking privileged containers
Enforcing resource limits
Validating labels and annotations
Restricting image sources
By implementing an admission webhook, we can inspect and validate incoming requests before they are persisted in the Kubernetes cluster.
Step 1: Create the Webhook Deployment
We will use busybox as the container image instead of a custom-built admission webhook image.
Create webhook-deployment.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: admission-webhook
spec:
replicas: 1
selector:
matchLabels:
app: admission-webhook
template:
metadata:
labels:
app: admission-webhook
spec:
containers:
- name: webhook
image: busybox
command: ["/bin/sh", "-c", "echo Webhook Running; sleep 3600"]
ports:
- containerPort: 443
volumeMounts:
- name: certs
mountPath: "/certs"
readOnly: true
volumes:
- name: certs
secret:
secretName: admission-webhook-secret
Key Changes:
- Using busybox instead of a custom image
- The container prints “Webhook Running” and sleeps for 1 hour
- Mounting a secret to hold TLS certificates
Step 2: Generate TLS Certificates
Kubernetes requires admission webhooks to communicate securely. We need to generate TLS certificates for our webhook server.
Run the following commands in Minikube:
openssl req -x509 -newkey rsa:4096 -keyout tls.key -out tls.crt -days 365 -nodes -subj "/CN=admission-webhook.default.svc"
kubectl create secret tls admission-webhook-secret --cert=tls.crt --key=tls.key
This creates a self-signed certificate and stores it in a Kubernetes Secret.
Step 3: Define the MutatingWebhookConfiguration
Now, let’s create a Kubernetes webhook configuration that tells the API server when to invoke our webhook.
Create webhook-configuration.yaml:
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
name: admission-webhook
webhooks:
- name: webhook.default.svc
clientConfig:
service:
name: admission-webhook
namespace: default
path: "/mutate"
caBundle: ""
rules:
- apiGroups: [""]
apiVersions: ["v1"]
operations: ["CREATE"]
resources: ["pods"]
admissionReviewVersions: ["v1"]
sideEffects: None
Key Details:
- The webhook applies to all Pods created in the cluster
- The webhook will be called whenever a Pod is created
- The caBundle field will be populated later
Apply the webhook configuration:
kubectl apply -f webhook-configuration.yaml
Step 4: Test the Webhook
Let’s check if the webhook is being triggered when a new Pod is created.
Create a test Pod:
apiVersion: v1
kind: Pod
metadata:
name: test-pod
spec:
containers:
- name: test
image: busybox
command: ["sleep", "3600"]
Apply the Pod:
kubectl apply -f test-pod.yaml
If the webhook is working correctly, the admission controller should intercept the request and either allow or reject it based on the configured policies.
Step 5: Debugging and Logs
To check the logs of the webhook, run:
kubectl logs -l app=admission-webhook
If the webhook is not working as expected, ensure:
- The webhook deployment is running (kubectl get pods)
- The secret exists (kubectl get secret admission-webhook-secret)
- The webhook configuration is applied (kubectl get mutatingwebhookconfigurations)
Conclusion
We successfully set up a custom Kubernetes admission controller. Instead of a custom-built webhook image, we used a minimal container (busybox) to simulate webhook functionality.
Key Takeaways:
- Admission controllers enforce security policies before resources are created
- Webhooks provide dynamic validation and policy enforcement
- Minikube can be used to test webhooks without pushing images to remote registries
What’s your experience with admission controllers? Let’s discuss!![]()