Chuyển đến nội dung chính

Lesson 1: Multi-container Pods & Init Containers

Multi-container Pod patterns: Sidecar, Ambassador, Adapter. Init Containers for prerequisites. Shared volumes between containers. CKAD hands-on tasks.

Multi-Container Pod Patterns — Sidecar, Ambassador, Adapter and Init Containers

1. Multi-container Pod Patterns

Containers in the same Pod share: network (same IP), IPC, and can share storage volumes. Use multiple containers when they need tight coordination.

PatternRoleReal-world Example
SidecarExtend/enhance the main container (same lifecycle)Log shipper, service mesh proxy (Envoy), config reloader
AmbassadorProxy traffic to/from the main containerLocal proxy cache, connection multiplexer
AdapterTransform the main container's outputMetrics format converter (app → Prometheus format)
Sidecar Pattern:
┌─────────────────────────────────────────────┐
│                    POD                      │
│  ┌──────────────┐    ┌─────────────────┐    │
│  │  App         │    │  Log Sidecar    │    │
│  │  Container   │    │  (Fluentd)      │    │
│  └──────┬───────┘    └────────┬────────┘    │
│         │                     │             │
│         └──── Shared Volume ──┘             │
│              /var/log/app                   │
└─────────────────────────────────────────────┘

2. Multi-container Pod YAML

apiVersion: v1
kind: Pod
metadata:
  name: web-with-sidecar
spec:
  containers:
  - name: web
    image: nginx:1.21
    volumeMounts:
    - name: shared-logs
      mountPath: /var/log/nginx

  - name: log-shipper
    image: fluent/fluentd:v1.14
    volumeMounts:
    - name: shared-logs
      mountPath: /var/log/nginx
      readOnly: true  # Sidecar reads, doesn't write

  volumes:
  - name: shared-logs
    emptyDir: {}     # Ephemeral, lost when pod deleted

Exam tip: CKAD often gives tasks to create Pods with a sidecar container. Key points: you need a shared volume for containers to communicate, and both containers must mount the volume at the correct path. Sidecars typically mount with readOnly: true.

3. Init Containers

Init Containers run before main containers and must complete successfully before the Pod starts. Use for: DB migration, waiting for a dependency, pre-populating a volume.

apiVersion: v1
kind: Pod
metadata:
  name: app-with-init
spec:
  initContainers:
  - name: wait-for-db
    image: busybox
    command: ['sh', '-c', 'until nc -z postgres-service 5432; do sleep 2; done']

  - name: db-migrate
    image: myapp:1.0
    command: ['python', 'manage.py', 'migrate']

  containers:
  - name: app
    image: myapp:1.0
    ports:
    - containerPort: 8000
PropertyInit ContainerRegular Container
Execution orderSequential, all before appParallel start
Must complete?Yes (exit 0)Runs continuously
Liveness probeNot supportedSupported
ResourcesCounted separatelyNormal requests/limits

4. Cheat Sheet

Exam QuestionAnswer
Log collection from app container?Sidecar with shared volume
Wait for service before starting?Init Container
Run DB migration before app?Init Container with migration command
Shared storage between containers?emptyDir volume

5. Practice Questions

Q1: You need to ensure a Pod's main application only starts after a config file is downloaded from an external URL. What is the best approach?

  • A) Use a Sidecar container to download the file
  • B) Use an Init Container that runs wget and completes before the main container starts ✓
  • C) Use a DaemonSet to pre-populate config on all nodes
  • D) Mount a ConfigMap as the initial configuration

Explanation: Init Containers run sequentially before main containers and must complete (exit 0). They're perfect for "prerequisites" like downloading config, waiting for services, or running migrations. Sidecar runs in parallel alongside the main container.

Q2: Two containers in the same Pod need to share data. Container A writes to /tmp/data, Container B reads from /tmp/data. What should you configure?

  • A) ExternalDNS shared volume
  • B) emptyDir volume mounted at /tmp/data in both containers ✓
  • C) A PersistentVolumeClaim for each container
  • D) ConfigMap mounted as a volume

Explanation: emptyDir is created when a Pod is assigned to a Node, and deleted when the Pod is removed. It's perfect for sharing ephemeral data between containers in the same Pod. Both containers mount it at the same path.

Q3: A Pod has a single Init Container that keeps failing (exit code 1). What happens to the main application container?

  • A) The main container starts after a timeout
  • B) The main container is skipped and the Pod succeeds
  • C) The main container never starts; Pod shows Init:Error or Init:CrashLoopBackOff ✓
  • D) The init container failure is ignored if main container is defined

Explanation: Init Containers MUST exit with code 0. If they fail, Kubernetes restarts them based on Pod's restartPolicy. The main container never starts until all init containers complete successfully.