Building Kubernetes Multi-Container Pods

AhmedIhab
3 min readAug 28, 2022

--

What is Kubernetes Pod?
Pods are the smallest, most basic deployable objects in Kubernetes. A Pod represents a single instance of a running process in your cluster. In other words, if you need to run a single container in Kubernetes, then you need to create a Pod for that container. At the same time, a Pod can contain more than one container, usually, because these containers are relatively tightly coupled

How the containers are tightly coupled?
because they are sharing resources such as network and storage volumes, as they can reach each other in the pod at different ports on localhost.

Why does Kubernetes allow Multi-Containers in the same pod?
The primary reason that Pods can have multiple containers is to support helper applications that assist a primary application. For example
- A container that performs logging and metrics collection from the main container,
- A container that performs health checks … etc

Multi-Container Pod

Let’s dive into Multi-Container Design Patterns

We will talk about sidecar and ambassador patterns

  1. Sidecar Container
    A sidecar container performs tasks to assist the main container. For examples:
  • Perform logging and metrics collection.
  • Perform health checks.
  • Perform configuration management.

Let’s take an example

We will create two containers that communicate with each other by making both of them point to the same shared volume, The main container writes text inside a file in the volume and the sidecar container reads what the main container wrote

apiVersion: v1
kind: Pod
metadata:
name: sidecar-test
spec:
containers:
- name: writer
image: busybox:stable
command: ['sh', '-c', 'echo "The writer wrote this!" > output/data.txt; while true; do sleep 5;done']
volumeMounts:
- name: shared
mountPath: /output
- name: sidecar
image: busybox:stable
command: ['sh', '-c', 'while true; do cat /input/data.txt; sleep 5; done']
volumeMounts:
- name: shared
mountPath: /input
volumes:
- name: shared
emptyDir: {}

2. Ambassador Container
The Ambassador container is a special type of sidecar container which simplifies accessing services outside the Pod. When you are running applications on Kubernetes it’s a high chance that you should access the data from the external services, but what if the service that your pod tries to connect to its port has been changed?..
With Ambassador container there is no problem in this case as it acts as a proxy that forwards your pod request to the right service port, also it hides the complexity and provides the uniform interface to access these external services

In a nutshell, it is responsible for proxying connections from the application container to other services

Ambassador container example

Let’s take an example

First, let’s create an Nginx pod with its service component, we will make our ambassador container forward the requests to this pod

apiVersion: v1
kind: Pod
metadata:
name: ambassador-test-webserver
labels:
app: ambassador-test
spec:
containers:
- name: nginx
image: nginx:stable
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: ambassador-test-svc
spec:
selector:
app: ambassador-test
ports:
- protocol: TCP
port: 8081
targetPort: 80

After that let’s create our main container with its Ambassador
Notice that the main container does a curl on localhost:8080 which is the Ambassador container as we can see from Ambassador container configMap it binds on port 8080 and forward the request to ambassador-test-svc:8081 which is Nginx service that we have created above

apiVersion: v1
kind: ConfigMap
metadata:
name: haproxy-config
data:
haproxy.cfg: |
frontend ambassador
bind *:8080
default_backend ambassador_test_svc
backend ambassador_test_svc
server svc ambassador-test-svc:8081
---
apiVersion: v1
kind: Pod
metadata:
name: ambassador-test
spec:
containers:
- name: main
image: radial/busyboxplus:curl
command: ['sh', '-c', 'while true; do curl localhost:8080; sleep 5; done']
- name: ambassador
image: haproxy:2.4
volumeMounts:
- name: config
mountPath: /usr/local/etc/haproxy/
volumes:
- name: config
configMap:
name: haproxy-config

Don’t forget to hit the Clap and Follow buttons to help me write more articles like this.

--

--

AhmedIhab

A DevOps & Cloud engineer. Mainly interested in infrastructure, Linux, and Networking.