Kubernetes Native Sidecar Containers

Native sidecar containers (stable in Kubernetes 1.29) solve a long-standing lifecycle problem: regular sidecar containers in the main containers list start and stop in an arbitrary order, causing proxy sidecars like Envoy to not be ready when the app starts, or log collectors to die before flushing the last batch. Native sidecars are init containers with restartPolicy: Always — they start before main containers and are guaranteed to terminate after them.

Overview

Overview

Native sidecar containers solve a persistent pain point of the sidecar pattern: no guaranteed lifecycle ordering between the proxy or collector and the main application. They arrived as beta, on by default, in Kubernetes 1.29 and graduated to stable in 1.33, with a single API field: restartPolicy: Always on an initContainer.

Before native sidecars

The sidecar pattern was an operator convention with no lifecycle guarantees. Engineers running Istio, Linkerd, Fluent Bit and similar tools built fragile workarounds with init containers, shell loops and sleep commands.

  • Occasional connection refused at app startup — The proxy was not ready yet
  • Systematic last-log-line loss in Jobs — The log collector was terminated before flushing its buffer

What changes

  • Declared as — A regular container — An initContainer with restartPolicy: Always
  • Startup order — Not guaranteed — Sidecar before the app
  • Shutdown order — Not guaranteed — App before the sidecar
  • Coordination — Application-level workarounds — Handled by the kubelet

> [!TIP] Platform teams that inject sidecars via MutatingAdmissionWebhook get correct lifecycle ordering transparently, just as the injection itself is transparent to developers.

Key concepts

restartPolicy on initContainers
The restartPolicy field is now valid on initContainers (K8s 1.29+). Setting restartPolicy: Always on an initContainer converts it to a native sidecar. The other two values (OnFailure and Never, the defaults for regular pods) cause the initContainer to behave like a traditional init container that must succeed before proceeding. A native sidecar (restartPolicy: Always initContainer): Starts in order with other initContainers Does NOT have to exit before the next initContainer or main containers start If the native sidecar's readinessProbe passes, the kubelet starts the next init container Is restarted if it crashes (like a main container with restartPolicy: Always) Is NOT sent SIGTERM until all main containers have exited The preStop hook on the native sidecar is important in mesh scenarios: you may want the proxy to continue accepting traffic for a few seconds after main container exit to drain in-flight connections before the proxy itself shuts down.

When to use it

  • When troubleshooting service mesh proxy startup failures where the app gets connection refused because the proxy is not yet ready
  • When Kubernetes Jobs are losing the last log batch because the log collector sidecar exits before flushing
  • When designing a new sidecar injection pattern via MutatingAdmissionWebhook and wanting lifecycle guarantees without workarounds
  • When evaluating K8s 1.29+ features for upgrading an existing cluster and assessing migration from manual sidecar ordering workarounds

Sign up free to read the full topic

More DevOps topics

Start free on Cariara · Coding problems · System design studio