How to Manage Multi-Container Pods in Kubernetes

Updated: January 30, 2024 By: Guest Contributor Post a comment

Introduction

When deploying applications in Kubernetes, you will eventually encounter the need to run multiple containers within a single pod. Kubernetes pods are designed to support multiple containers to run in a shared context, which can be critical for supporting sidecar, adapter, or ambassador patterns among others. This tutorial will take you through managing multi-container pods including their creation, communication, and managing their resources.

Understanding Multi-Container Pods

In Kubernetes, a Pod is the smallest deployable unit that can be created, scheduled, and managed. It’s common to have a Pod running just a single container, but Kubernetes also allows you to run multiple containers within the same Pod. These co-located containers can share resources, synchronize their execution, and communicate seamlessly, leveraging the same network and storage.

All containers inside a single pod:

  • Share the same Network IP – they can communicate with each other using localhost.
  • Have access to the same volumes – allowing them to share files.
  • Are scheduled on the same physical or virtual machine.

Basic Pod with Multiple Containers

To get started, let’s create a basic Pod YAML definition that includes two containers:

apiVersion: v1
kind: Pod
metadata:
  name: multi-container-pod
spec:
  containers:
  - name: app-container
    image: busybox
    command: ['sh', '-c', 'echo "Hello from the app container" && sleep 3600']
  - name: sidecar-container
    image: busybox
    command: ['sh', '-c', 'echo "Hello from the sidecar container" && sleep 3600']

To apply this configuration and create the pod in Kubernetes, use:

kubectl apply -f multi-container-pod.yaml

Once the Pod is running, you can check the logs of each container:

kubectl logs multi-container-pod -c app-container
kubectl logs multi-container-pod -c sidecar-container

You should see the “Hello” messages from both containers.

Inter-container Communication

The containers within a pod can communicate using ‘localhost’, as they share the network namespace. Here’s an example of two containers communicating over a local socket:

apiVersion: v1
kind: Pod
metadata:
  name: intercom-pod
spec:
  containers:
  - name: server
    image: busybox
    command:
    - sh
    - -c
    - 'nc -lk -p 12345 -e echo "Hello World!"'
  - name: client
    image: busybox
    command:
    - sh
    - -c
    - 'sleep 30; nc localhost 12345'

To verify communication between the containers, check the logs after applying the configuration:

kubectl logs intercom-pod -c client

The client container should output “Hello World!” received from the server container.

Managing Resources for Containers

In multi-container pods, you may need to allocate resources differently for each container. Here is an example of how to specify resource requests and limits:

apiVersion: v1
kind: Pod
metadata:
  name: resources-pod
spec:
  containers:
  - name: primary-container
    image: nginx
    resources:
      requests:
        memory: "64Mi"
        cpu: "250m"
      limits:
        memory: "128Mi"
        cpu: "500m"
  - name: secondary-container
    image: redis
    resources:
      requests:
        memory: "32Mi"
        cpu: "100m"
      limits:
        memory: "64Mi"
        cpu: "200m"

Apply the pod definition to see the resources in effect. Kubernetes will ensure that requests are guaranteed and limits are enforced.

Advanced: Using Init Containers

Init containers are specialized containers that run before app containers and are part of a pod’s initialization. Here’s an example of using an init container:

apiVersion: v1
kind: Pod
metadata:
  name: init-container-pod
spec:
  initContainers:
  - name: init-myservice
    image: busybox
    command: ['sh', '-c', 'echo init container started; sleep 5']
  containers:
  - name: myservice
    image: nginx
  - name: mysidecar
    image: redis

Apply this and then check the status of the pod. The init container must complete before the other containers start.

Sharing Volumes between Containers

You can share data between containers in a Pod using shared volumes. Here is how you can define a Pod with shared volumes:

apiVersion: v1
kind: Pod
metadata:
  name: shared-volume-pod
spec:
  volumes:
  - name: shared-data
    emptyDir: {}
  containers:
  - name: producer
    image: busybox
    volumeMounts:
    - name: shared-data
      mountPath: /usr/share/data
    command: ['sh', '-c', 'echo "Data from producer" > /usr/share/data/index.html']
  - name: consumer
    image: busybox
    volumeMounts:
    - name: shared-data
      mountPath: /usr/share/data2
    command: ['sh', '-c', 'cat /usr/share/data2/index.html']

To test the shared volume, create the pod and then check the logs of the consumer container to see the data written by the producer container.

Conclusion

Managing multi-container pods in Kubernetes provides powerful ways to structure applications. By using shared volumes, network spaces, and careful resource allocation syntax, we can build complex, efficient, and tightly coupled systems that work harmoniously in a single pod. With the provided examples, you should be well on your way to mastering multi-container pods in Kubernetes.