Introduction
Welcome to Day 11 of the 40DaysOfKubernetes challenge! Today, we're diving into the concept of multi-container pods in Kubernetes. As you progress in your Kubernetes journey, you'll often encounter scenarios where a single container is insufficient for your application needs. This is where multi-container pods come into play, providing a powerful way to run closely related application components together within the same pod. Let's get Started
Multi-Container Pods in Kubernetes
A pod is the smallest deployable unit in Kubernetes and can contain one or more containers that share the same network namespace and storage. Multi-container pods are often used to enable tightly coupled application components to share resources and communicate easily.
Benefits of Multi-Container Pods:
Resource Sharing: Containers within a pod share the same network IP, port space, and storage volumes, making it easier for them to communicate and share data.
Tightly Coupled Components: Ideal for scenarios where multiple containers need to work closely together, for instance, a main application container and a helper container.
Separation of Concerns: Allows the separation of different functionalities into distinct containers, each handling a specific task.
Init Container
Init containers are specialized containers that run before the main application containers in a pod. They are primarily used to perform initialization tasks that must be completed before the main containers start.
Characteristics of Init Containers:
Run Sequentially: Init containers run one at a time in sequence. Each init container must complete successfully before the next one starts.
Transient: Once all init containers complete successfully, they are terminated, and the main application containers start.
Different Configuration: Init containers can have different images and configurations from the main containers, allowing them to perform setup tasks that the main containers do not require.
Use Cases for Init Containers:
Setup Tasks: Performing setup tasks like database schema migrations or pre-fetching data.
Dependency Checking: Ensuring that all dependencies are available before the main application starts.
Configuration Management: Setting up configuration files or secrets required by the main containers.
Example
Create a file mypod.yaml
and paste the content below into it:
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: "shivam"
initContainers:
- name: init-mycontainer
image: busybox:1.28
command: ['sh', '-c']
args: ['until nslookup myservice.default.svc.cluster.local; do echo waiting to service up; sleep 2 ; done']
Explanation of this File
apiVersion: v1
Specifies the API version used to create this object. Here, v1
is the stable API version for core Kubernetes objects like pods.
kind: Pod
Specifies the type of Kubernetes object being created. In this case, it's a Pod.
metadata
Metadata provides information about the pod.
name: myapp Sets the name of the pod to
myapp
.labels Adds labels to the pod for identification and grouping purposes.
- name: myapp-pod Adds a label with key
name
and valuemyapp-pod
.
- name: myapp-pod Adds a label with key
spec
Spec defines the desired state of the pod, including the containers it runs.
containers
Defines the list of containers that run in the pod.
- name: myapp-container Names the container
myapp-container
.image: busybox:1.28 Specifies the container image to use. In this case, it's
busybox
version1.28
.command: ['sh', '-c', 'echo The app is running! && sleep 3600'] Sets the command to run in the container. Here, it runs a shell command that prints "The app is running!" and then sleeps for 3600 seconds (1 hour).
env Defines environment variables for the container.
- - name: FIRSTNAME Sets an environment variable
FIRSTNAME
with the value"shivam"
.
- - name: FIRSTNAME Sets an environment variable
initContainers
Defines the list of init containers for the pod. Init containers run to completion before any app containers start.
- name: init-mycontainer Names the init container
init-mycontainer
.image: busybox:1.28 Specifies the container image to use. In this case, it's
busybox
version1.28
.command: ['sh', '-c'] Specifies the command to run in the init container. The command uses the shell (
sh
) and the-c
option allows the execution of a shell command string.arg: ['until nslookup myservice.default.svc.cluster.local; do echo waiting to service up; sleep 2 ; done'] Provides the arguments for the command. Here, the command repeatedly checks (
nslookup
) if the servicemyservice.default.svc.cluster.local
is up. If not, it prints "waiting to service up" and sleeps for 2 seconds before trying again. Theuntil
loop continues until thenslookup
command succeeds.
This YAML file defines a Kubernetes pod with one init container and one application container. The init container ensures that a specific service (myservice.default.svc.cluster.local
) is available before the main application container starts running. The application container runs a simple shell command that prints a message and then sleeps for an hour.
Now apply this file with the command:
kubectl apply -f mypod.yaml
In the image, you can see that our pod is created, In our pod there are two containers one is myapp( application container) and other one is init-container, but our application container is not running because it is waiting for the init container to run, and the init container is waiting for the condition to be satisfied as specified in our YAML file.
You can see the logs using the command:
kubectl logs pod/<pod-name>
And to see the logs of the init-container, use:
kubectl logs pod/<pod-name> <init-container-name>
It shows that it is waiting for the service to be up and keeps checking every 2 seconds, as specified in the YAML file.
Now we will create a deployment and expose it to a myservice
service.
From the image, we can see that our myapp
pod is running because the init container was waiting for myservice
, and myservice
was created.
Now check the logs of the init-container again using:
kubectl logs pod/myapp init-mycontainer
Now it is getting the response, as seen in the above image.
We already set an environment variable in our myapp
pod, and to see that we can use the command:
kubectl exec -it myapp -- printenv
We can have multiple init-containers in the pod, and to run the main application, they should all run first.
Sidecar Containers
Sidecar containers are auxiliary containers that run alongside the main container(s) within the same pod. They help extend and enhance the functionality of the main application container without modifying it.
Characteristics of Sidecar Containers:
Run Concurrently: Sidecar containers run concurrently with the main containers and share the pod's lifecycle.
Complementary Functions: They provide supplementary functions such as logging, monitoring, or proxying.
Use Cases for Sidecar Containers:
Logging: Collecting and shipping logs from the main application container to a central logging system.
Monitoring: Running monitoring agents that collect metrics and health information.
Proxying: Acting as a reverse proxy to manage traffic to and from the main application container.
Data Synchronization: Synchronizing data between the main application and external services or systems.
We will be doing more hands-on with sidecar containers in the coming days.
Thank you for reading my blog. If you have any queries, please ask in the comments. I will surely answer your questions.