- Update container images with Copa - Mon, Nov 27 2023
- Deploying stateful applications with Kubernetes StatefulSets - Wed, Nov 1 2023
- Install and enable IIS Manager for Remote Administration - Thu, Oct 26 2023
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
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:
- 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.
- 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.
- Reduced attack surface—Keeping the external dependencies separate from the actual app image reduces the overall attack surface.
- 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"
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
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
To see the container logs, you can run this command:
kubectl logs webapp -c check-db
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
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.
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.
Read the latest IT news and community updates!
Join our IT community and read articles without ads!
Do you want to write for 4sysops? We are looking for new authors.