How to create and use init containers in Kubernetes

Posted on 139 views

Kubernetes abbreviated as k8s or Kube is an effective container orchestration tool initially developed by Google, but currently a community project. This tool is used to automate and scale container deployment. In recent days, the popularity of Kubernetes and its ecosystem has grown immensely with its ability to design patterns, workload types, and behavior.

One of the jewels in the crown is the init containers feature. This feature provides many advantages in the initialization of workloads.

What is an init Container?

An init container can be defined as a container with modified operational rules and behavior. They normally contain utilities and setup scripts that are not present in the app image. The most preeminent feature for init containers is that they start and terminate before the application containers.

In a single pod, there might be multiple containers running with one or more init containers as well. Init containers have similar features and fields to app containers. These features include volumes, security settings, and resource limits though resource limits in init containers are handled differently.

The main difference between init containers and regular containers are:

  • Init containers always run to completion.
  • Each init container must complete successfully before the next one starts.

In addition to the above, init containers do not support livenessProbereadinessProbestartupProbe or lifecycle since they must run to completion for the pod to be ready. Normally, when multiple init containers are specified in a pod, the kubelet runs them sequentially. Each container has to succeed before the next runs.

When an init pod fails, the Kubelet will restart it repeatedly until it succeeds. However, if the pod has a restartPolicy of Never, and the init Pod fails to run successfully, then the overall pod will be treated as a failed pod.

Init containers are used in the following areas:

  • Fetch encrypted secrets from a vault and write them to a file system
  • A blockchain app that needs to register itself amongst its peers
  • Database migrations/applying seeds – Dynamic data fetched from a database and cached for the app to run after startup
  • An app that must fetch an access token from an identity provider
  • Fetching assets from a git repository or cloud storage that requires credentials.
  • Generating configuration files using runtime properties, for example, pod IP, assigned external IP, hostname, external ingress IP, etc.

This guide provides an overview of how to create and use init containers in Kubernetes.

Before you Begin

I assume that you already have a Kubernetes cluster set up. If not, you can use the below guides to set up a Kubernetes cluster.

Once the cluster is configured, you can use the kubectl utility to manage it. Install it as below:

curl -LO "https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl"
chmod +x kubectl
sudo mv kubectl /usr/local/bin

Export the admin conf to be able to manage the cluster.

# For k0s
export KUBECONFIG=/var/lib/k0s/pki/admin.conf

Creating and Using Init Containers in Kubernetes

There are several ways in which Init containers can be used. Some of them can be:

  • Waiting for a service to start using a shell command:
for i in 1..100; do sleep 1; if dig myservice; then exit 0; fi; done; exit 1
  • Waiting for some time before the app container is started.
sleep 120
  • Register this Pod with a remote server from the downward API with a command:
curl -X POST http://$MANAGEMENT_SERVICE_HOST:$MANAGEMENT_SERVICE_PORT/register -d 'instance=$()&ip=$()'

This guide provides a more practical example by creating a simple pod with two Init containers. Normally, init containers are defined in the pod.spec.initContainers array while the app containers are defined in the pod. spec.containers array.

Here, we will have the first init container that waits for service and the other waiting for database.

Create the configuration file.

vim application.yaml

The file will contain the below lines:

apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
  labels:
    app: myapp
spec:
  containers:
  - name: myapp-container
    image: busybox:1.28
    command: ['sh', '-c', 'echo The app is running! && sleep 3600']
  initContainers:
  - name: init-service
    image: busybox:1.28
    command: ['sh', '-c', "until nslookup service.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for service; sleep 2; done"]
  - name: init-db
    image: busybox:1.28
    command: ['sh', '-c', "until nslookup database.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for database; sleep 2; done"]

Apply the manifest.

$ kubectl apply -f application.yaml
pod/myapp-pod created

Check the status of the pod.

$ kubectl get -f application.yaml
NAME        READY   STATUS     RESTARTS   AGE
myapp-pod   0/1     Init:0/2   0          23s

Alternatively use:

$ kubectl get pod myapp-pod
NAME        READY   STATUS     RESTARTS   AGE
myapp-pod   0/1     Init:0/2   0          65s

From the output, we have two init containers. You can view more details by describing the pod:

$ kubectl describe -f application.yaml
Name:         myapp-pod
Namespace:    default
Priority:     0
Node:         debian/192.168.205.4
Start Time:   Sun, 24 Apr 2022 10:29:34 +0000
Labels:       app=myapp
Annotations:  kubernetes.io/psp: 00-k0s-privileged
Status:       Pending
IP:           10.244.1.3
IPs:
  IP:  10.244.1.3
Init Containers:
  init-service:
    Container ID:  containerd://7ca9c41dbf829d3be660a68eb5dce4ebbe8902b6ae0562bbbd723453898ef9ce
    Image:         busybox:1.28
    Image ID:      docker.io/library/[email protected]:141c253bc4c3fd0a201d32dc1f493bcf3fff003b6df416dea4f41046e0f37d47
    Port:          
    Host Port:     
    Command:
      sh
      -c
      until nslookup service.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for service; sleep 2; done
    State:          Running
      Started:      Sun, 24 Apr 2022 10:29:38 +0000
    Ready:          False
    Restart Count:  0
    Environment:    
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-l29rv (ro)
  init-db:
    Container ID:  
    Image:         busybox:1.28
    Image ID:      
    Port:          
    Host Port:     
    Command:
      sh
      -c
      until nslookup database.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for database; sleep 2; done
    State:          Waiting
      Reason:       PodInitializing
    Ready:          False
    Restart Count:  0
    Environment:    
.......

Inspect logs for the init containers in the pod(myapp) with the command:

# Inspect the first init container
kubectl logs myapp-pod -c init-service 

# Inspect the second init container
kubectl logs myapp-pod -c init-db      

The output suggests that the Init containers are waiting for the services database and service for them to run.

So we will create the two services as below:

vim service.yaml

Add the lines below to it.

---
apiVersion: v1
kind: Service
metadata:
  name: service
spec:
  ports:
  - protocol: TCP
    port: 80
    targetPort: 9376
---
apiVersion: v1
kind: Service
metadata:
  name: database
spec:
  ports:
  - protocol: TCP
    port: 80
    targetPort: 9377

Create the services with the command:

$ kubectl apply -f service.yaml
service/service created
service/database created

Now check the status of the pod.

$ kubectl get -f application.yaml
myapp-pod   1/1     Running   0          4m52s

The two Init containers have started and terminated successfully, which has allowed the app container( myapp-pod) to start as well. That brings this guide on how to create and use init containers in Kubernetes to the finale. You can now use the gathered knowledge to create your own Init containers in Kubernetes.

coffee

Gravatar Image
A systems engineer with excellent skills in systems administration, cloud computing, systems deployment, virtualization, containers, and a certified ethical hacker.