An init container runs and stops. A sidecar runs and stays, beside the app, for as long as the Pod lives.
Native sidecars
Since Kubernetes 1.29 a sidecar is written as an init container with its own restartPolicy: Always:
yaml
spec:
volumes:
- name: logs
emptyDir: {}
initContainers:
- name: log-shipper
image: busybox
restartPolicy: Always
command: ["sh", "-c", "while true; do echo shipping logs; sleep 5; done"]
volumeMounts:
- name: logs
mountPath: /var/log/app
containers:
- name: web
image: nginx:1.27
volumeMounts:
- name: logs
mountPath: /var/log/nginxThat single field changes the rules for that container:
| Init container | Sidecar (init + restartPolicy: Always) | |
|---|---|---|
| Started | Before the app, in order | Before the app, in order |
| Waited for | Until it exits 0 | Until it has started |
| Afterwards | Stays finished | Keeps running; restarted if it stops |
| READY | Not counted | Counted |
log-shipperstarted, not waited for
webstarts once the sidecar is up
both run until the Pod ends
RunningREADY 2/2
Why the order matters
A log shipper should be reading before the app writes. A proxy should be listening before the app takes its first request. Writing the helper as a plain second container gives no such guarantee; writing it as a sidecar does. And when the Pod shuts down, sidecars stop after the app, so the last log line still gets shipped.