CKAD — Sidecar Pattern

2 minute read

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 →

Updated: