Photo by PJH on Unsplash

On this page

A classic example of multi container pods is when you have your Main app Container separated from a Container that has helper code. That way you separate responsibility and the Helper Container can be reused in other pods.

image-21-1024x823.png

Multi Container patterns

Depending on the role of each container in a Pod, best practices (or design patterns) emerged. All patterns presented here are based on a pattern called Sidecar, which is simply having two Containers in one Pod: A Main Container and a Sidecar Container.

We can further specify whether the Sidebar Container has to run to completion before(!) the Main Container starts. If yes, then we call this an **Init Container **or Init Pattern. If not, both app containers are running concurrently and we call it Sidecar pattern.

Init Pattern

One use case for this pattern is to have the Sidecar pull down code from a git repository initially(!) and only after that is done, the web server Container will start using that code.

image-23-1024x607.png

To make this happen we have to configure the Pod accordingly. Kubernetes even has a special configuration property initContainers for that:

init-git-sync.yml
apiVersion: v1
kind: Pod
metadata:
name: git-syncer
labels:
app: git-syncer
spec:
initContainers:
- image: k8s.gcr.io/git-sync:v3.1.5
name: init-sync-ctr
volumeMounts:
- name: html
mountPath: /tmp/git
env:
- name: GIT_SYNC_REPO
value: https://github.com/your-username/your-repo.git
- name: GIT_SYNC_BRANCH
value: master
- name: GIT_SYNC_DEPTH
value: "1"
- name: GIT_SYNC_DEST
value: "html"
- name: GIT_SYNC_ONE_TIME # only get the git files initially and then quit
value: "true"
containers:
- image: nginx
name: web
volumeMounts:
- name: html
mountPath: /usr/share/nginx
volumes:
- name: html
emptyDir: {}
---
apiVersion: v1
kind: Service
metadata:
name: git-syncer
spec:
selector:
app: git-syncer
ports:
- port: 80
type: LoadBalancer

Kubernetes runs those Init Containers in order and sequential (not parallel) and guarantees that they are run before the Main Container.

But what if we want to continue to update our running app, even after the initial git sync? Well, we create a similar configuration and put them in a (non-init) sidecar container:

apiVersion: v1
kind: Pod
metadata:
name: git-syncer
labels:
app: git-syncer
spec:
containers:
- image: nginx
name: web
volumeMounts:
- name: html
mountPath: /usr/share/nginx/
- image: k8s.gcr.io/git-sync:v3.1.5
name: init-sync-ctr
volumeMounts:
- name: html
mountPath: /tmp/git
env:
- name: GIT_SYNC_REPO
value: https://github.com/your-username/your-repo.git
- name: GIT_SYNC_BRANCH
value: master
- name: GIT_SYNC_DEPTH
value: "1"
- name: GIT_SYNC_DEST
value: "html"
volumes:
- name: html
emptyDir: {}
---
apiVersion: v1
kind: Service
metadata:
name: git-syncer
spec:
selector:
app: git-syncer
ports:
- port: 80
type: LoadBalancer

Another use case is if you want to prepare environment variables or wait for the availability of a service before the Main Container executes. In the following example we execute a command that continuously looks up (1 seconds intervals) if the service my-service is available:

init-pod.yml
apiVersion: v1
kind: Pod
metadata:
name: ps-init
labels:
app: initializer
spec:
initContainers:
- name: init-ctr
image: busybox
command: ['sh', '-c', 'until nslookup my-service; do echo waiting for my-service; sleep 1; done; echo Service found!']
containers:
- name: web-ctr
image: myrepo/web-app:1.0
ports:
- containerPort: 8080

If any Init Container fails, the pod restarts (unless restart policy it set to ‘never’) and the Init Containers run again! That’s why it is important that your init container are idempotent, meaning they should have the same predictable outcome every time they are started. Keep resource limits low for Init Containers.

Service Mesh pattern

Service Mesh pattern is another Sidecar pattern. It serves as a Pod’s single entry point. It allows you to add additional features/services like monitoring, encrypting, telemetry, filtering, logging of your Pod.

image.png

Adapter pattern

The Adapter pattern takes non standard output and transforms it to standardised output via a Adapter Container, so that an External system can process it.

image-22-1024x592.png

For example, Prometheus is a monitoring tool that uses this pattern.

Ambassador pattern

The Ambassador pattern proxies traffic from the main container to an external system:

image-24-1024x471.png

Search articles

Type a word to search published articles.

Open the search page