Init containers are a Kubernetes mechanism for initializing new Pods. Init containers start and exit before their Pod’s main application containers, providing a chance to run bootstrap scripts in sequential order.
In this article we’ll show how to add init containers to a Pod and consider some common use cases. Although init containers are configured similarly to regular containers, they do have some differences because of their specialized purpose.
The Role of Init Containers
Init containers solve challenges associated with first-run initialization of applications. It’s common for services to depend on the successful completion of a setup script before they can fully start up.
In smaller systems, you could add the script to your existing application container image. However this isn’t ideal as it adds another responsibility to the image. You may even have several distinct stages to complete, each with their own dependencies and relationships. Adding all these single-use operations to your main container image can quickly create bloated complexity that’s hard to maintain.
Init containers address this by letting you run specialized containers before a Pod’s application containers start. Each Pod can have multiple init containers; they’re guaranteed to run sequentially, only after the previous one has completed by exiting successfully.
Kubernetes starts the Pod’s regular containers once all the init containers have completed. If an init container fails, it will be restarted until it completes. When the Pod’s
restartPolicy is set to
Never, the Pod is marked as failed instead.
Adding Init Containers to a Pod
Init containers are defined in the
spec.initContainers field of a Pod’s manifest. This is very similar to a regular
Here’s a example of a Pod with two init containers attached:
apiVersion: v1 kind: Pod metadata: name: init-containers-pod spec: containers: - name: app-container image: busybox:latest command: ["echo", "Started app"] initContainers: - name: first-init-container image: busybox:latest command: ["echo", "This is the first init container"] - name: second-init-container image: busybox:latest command: ["echo", "This is the second init container"]
Use Kubectl to add the Pod to your cluster:
$ kubectl apply -f pod.yaml pod/init-containers-pod created
Now retrieve the logs associated with each of the init containers to confirm they’ve been run:
$ kubectl logs init-containers-pod -c first-init-container This is the first init container $ kubectl logs init-containers-pod -c second-init-container This is the second init container
You can use most properties available to Kubernetes container manifests within an
initContainers field. These include volumes, ports, environment variables, and security contexts.
Init containers support resource limits too but these are handled differently to regular containers. The highest value of the resource limits declared by all the init containers is selected as the Pod’s effective limit, unless it’s lower than the sum of the limits on the Pod’s application containers. This computed value will be used for scheduling purposes.
One limitation of init containers is their lack of support for probes. You can’t assign
startupProbe fields to container objects in the
initContainers field. Init containers are a separate mechanism which you can use instead of or alongside probes attached to your main application containers.
There are a few common pitfalls when using init containers. Here are some details to remember:
- Init containers run each time their Pod restarts. This means your init container operations should be idempotent so they’re resilient to running twice in the same Pod. If the Pod is restarted, all its init containers will be executed again.
- Changes to a Pod’s
initContainersfield aren’t supported, with one exception. You can modify the
imagefield. This will cause the Pod to restart and run your new init containers.
- Init container names need to be unique across all the containers in the Pod. This includes other init containers and your application containers. You’ll see a YAML validation error in your console if you try to apply a manifest that breaks this rule.
- Pods have an
Initialized: Falsecondition when init containers are running. This is visible under the
Conditionsheading when you run
kubectl describe my-pod.
You can also check whether a Pod’s init containers have completed using the
kubectl get command:
$ kubectl get init-containers-pod NAME READY STATUS RESTARTS AGE init-containers-pod 0/1 Init:1/2 0 1m
In this case, the
STATUS column shows the Pod has two init containers, one of which has successfully completed. Once all the init containers finish, Kubernetes will start the application containers and the Pod’s status will change to
When to Use Init Containers
Init containers are ideal whenever new deployments of your application need to be initialized in some way. They cater for dedicated pre-run tasks that depend on tooling outside your main container image.
Here are a few situations where you might use init containers:
- Generating configuration files from environment variables.
- Pre-populating caches used by your application.
- Migrating and seeding a database instance.
- Downloading and installing application plugins into a volume.
- Blocking application start-up until dependencies are available (such as databases or external APIs).
Another way to achieve some of these tasks is with a readiness or startup probe. However there is a difference in intent: probes are primarily designed to communicate a container’s state to Kubernetes whereas init containers are designated as a way to perform actions during Pod initialization.
Init containers are a way to perform first run initialization routines within a Kubernetes Pod. They can be used to block or delay application container startup while you wait for dependencies to become available or bootstrap scripts to complete.
The functionality of init containers sometimes overlaps startup and readiness probes. You can use a probe when the activity you want to perform mostly concerns blocking application startup until a condition is met. They rely on your script already existing in your application’s container image. An init container is a better choice when you want to perform specialist actions without bloating your main image with single-use utilities.