Sidecars & Init Containers
Update the existing wordpress Deployment in the wordpress-ns namespace, adding a sidecar container named sidecar using the busybox:stable image to the existing pod.
Live lab access
This task description is public. Its live lab requires full access; six other CKA labs are available in Free Practice with AI Lab Coach.
Create an account to continue →
Explore the six free labs with AI Lab Coach →
Read the brief on any device. Use a desktop or laptop for the terminal lab. Nothing starts until you choose Start.
The task
Task
Update the existing wordpress Deployment in the wordpress-ns namespace, adding a sidecar container named sidecar using the busybox:stable image to the existing pod.
The new sidecar container has to run the following command:
/bin/sh -c tail -f /var/log/wordpress.log
Use an emptyDir volume named logs, mounted at /var/log in both the wordpress and sidecar containers, to make the log file wordpress.log available to the co-located container. The volume must be named logs.
Original Prepium workshop · Tested on Kubernetes v1.35.0 on 1 October 2026 in a kind cluster. Native sidecar containers are stable since Kubernetes v1.33 and enabled by default since v1.29. Run this independent example in a disposable cluster.
Share a log file through emptyDir, and see why native sidecars exist
Containers in one Pod share a network namespace but not a filesystem. To let a helper read files the main container writes, mount the same volume into both. An emptyDir volume is created empty when the Pod starts, lives as long as the Pod, and is the standard way to hand files between co-located containers.
The helper can be declared in two ways. A classic sidecar is just another entry under containers. A native sidecar is an entry under initContainers with restartPolicy: Always: it starts before the main containers, keeps running beside them, and is stopped automatically when they finish.
report ── writes /logs/app.log ──┐
├── emptyDir "logs"
shipper ── tail -F /logs/app.log ──┘
1. Run the same Job both ways
Save the classic version as sidecar-classic-job.yaml:
apiVersion: batch/v1
kind: Job
metadata:
name: report-classic
namespace: prepium-tutorial
spec:
backoffLimit: 0
template:
spec:
restartPolicy: Never
volumes:
- name: logs
emptyDir: {}
containers:
- name: report
image: busybox:1.36
command: ["/bin/sh", "-c", "for i in 1 2 3 4 5; do echo line-$i >> /logs/app.log; sleep 2; done"]
volumeMounts:
- name: logs
mountPath: /logs
- name: shipper
image: busybox:1.36
command: ["/bin/sh", "-c", "touch /logs/app.log; tail -F /logs/app.log"]
volumeMounts:
- name: logs
mountPath: /logs
And the native version as sidecar-native-job.yaml. The only structural change is where shipper is declared and its restartPolicy: Always:
apiVersion: batch/v1
kind: Job
metadata:
name: report-native
namespace: prepium-tutorial
spec:
backoffLimit: 0
template:
spec:
restartPolicy: Never
volumes:
- name: logs
emptyDir: {}
initContainers:
- name: shipper
image: busybox:1.36
restartPolicy: Always
command: ["/bin/sh", "-c", "touch /logs/app.log; tail -F /logs/app.log"]
volumeMounts:
- name: logs
mountPath: /logs
containers:
- name: report
image: busybox:1.36
command: ["/bin/sh", "-c", "for i in 1 2 3 4 5; do echo line-$i >> /logs/app.log; sleep 2; done"]
volumeMounts:
- name: logs
mountPath: /logs
kubectl create namespace prepium-tutorial
kubectl apply -f sidecar-classic-job.yaml -f sidecar-native-job.yaml
kubectl -n prepium-tutorial get jobs --watch
2. Read the result
After about a minute, report-native shows Complete 1/1. report-classic is still Running 0/1 and stays that way. Look at its Pod:
kubectl -n prepium-tutorial get pods -l job-name=report-classic
kubectl -n prepium-tutorial get pods -l job-name=report-classic \
-o jsonpath='{range .items[0].status.containerStatuses[*]}{.name}: {.state}{"\n"}{end}'
The Pod is 1/2 NotReady: report terminated with exit code 0, but shipper is still running its tail -F. A Job's Pod only succeeds when all regular containers have exited, and a log follower never exits. This is the problem native sidecars solve. Kubernetes knows shipper in the native version is a sidecar, so it terminates it once report finishes and the Job completes.
3. Prove the volume was shared
kubectl -n prepium-tutorial logs job/report-native -c shipper
The shipper printed line-1 through line-5, which it could only have read from the file report wrote into the shared volume. If you see nothing, compare the mountPath in both containers: the volume name must match the volumes entry and both mounts must point at the directory the writer uses.
4. When the classic form is fine
In a long-running Deployment, the main container never exits either, so a classic sidecar works and is still common in existing manifests and exam tasks. Native sidecars add two guarantees that matter more as Pods get stricter: they are started (and, with a startup probe, ready) before the main containers, and they are stopped after them. If a task tells you exactly which list to put the container in, follow the task. If you are choosing, the native form is the modern default.
| Example check | Evidence |
|---|---|
| Helper container exists with the requested name and image | Container listed in the Pod spec |
| Volume is shared | Same volume name mounted in both containers at the expected path |
| Helper sees the data | kubectl logs -c <helper> shows the writer's lines |
Cleanup: kubectl delete namespace prepium-tutorial. Reference: Sidecar containers and emptyDir. Next, try init containers and native sidecars on CKAD.
What this tests
Run and schedule workloads - deployments, autoscaling, taints and tolerations, affinity, and resource limits. On the CKA exam, Workloads & Scheduling tasks are graded purely on what you build in the cluster - not multiple choice - so the only way to get faster is to do them on a real cluster against a clock.
Practice it for real
The public description lets you study the task before signing up. Full access includes every live lab. Six selected CKA scenarios are included in Free Practice, with five shared sessions each week. You solve the task in a real terminal, hit validate, and a programmatic checker scores exactly what you got right and wrong (with partial credit). You can open the solution while practising, then retry and use the failed checks to improve your score.