CKAD — Sidecar Pattern
What is the Sidecar Pattern?
A sidecar container runs alongside the main application container for the entire Pod lifetime. It extends or enhances the main container without changing its code.
Think of it like a motorcycle sidecar — attached to the main vehicle, providing additional capability.
Common Use Cases
| Use Case | Sidecar Does | Example |
|---|---|---|
| Log shipping | Reads logs from shared volume, forwards to logging service | Fluentd, Filebeat |
| Proxy | Handles TLS termination, auth, or traffic routing | Envoy, Nginx |
| Config reloading | Watches for config changes and signals the app | Config-reloader |
| Monitoring agent | Collects metrics and exports to monitoring system | Prometheus exporter |
| Security | Handles certificate rotation, secret injection | Vault agent |
Example: Log Shipper Sidecar
apiVersion: v1
kind: Pod
metadata:
name: app-with-logging
labels:
app: web
spec:
containers:
- name: app
image: busybox:1.36
command: ["/bin/sh", "-c"]
args:
- |
while true; do
echo "$(date) - Request processed" >> /var/log/app.log
sleep 5
done
volumeMounts:
- name: log-volume
mountPath: /var/log
- name: log-shipper
image: busybox:1.36
command: ["/bin/sh", "-c"]
args:
- |
tail -f /var/log/app.log
volumeMounts:
- name: log-volume
mountPath: /var/log
volumes:
- name: log-volume
emptyDir: {}
kubectl apply -f app-with-logging.yaml
# Check the log shipper is streaming logs
kubectl logs app-with-logging -c log-shipper
# Expected output:
# Mon Feb 10 10:00:00 UTC 2025 - Request processed
# Mon Feb 10 10:00:05 UTC 2025 - Request processed
The app container writes logs to a shared volume. The log-shipper sidecar reads and forwards those logs. Neither container knows about the other’s implementation.
Example: NGINX Reverse Proxy Sidecar
apiVersion: v1
kind: Pod
metadata:
name: app-with-proxy
spec:
containers:
- name: app
image: hashicorp/http-echo
args: ["-text=Hello from the app", "-listen=:5678"]
- name: proxy
image: nginx:1.27
ports:
- containerPort: 80
volumeMounts:
- name: nginx-config
mountPath: /etc/nginx/conf.d
initContainers:
- name: config-writer
image: busybox:1.36
command: ['sh', '-c']
args:
- |
cat > /config/default.conf << 'EOF'
server {
listen 80;
location / {
proxy_pass http://localhost:5678;
}
}
EOF
volumeMounts:
- name: nginx-config
mountPath: /config
volumes:
- name: nginx-config
emptyDir: {}
Traffic arrives at the NGINX proxy on port 80, which forwards it to the app on localhost:5678. The app doesn’t need to handle TLS, rate limiting, or other proxy concerns.
Kubernetes Native Sidecar Containers (v1.29+)
Starting with Kubernetes 1.29, you can define native sidecar containers using initContainers with restartPolicy: Always. These sidecars:
- Start before the main container
- Stay running for the Pod’s lifetime
- Are properly terminated during Pod shutdown
- Are restarted if they crash
Native Sidecar Example
apiVersion: v1
kind: Pod
metadata:
name: native-sidecar
spec:
initContainers:
- name: log-agent
image: busybox:1.36
restartPolicy: Always
command: ["/bin/sh", "-c", "tail -f /var/log/app.log"]
volumeMounts:
- name: logs
mountPath: /var/log
containers:
- name: app
image: busybox:1.36
command: ["/bin/sh", "-c"]
args: ["while true; do echo $(date) >> /var/log/app.log; sleep 5; done"]
volumeMounts:
- name: logs
mountPath: /var/log
volumes:
- name: logs
emptyDir: {}
Traditional vs Native Sidecar
| Feature | Traditional Sidecar | Native Sidecar (v1.29+) |
|---|---|---|
| Defined in | containers |
initContainers with restartPolicy: Always |
| Start order | Starts alongside main container | Starts before main container |
| Shutdown | Stops alongside main container | Properly terminated last |
| Guaranteed running for app startup | No | Yes |
| Restart on crash | Yes | Yes |
Exam tip: If your exam environment uses Kubernetes 1.29+, you may see native sidecar containers. The key difference is they are defined under initContainers with restartPolicy: Always.
Next: Learn about setup tasks with Init Containers →