Add a Sidecar Container

KubernetesBeginner
Practice Now

Introduction

A sidecar container runs in the same Pod as an application container and supports the application while it is running. This is different from an init container, which must finish before the app starts. Sidecars are commonly used for log shipping, proxying, synchronization, or other helper behavior that should share the Pod lifecycle.

In this lab, you will create a multi-container Pod with an app container that writes log lines into a shared emptyDir volume and a sidecar container that follows that file. You will inspect both containers, read sidecar logs, and then put the same sidecar pattern into a Deployment template.

Prepare a Sidecar Namespace

In this step, you will prepare a clean namespace for sidecar practice.

Start in /home/labex/project. You will write a Pod manifest and a Deployment manifest in this directory.

mkdir -p /home/labex/project
cd /home/labex/project

Check that the Kubernetes API server is reachable. If the VM has just started and the node is not ready yet, wait a few seconds and run the command again.

kubectl get nodes --request-timeout=5s

Expected output includes:

NAME         STATUS   ROLES           AGE   VERSION
labex-v135   Ready    control-plane   ...   v1.35...

Wait until the cluster networking Pod is Ready before creating workloads.

kubectl wait --namespace kube-system --for=condition=Ready pod -l k8s-app=calico-node --timeout=120s

Expected output:

pod/calico-node-... condition met

Create a namespace named ckad-prep-sidecar:

kubectl create namespace ckad-prep-sidecar

Set this namespace as the current context namespace:

kubectl config set-context --current --namespace=ckad-prep-sidecar

Confirm the current namespace:

kubectl config view --minify --output 'jsonpath={..namespace}'; echo

Expected output:

ckad-prep-sidecar

Create a Multi-Container Pod

In this step, you will create a Pod with an application container and a sidecar container.

Both containers mount the same emptyDir volume at /var/log/shared. The app container writes log lines into /var/log/shared/app.log. The sidecar container runs at the same time and uses tail -f to stream that file. The touch command creates the file before tail -f starts, so the sidecar can wait safely even if the app has not written its first line yet.

Create sidecar-pod.yaml:

cat > sidecar-pod.yaml <<'EOF'
apiVersion: v1
kind: Pod
metadata:
  name: sidecar-demo
  labels:
    app: sidecar-demo
spec:
  terminationGracePeriodSeconds: 0
  volumes:
  - name: shared-logs
    emptyDir: {}
  containers:
  - name: app
    image: busybox:1.36
    command:
    - /bin/sh
    - -c
    - 'i=1; while true; do echo "app-line-${i}" >> /var/log/shared/app.log; i=$((i+1)); sleep 2; done'
    volumeMounts:
    - name: shared-logs
      mountPath: /var/log/shared
  - name: log-sidecar
    image: busybox:1.36
    command:
    - /bin/sh
    - -c
    - 'touch /var/log/shared/app.log; tail -n +1 -f /var/log/shared/app.log'
    volumeMounts:
    - name: shared-logs
      mountPath: /var/log/shared
EOF

Apply the manifest:

kubectl apply -f sidecar-pod.yaml

Expected output:

pod/sidecar-demo created

Wait until the Pod is Ready. A multi-container Pod is Ready only when all regular containers are ready.

kubectl wait --for=condition=Ready pod/sidecar-demo --timeout=120s

Expected output:

pod/sidecar-demo condition met

List the container names in the Pod:

kubectl get pod sidecar-demo -o 'jsonpath={.spec.containers[*].name}{"\n"}'

Expected output:

app log-sidecar

Inspect Sidecar Collaboration

In this step, you will confirm that both containers are running and that the sidecar is streaming the app's log file.

First inspect container readiness. The output prints each container name and whether it is ready.

kubectl get pod sidecar-demo -o 'jsonpath={range .status.containerStatuses[*]}{.name}{" "}{.ready}{"\n"}{end}'

Expected output includes:

app true
log-sidecar true

Read the app container logs. The app writes normal stdout only when the shell command starts; its repeated lines go into the shared file.

kubectl logs sidecar-demo -c app --tail=5

The app container may not print repeated lines to stdout. The important evidence is in the shared file and the sidecar logs.

Read the shared file through the app container:

kubectl exec sidecar-demo -c app -- sh -c 'tail -n 3 /var/log/shared/app.log'

Expected output includes app log lines:

app-line-...
app-line-...
app-line-...

Now read the sidecar logs. Because the sidecar tails the same file, its logs should include the same kind of lines.

kubectl logs sidecar-demo -c log-sidecar --tail=3

Expected output includes:

app-line-...
app-line-...
app-line-...

Add the Sidecar Pattern to a Deployment

In this step, you will put the sidecar pattern into a Deployment template.

Standalone Pods are useful for learning, but applications usually run through controllers. A Deployment can create replacement Pods, and each replacement Pod will include both the app container and the sidecar container from the template.

Create sidecar-deployment.yaml:

cat > sidecar-deployment.yaml <<'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
  name: sidecar-worker
spec:
  replicas: 1
  selector:
    matchLabels:
      app: sidecar-worker
  template:
    metadata:
      labels:
        app: sidecar-worker
    spec:
      terminationGracePeriodSeconds: 0
      volumes:
      - name: shared-logs
        emptyDir: {}
      containers:
      - name: app
        image: busybox:1.36
        command:
        - /bin/sh
        - -c
        - 'i=1; while true; do echo "worker-line-${i}" >> /var/log/shared/worker.log; i=$((i+1)); sleep 2; done'
        volumeMounts:
        - name: shared-logs
          mountPath: /var/log/shared
      - name: log-sidecar
        image: busybox:1.36
        command:
        - /bin/sh
        - -c
        - 'touch /var/log/shared/worker.log; tail -n +1 -f /var/log/shared/worker.log'
        volumeMounts:
        - name: shared-logs
          mountPath: /var/log/shared
EOF

Apply the Deployment:

kubectl apply -f sidecar-deployment.yaml

Expected output:

deployment.apps/sidecar-worker created

Wait until the Deployment is available:

kubectl wait --for=condition=Available deployment/sidecar-worker --timeout=120s

Expected output:

deployment.apps/sidecar-worker condition met

Find the Pod created by the Deployment:

worker_pod="$(kubectl get pods -l app=sidecar-worker -o 'jsonpath={.items[0].metadata.name}')"
echo "$worker_pod"

Expected output shows a generated Pod name:

sidecar-worker-...

Read the sidecar logs from the Deployment-created Pod:

kubectl logs "$worker_pod" -c log-sidecar --tail=3

Expected output includes:

worker-line-...
worker-line-...
worker-line-...

Summary

You created a multi-container Pod with an app container and a sidecar container, used an emptyDir volume to share a log file, confirmed that both containers run together, and moved the same sidecar pattern into a Deployment template. You now know when a sidecar fits: it supports the application while the application is running.