• Never put multiple microservices in one Pod: helpers/init only
  • Same Pod: shared localhost network + shared volumes

Patterns

PatternPurposeExample
SidecarAugments/enhances main containerLog shipper, service mesh proxy
Init ContainerRuns to completion before app startsDB migration check, wait-for-service
AmbassadorProxy to simplify external service accessDB proxy, connection pooling
AdapterTransforms output for external consumersConvert app metrics to Prometheus format

Init containers

  • Under spec.initContainers: run before app containers
  • Run sequentially; each must succeed before next
  • Failure → Pod restart, all inits re-run
  • Terminate when done; no probes
  • Status: Init:0/1Init:CrashLoopBackOffRunning

Sidecar + init container example

spec:
  initContainers:
  - name: wait-for-db
    image: busybox
    command: ['sh', '-c', 'until nc -z db-service 5432; do sleep 2; done']
  containers:
  - name: app
    image: myapp:1.0
    volumeMounts:
    - name: shared-logs
      mountPath: /var/log/app
  - name: log-shipper          # SIDECAR
    image: fluent/fluentd:v1.14
    volumeMounts:
    - name: shared-logs
      mountPath: /var/log/app
      readOnly: true
  volumes:
  - name: shared-logs
    emptyDir: {}

Adapter example

spec:
  containers:
  - name: app
    image: myapp:1.0
    volumeMounts:
    - name: raw-logs
      mountPath: /var/log/app
  - name: adapter                    # converts to prometheus format
    image: prom-exporter:1.0
    ports:
    - containerPort: 9090
    volumeMounts:
    - name: raw-logs
      mountPath: /var/log/app
      readOnly: true
  volumes:
  - name: raw-logs
    emptyDir: {}

Ambassador example

spec:
  containers:
  - name: app
    image: myapp:1.0
    env:
    - name: DB_HOST
      value: localhost               # app always talks to localhost
    - name: DB_PORT
      value: "6379"
  - name: ambassador                 # proxies to real Redis cluster
    image: redis-proxy:1.0
    ports:
    - containerPort: 6379
    env:
    - name: REDIS_CLUSTER_HOST
      value: redis-cluster.prod.svc.cluster.local

Native sidecar containers (Kubernetes 1.29+)

Init container with restartPolicy: Always: starts before app containers, stays running for Pod lifetime, supports probes.

spec:
  initContainers:
  - name: log-collector
    image: fluent/fluentd:v1.14
    restartPolicy: Always          # native sidecar
    volumeMounts:
    - name: shared-logs
      mountPath: /var/log/app
  containers:
  - name: app
    image: myapp:1.0
Classic sidecar (containers[])Native sidecar (initContainers + restartPolicy: Always)
StartsWith app containersBefore app containers
Job compatibilityYesNo
Exam clustersAlways worksk8s 1.29+ only

kubectl commands

kubectl logs <pod> -c <container>
kubectl exec <pod> -it -c <container> -- /bin/sh
kubectl get po <n>   # READY 2/2
  • Without -c, kubectl targets first container in spec

Exam gotchas

  • Init:0/1 → init container not done: kubectl logs <pod> -c <init-container-name>
  • Native sidecar: initContainers + restartPolicy: Always (k8s 1.29+); otherwise use regular container in containers[]