Understanding and Implementing Kubernetes Admission Controllers with a Sidecar Injection Example
This article explains the purpose and phases of Kubernetes Admission Controllers, outlines their security, governance, and configuration management benefits, and provides a step‑by‑step guide—including TLS certificate creation, a Go HTTPS webhook server, and MutatingWebhookConfiguration YAML—to inject a sidecar container into pods.
Kubernetes Admission Controllers are webhook mechanisms that allow users to modify or validate resource objects before they are persisted to etcd, enabling custom security, governance, and configuration management policies.
The two types of admission webhooks are:
Mutation admission webhook : modifies resource objects.
Validation admission webhook : validates resource objects.
To use an Admission Controller you must ensure the API server has admission plugins enabled, provide TLS/SSL certificates (self‑signed is acceptable), build an HTTPS server that implements the webhook logic, and configure either a MutatingWebhookConfiguration or ValidatingWebhookConfiguration to tell Kubernetes how to communicate with your server.
Sidecar Injection Example
1. Verify admission plugins are enabled
Run the following command to list admission resources:
kubectl api-resources | grep admissionTypical output shows mutatingwebhookconfigurations and validatingwebhookconfigurations , confirming support. Ensure the API server is started with the flag:
--enable-admission-plugins=MutatingAdmissionWebhook,ValidatingAdmissionWebhook2. Create TLS/SSL certificates
Generate a root CA and a server certificate in a directory such as ~/certs :
Create the root CA: openssl genrsa -des3 -out rootCA.key 4096 openssl req -x509 -new -nodes -key rootCA.key -sha256 -days 1024 -out rootCA.crt
Create the server certificate signing request and key: openssl genrsa -out mylocal.com.key 2048 openssl req -new -key mylocal.com.key -out mylocal.com.csr
Sign the server certificate with the root CA, specifying the internal IP address: echo subjectAltName = IP:192.168.100.22 > extfile.cnf openssl x509 -req -in mylocal.com.csr \ -CA rootCA.crt -CAkey rootCA.key \ -CAcreateserial -out mylocal.com.crt \ -days 500 -extfile extfile.cnf
After these steps you will have the following files:
rootCA.key : root CA private key
rootCA.crt : root CA certificate
rootCA.srl : serial number file
mylocal.com.key : server private key
mylocal.com.csr : certificate signing request
mylocal.com.crt : server certificate
3. Build a simple HTTPS server in Go
The webhook receives an AdmissionReview request and must return an AdmissionResponse . The example below adds a sidecar container (busybox) to the pod's spec.containers array using a JSONPatch.
package main
import (
"encoding/json"
"log"
"net/http"
v1 "k8s.io/api/admission/v1"
corev1 "k8s.io/api/core/v1"
)
// patchOperation is an operation of a JSON patch, see https://tools.ietf.org/html/rfc6902 .
type patchOperation struct {
Op string `json:"op"`
Path string `json:"path"`
Value interface{} `json:"value,omitempty"`
}
var (
certFile = "/Users/wy/certs/mylocal.com.crt"
keyFile = "/Users/wy/certs/mylocal.com.key"
)
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
defer req.Body.Close()
var admissionReview v1.AdmissionReview
err := json.NewDecoder(req.Body).Decode(&admissionReview)
if err != nil {
log.Fatal(err)
}
var patches []patchOperation
patches = append(patches, patchOperation{
Op: "add",
Path: "/spec/containers/-",
Value: &corev1.Container{
Image: "busybox",
Name: "sidecar",
},
})
patchBytes, err := json.Marshal(patches)
if err != nil {
log.Fatal(err)
}
var PatchTypeJSONPatch v1.PatchType = "JSONPatch"
admissionReview.Response = &v1.AdmissionResponse{
UID: admissionReview.Request.UID,
Allowed: true,
Patch: patchBytes,
PatchType: &PatchTypeJSONPatch,
}
// Return the AdmissionReview with a response as JSON.
bytes, err := json.Marshal(&admissionReview)
if err != nil {
log.Fatal(err)
}
w.Write(bytes)
})
log.Printf("About to listen on 8443. Go to https://127.0.0.1:8443/")
err := http.ListenAndServeTLS(":8443", certFile, keyFile, nil)
log.Fatal(err)
}4. Configure MutatingWebhookConfiguration
Create a MutatingWebhookConfiguration that points to the HTTPS server and defines the rules for triggering the webhook (e.g., on pod creation with specific labels).
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
name: test-sidecar-injector
webhooks:
- name: sidecar-injector.mytest.io
admissionReviewVersions:
- v1 # must match the server version
sideEffects: "NoneOnDryRun"
reinvocationPolicy: "Never"
timeoutSeconds: 30
objectSelector:
matchExpressions:
- key: run
operator: In
values:
- "nginx"
rules:
- apiGroups:
- ""
apiVersions:
- v1
operations:
- CREATE
resources:
- pods
scope: "*"
clientConfig:
caBundle: ${CA_PEM_B64}
url: https://192.168.100.22:8443/ # point to the local serverReplace ${CA_PEM_B64} with the base64‑encoded content of rootCA.crt (obtainable via openssl base64 -A -in rootCA.crt ).
Finally, test the setup by creating a pod:
kubectl run nginx --image=nginxInspect the created pod and you will see the injected sidecar container alongside the original container.
Conclusion
After reading this guide you should understand the basic workflow of Kubernetes Admission Controllers and how they are leveraged by many open‑source projects such as Istio.
System Architect Go
Programming, architecture, application development, message queues, middleware, databases, containerization, big data, image processing, machine learning, AI, personal growth.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.