Prabal Tripathi

What an Init Container Is Actually For

A container whose entire job is to run and exit — and the ordering problem it solves.

Kubernetes lets you declare containers that run before your application container, and must finish successfully first. They're called init containers, and the first time I met one it was doing something that looked absurd.

It printed a line and exited.

Why you'd ship a container that does nothing

The container's job wasn't the printing. It was existing.

Some things need to be true before your app starts — the pod scheduled onto a node, an IP assigned, networking attached. If you need a guarantee that something else is in place before your app's first line runs, you need a phase that happens before the app, and that phase has to be non-empty to happen at all.

So a container that prints and exits is a placeholder for a point in time.

Once I understood that, a lot of infrastructure stopped looking silly. A fair amount of it exists to create ordering guarantees, and ordering is exactly the thing that's invisible when you read a config file.

The real version

The useful cases do actual work:

  • Write a config file the app will read
  • Run a database migration before any replica serves traffic
  • Tune a kernel setting the app needs (this one needs privileges the app itself should never have — which is a nice pattern: the dangerous thing happens in a container that exits before the attackable surface exists)

That last one is the bit I'd underline. The init container holds the privilege and then dies. Your app runs unprivileged. The capability doesn't outlive the need for it.

Where it gets interesting

Newer Kubernetes blurs this. You can declare a container in the init list that keeps running — a sidecar that starts before the app and stays up for the pod's life. Now "init" doesn't mean "runs and exits," it means "starts first."

That turns out to matter enormously for anything that intercepts traffic. If your proxy is a normal sidecar, it and your app start together, and there's a window where the app is up and the proxy isn't. Every request in that window escapes. You can paper over it with a readiness wait, but that's a hope, not a guarantee. Start it first with a startup probe and the window closes.

What I took from it

"Run before, then exit" is a primitive for ordering. "Start before, keep running" is a primitive for interception.

Most of the confusing config I've read turned out to be someone reaching for one of those two.