Day 11/40 Days of K8s: Kubernetes Multi-container Pods: Sidecar vs Init Container

πŸ” Overview

In a Kubernetes pod, we can have multiple containers:

  1. Main application container (ex: Nginx)

  2. Init container

  3. Sidecar/helper container

These containers share pod resources like CPU, RAM, and storage.

πŸš€ Init Containers

  • Init containers starts even before the app container starts. If pod is scheduled, first init container starts and once done, app container will be up and running. It works in conjunction with main app container.

  • Use Case: Waiting for a service to be Ready(in our example below..)

    An init container can be used to wait for the service to be ready before it to start and the main application container starts.

🀝 Sidecar/Helper Containers

  • Side car runs alongside with app container. Like it sends some input or collects output from main container.

  • Use Case: Logging and Monitoring

    Consider a web application that needs to send logs to an external logging service. A sidecar container can be used to handle the log shipping process.

Environment Variables in Kubernetes Pods

Let's look at how to use environment variables in a Kubernetes pod Yaml file:

apiVersion: v1 
kind: Pod
metadata:
  name: myapp
  labels:
     name: myapp-pod 
spec:
  containers:
  - name: myapp-container 
    image: busybox:1.28
    command: ['sh','-c', 'echo the app is running && sleep 3600']
    env:
    - name: FIRSTNAME 
      value: "vivek"
  initContainers:
  - name: init-myservice 
    image: busybox:1.28
    command: ['sh', '-c']
    args: ['until nslookup my-service.default.svc.local,; do echo "waiting for service to be up"; sleep 2;done']

πŸ“Œ Key Points:

  • The FIRSTNAME environment variable is set with the value "vivek" inside the container.

  • Once the container is running, we can access this env var from inside the container.

  • myapp-container: It is using busy box image and using the command to echo the app is running and make the container up and running for 3600 sec to avoid pod crashes.

  • init-myservice container: It is using busy box image and using nslookup command and work only or until where service my-service is available else it keeps waiting for service to be up and running.

  • NOTE: until init container is up and running the main app container will not come up.

Next Steps:

  1. Create the pod using this YAML file

     vivekmanne@Viveks-MacBook-Pro Day11 % k describe pod myapp-pod
     Name:             myapp-pod
     Namespace:        default
     Priority:         0
     Service Account:  default
     Node:             kind-cluster-1-worker2/172.19.0.3
     Start Time:       Thu, 04 Jul 2024 07:07:03 +0530
     Labels:           app.kubernetes.io/name=MyApp
     Annotations:      <none>
     Status:           Pending
     IP:               10.244.2.9
     IPs:
       IP:  10.244.2.9
     Init Containers:
       init-myservice:
         Container ID:  containerd://ff2fc60945348780227def2c944a392eae8e145a3f48395575742dc206c64287
         Image:         busybox:1.28
         Image ID:      docker.io/library/busybox@sha256:141c253bc4c3fd0a201d32dc1f493bcf3fff003b6df416dea4f41046e0f37d47
         Port:          <none>
         Host Port:     <none>
         Command:
           sh
           -c
         Args:
           until nslookup my-service.default.svc.cluster.local; do echo waiting for myservice; sleep 2; done
         State:          Running
           Started:      Thu, 04 Jul 2024 07:07:04 +0530
         Ready:          False
         Restart Count:  0
         Environment:    <none>
         Mounts:
           /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-nvpjk (ro)
     Containers:
       myapp-container:
         Container ID:
         Image:         busybox:1.28
         Image ID:
         Port:          <none>
         Host Port:     <none>
         Command:
           sh
           -c
           echo The app is running! && sleep 3600
         State:          Waiting
           Reason:       PodInitializing
         Ready:          False
         Restart Count:  0
         Environment:
           FIRSTNAME:  Vivek
         Mounts:
           /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-nvpjk (ro)
     Conditions:
       Type                        Status
       PodReadyToStartContainers   True
       Initialized                 False
       Ready                       False
       ContainersReady             False
       PodScheduled                True
     Volumes:
       kube-api-access-nvpjk:
         Type:                    Projected (a volume that contains injected data from multiple sources)
         TokenExpirationSeconds:  3607
         ConfigMapName:           kube-root-ca.crt
         ConfigMapOptional:       <nil>
         DownwardAPI:             true
     QoS Class:                   BestEffort
     Node-Selectors:              <none>
     Tolerations:                 node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
                                  node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
     Events:
       Type    Reason     Age   From               Message
       ----    ------     ----  ----               -------
       Normal  Scheduled  19s   default-scheduler  Successfully assigned default/myapp-pod to kind-cluster-1-worker2
       Normal  Pulled     18s   kubelet            Container image "busybox:1.28" already present on machine
       Normal  Created    18s   kubelet            Created container init-myservice
       Normal  Started    18s   kubelet            Started container init-myservice
    
  2. check logs of the Init container

    nslookup: can't resolve 'my-service.default.svc.cluster.local'

    We can see the init container is running but waiting for the condition to be satisfied. Until it find the service 'my-service' it keeps on trying for every 2 sec.

  3. Create deploy nginx and expose it to make svc available

Now, as you can see the pod is up and running and both app container and Init containers are running.

  1. Now, exec into the pod where app container is running and access the ENV variable defined.

πŸ’ Muti-init containers in the pod.

  1. Updated pod yaml:

     apiVersion: v1
     kind: Pod
     metadata:
       name: myapp-pod
       labels:
         app.kubernetes.io/name: MyApp
     spec:
       containers:
       - name: myapp-container
         image: busybox:1.28
         env:
         - name: FIRSTNAME
           value: "Vivek"
         command: ['sh', '-c', 'echo The app is running! && sleep 3600']
    
       initContainers:
       - name: init-myservice
         image: busybox:1.28
         command: ['sh', '-c']
         args: ['until nslookup my-service.default.svc.cluster.local; do echo waiting for myservice; sleep 2; done']
    
       - name: init-mydb
         image: busybox:1.28
         command: ['sh', '-c']
         args: ['until nslookup mydb.default.svc.cluster.local; do echo waiting for mydb; sleep 2; done']
    

In this case we have added another init container named init-mydb. It is using busy box image and the command using nslookup command and work only or until where svc mydb is available else it keep waiting for service to be up and running.

  1. Let's create pod using pod yaml...
vivekmanne@Viveks-MacBook-Pro Day11 % k apply -f pod.yaml
The Pod "myapp-pod" is invalid: spec.initContainers: Forbidden: pod updates may not add or remove containers

NOTE: We can’t add or delete init containers once it is created, so delete the pod and recreate the pod which updates 2 init containers.

As you can see above, myapp-pod is not running since init-db container is not running as it couldn’t find the service as it can't resolve 'mydb.default.svc.cluster.local'

  1. Create my-db service and expose

  1. Finally, the myapp-pod is running as both init containers are running. To verify it.
k logs myapp-pod -c init-mydb
Server:    10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local

Name:      mydb.default.svc.cluster.local
Address 1: 10.96.245.177 mydb.default.svc.cluster.local

It's important to understand how multi-container pod works and about the init containers startups for effectively managing pod lifecycles in Kubernetes.

#Kubernetes #Pod #Multi-container Pod #Init container #Sidecar container#CKASeries #40DaysofKubernetes

1
Subscribe to my newsletter

Read articles from Gopi Vivek Manne directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Gopi Vivek Manne
Gopi Vivek Manne

I'm Gopi Vivek Manne, a passionate DevOps Cloud Engineer with a strong focus on AWS cloud migrations. I have expertise in a range of technologies, including AWS, Linux, Jenkins, Bitbucket, GitHub Actions, Terraform, Docker, Kubernetes, Ansible, SonarQube, JUnit, AppScan, Prometheus, Grafana, Zabbix, and container orchestration. I'm constantly learning and exploring new ways to optimize and automate workflows, and I enjoy sharing my experiences and knowledge with others in the tech community. Follow me for insights, tips, and best practices on all things DevOps and cloud engineering!