K8s Sidecar Containers: Native Support
Configure Kubernetes native sidecar containers with restartPolicy Always in initContainers. Logging sidecars, service mesh proxies, and lifecycle management.
π‘ Quick Answer: Kubernetes 1.28+ supports native sidecar containers using
initContainerswithrestartPolicy: Always. They start before main containers, run alongside them, and shut down after main containers exit. This fixes the long-standing issue of sidecar lifecycle management β sidecars no longer prevent Job completion or delay pod termination.
The Problem
Traditional sidecar pattern (multiple containers in containers[]) has issues:
- Jobs never complete β sidecar keeps running after main container exits
- No startup ordering β sidecar and app start simultaneously
- Shutdown race conditions β app might exit before sidecar finishes flushing
- No guaranteed sidecar availability β app may start before sidecar is ready
The Solution
Native Sidecar (K8s 1.28+)
apiVersion: v1
kind: Pod
metadata:
name: app-with-sidecar
spec:
initContainers:
# Native sidecar β starts first, runs alongside main containers
- name: log-collector
image: fluent/fluent-bit:3.0
restartPolicy: Always # β This makes it a sidecar
volumeMounts:
- name: logs
mountPath: /var/log/app
resources:
requests:
cpu: 50m
memory: 64Mi
containers:
- name: app
image: myapp:v2
volumeMounts:
- name: logs
mountPath: /var/log/app
volumes:
- name: logs
emptyDir: {}Lifecycle Order
Pod Created:
1. Init containers run sequentially (traditional)
2. Sidecar init containers start (restartPolicy: Always)
3. Wait for sidecar readiness probe (if defined)
4. Main containers start
5. All run together...
Pod Terminating:
1. Main containers receive SIGTERM
2. Main containers exit
3. Sidecar containers receive SIGTERM (AFTER main exits)
4. Pod terminates
# Key difference from old pattern:
# Old: sidecars and main containers get SIGTERM simultaneously
# New: sidecars get SIGTERM AFTER main containers exitService Mesh Proxy Sidecar
apiVersion: v1
kind: Pod
metadata:
name: app
spec:
initContainers:
# Envoy/Istio proxy as native sidecar
- name: proxy
image: envoyproxy/envoy:v1.30
restartPolicy: Always
ports:
- containerPort: 15001
readinessProbe:
httpGet:
path: /ready
port: 15021
initialDelaySeconds: 1
periodSeconds: 2
resources:
requests:
cpu: 100m
memory: 128Mi
containers:
- name: app
image: myapp:v2
ports:
- containerPort: 8080
# App starts AFTER proxy is ready
# App exits BEFORE proxy β proxy can drain connectionsJob with Sidecar (Fixed!)
# Before native sidecars: Job never completes because sidecar keeps running
# With native sidecars: Sidecar exits after main container completes
apiVersion: batch/v1
kind: Job
metadata:
name: data-export
spec:
template:
spec:
initContainers:
- name: cloud-sql-proxy # Database proxy sidecar
image: gcr.io/cloud-sql-connectors/cloud-sql-proxy:2.8
restartPolicy: Always # Native sidecar
args: ["--port=5432", "project:region:instance"]
containers:
- name: exporter
image: myapp:v2
command: ["./export-data"] # Runs and exits
restartPolicy: Never
# Lifecycle:
# 1. cloud-sql-proxy starts
# 2. exporter runs, connects to proxy, exports data, exits
# 3. cloud-sql-proxy receives SIGTERM, exits
# 4. Job marked Complete β
Old vs New Sidecar Pattern
# OLD pattern (pre-1.28) β DON'T use for new deployments
spec:
containers:
- name: app
image: myapp:v2
- name: sidecar # Regular container
image: fluent-bit:3.0
# Problems: no ordering, Job never completes, shutdown race
# NEW pattern (1.28+) β USE THIS
spec:
initContainers:
- name: sidecar
image: fluent-bit:3.0
restartPolicy: Always # Makes it a sidecar
containers:
- name: app
image: myapp:v2
# Benefits: ordered startup, graceful shutdown, Jobs completeMultiple Sidecars
spec:
initContainers:
# Sidecars start in order, all must be ready before main containers
- name: proxy
image: envoyproxy/envoy:v1.30
restartPolicy: Always
readinessProbe:
httpGet:
path: /ready
port: 15021
- name: log-agent
image: fluent/fluent-bit:3.0
restartPolicy: Always
# Traditional init container (runs once, then exits)
- name: db-migrate
image: myapp:v2
command: ["./migrate"]
# No restartPolicy: Always β runs once before sidecars start app
containers:
- name: app
image: myapp:v2Common Issues
Sidecar not starting β βinitContainers still runningβ
Sidecar readiness probe failing. Check logs: kubectl logs <pod> -c <sidecar-name>. Remove or fix readiness probe.
Feature not available on cluster
Native sidecars require K8s 1.28+ with SidecarContainers feature gate enabled (GA in 1.29). Check: kubectl version.
Sidecar consuming too many resources
Set resource requests/limits on sidecar init containers β they count toward pod total resources.
Best Practices
- Use native sidecars (1.28+) over regular multi-container pods
- Add readiness probes to sidecars β main containers wait for sidecar readiness
- Keep sidecar resources small β they run on every pod instance
- Use for: proxies, log collectors, config reloaders, auth agents
- Donβt use for: batch processing, one-off tasks (use init containers)
Key Takeaways
- Native sidecars use
initContainerswithrestartPolicy: Always - Start before main containers, stop after β correct lifecycle ordering
- Fixes Job completion issue with traditional sidecar pattern
- Main containers wait for sidecar readiness before starting
- Available in K8s 1.28+ (feature gate), GA in 1.29

Recommended
Kubernetes Recipes β The Complete Book100+ production-ready patterns with detailed explanations, best practices, and copy-paste YAML. Everything in one place.
Get the Book βLearn by Doing
CopyPasteLearn β Hands-on Cloud & DevOps CoursesMaster Kubernetes, Ansible, Terraform, and MLOps with interactive, copy-paste-run lessons. Start free.
Browse Courses βπ Deepen Your Skills β Hands-on Courses
Courses by CopyPasteLearn.com β Learn IT by Doing
