In a previous post in this Kubernetes guide, you learned how to use commands and arguments in a Kubernetes Pod. This post will teach you about Kubernetes init containers. A Kubernetes init container is a special type of container that runs before the main application container in a Pod. The init containers can be used to perform tasks such as setting up the environment, pulling code or a binary from a repository, downloading dependencies, or running scripts that are not part of the container image. You can use an init container to wait for other services, such as a database, to come up before the main app container starts. Essentially, init containers are used to get things ready for your app containers.
Avatar

Multicontainer Pods

Before directly jumping into the init containers, let's discuss multicontainer Pods. A multicontainer Pod is a Pod that contains two or more containers that share resources, such as network, storage, or memory. These containers work together as a single unit to perform a specific task. Remember, the spec.containers field in a Pod specification is an array that allows you to define multiple containers:

apiVersion: v1
kind: Pod
metadata:
  name: myapp
spec:
  containers:
  - name: app
    image: nginx
    ports:
    - containerPort: 80
    volumeMounts:
    - name: data
      mountPath: /var/log/nginx
  - name: logger
    image: busybox
    args: [/bin/sh, -c, 'tail -n+1 -f /var/log/nginx/access.log']
    volumeMounts:
    - name: data
      mountPath: /var/log/nginx
  volumes:
  - name: data
    emptyDir: {}

Here, we defined two containers: app and logger. The app container runs the actual application, whereas the logger container uses the tail command to follow the nginx access log file. Both containers share a volume mount named data. Read this post to learn more about Kubernetes Pods. Now, apply the YAML file.

Kubectl apply -f multi-container-pod.yaml
Create a multi container Pod in Kubernetes

Create a multi container Pod in Kubernetes

Remember, a container only lives as long as its main process continues to run. Similarly, a Kubernetes Pod exists only as long as at least one container in it is running. The main process in containers must run continuously to keep the containers and Pod alive. The screenshot indicates that both containers are running, confirming that the Pod is running as well. If either container fails, the Pod will be restarted. If the containers can't keep running after multiple attempts, the Pod will fail with a CrashLoopBackOff status.

Init containers

As mentioned earlier, a Pod can comprise multiple containers. Similarly, you can define multiple init containers in a Pod under the spec.initContainers field, which is an array just like the containers field. If you define multiple init containers in a Pod, they run one after another in sequential order. Before starting the app container, all init containers must complete successfully. If any init container fails, the Pod will not launch.

Benefits of init containers

The benefits of init containers are as follows:

  1. Small image size—The init container uses independent images. This allows you to decouple dependencies and utilities from the actual app image, thereby reducing the size and complexity of the app image.
  2. Dependency resolution—Init containers run before the app containers start. This ensures that the app containers only start when all dependencies and preconditions are satisfied.
  3. Reduced attack surface—Keeping the external dependencies separate from the actual app image reduces the overall attack surface.
  4. Security improvement—Init containers can run with a different file system view than the app containers in the same Pod. They can now access Kubernetes Secrets that were previously inaccessible to app containers.

Define an init container

To understand an init container, see this Pod manifest file named webapp.yaml:

apiVersion: v1
kind: Pod
metadata:
  name: webapp
spec:
  initContainers:
  - name: check-db
    image: busybox
    command: ['/bin/sh']
	args: ['-c', 'until nc -z db-service 3306; do echo waiting for db-service; sleep 5; done;']
  containers:
  - name: app
    image: harbor.testlab.local/library/webapp
    env:
    - name: DB_HOST
      value: db-service
    - name: DB_PORT
      value: "3306"
Define init containers in a Kubernetes Pod

Define init containers in a Kubernetes Pod

In the screenshot, you can see a new spec.initContainers section, which is similar to the spec.containers section. We defined an init container named check-db, which uses a busybox image. Here, I used command and arguments to run the nc -z db-service 3306 command, which checks whether Port 3306 on the host "db-service" is open. The init container will not complete until it can reach db-service, and the app container waits for it to finish before starting.

Let's apply this YAML file and see what happens.

kubectl apply -f webapp.yaml
kubectl get pods webapp
Create and view a Kubernetes Pod with an init container

Create and view a Kubernetes Pod with an init container

Notice how the Pod is stuck with a status of Init:0/1. This essentially means that 0 out of 1 init containers are complete so far. The kubectl describe pods command will tell you the state of the init and app containers, as shown in the screenshot below.

kubectl describe pods webapp
View the state of init and app containers in a Kubernetes Pod

View the state of init and app containers in a Kubernetes Pod

To see the container logs, you can run this command:

kubectl logs webapp -c check-db
View the init container logs in a Kubernetes Pod

View the init container logs in a Kubernetes Pod

You can see that the check-db init container is waiting for the db-service. Let's now create a YAML manifest to deploy the MySQL database in Kubernetes.

apiVersion: v1
data:
  password: UEBzc3cwcmQ=
kind: Secret
metadata:
  name: db-secret
---
apiVersion: v1
kind: Service
metadata:
  name: db-service
spec:
  ports:
  - port: 3306
  selector:
    app: db
  clusterIP: None
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: db-deployment
spec:
  selector:
    matchLabels:
      app: db
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: db
    spec:
      containers:
      - image: mysql:5.7
        name: db-container
        env:
        - name: MYSQL_ROOT_PASSWORD
          valueFrom:
                secretKeyRef:
                  name: db-secret
                  key: password
        ports:
        - containerPort: 3306
          name: db
        volumeMounts:
        - name: db-persistent-storage
          mountPath: /var/lib/mysql
      volumes:
      - name: db-persistent-storage
        persistentVolumeClaim:
          claimName: db-pv-claim
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: db-pv-volume
  labels:
    type: local
spec:
  storageClassName: manual
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: "/mnt/data"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: db-pv-claim
spec:
  storageClassName: manual
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi

This YAML file contains all the configurations required to create a Kubernetes Secret, Deployment, Service, persistent volume, and persistent volume claims. Let's apply this file and wait for the status of the webapp Pod to change.

kubectl apply -f database.yaml
kubectl get pods webapp --watch
Create the db service and watch the webapp Pod starting up in a Kubernetes cluster

Create the db service and watch the webapp Pod starting up in a Kubernetes cluster

You can see in the screenshot that when I created the db-service in the Kubernetes cluster, the webapp Pod started running because the check-db init container had completed.

View the init container state in a Kubernetes Pod

View the init container state in a Kubernetes Pod

Concluding

You have learned about multicontainer Pods and completed the Kubernetes init containers demo. Note that this is just a simple use case of Kubernetes init containers. In a production environment, you will often encounter more complex start requirements for containers.

Subscribe to 4sysops newsletter!

In my next post I will cover deploying stateful applications with Kubernetes StatefulSets.

0 Comments

Leave a reply

Your email address will not be published. Required fields are marked *

*

© 4sysops 2006 - 2023

CONTACT US

Please ask IT administration questions in the forums. Any other messages are welcome.

Sending

Log in with your credentials

or    

Forgot your details?

Create Account