The idea of decoupling a large Monolith application into sub components known as microservices enables us to develop and deploy a set independent small and reusable code. This architecture then helps us to scale up or down as well as modify each service as required as opposed for modifying the entire application.

However at times, we may need two services to work together such as web server and a logging service. We need one agent instance per web server instance that are paired together. We don't want to merge and bloat the code of the two servcies as each of them target different functionalities. we would still like them to be devloped and deployed separately.
We only need these two functionalities to work together. We need one agent per webserver instance paired together that can scale up and down together.

That is why we have multi-container pods that share the same life cycle (created together and destroyed together), share the same network space (they can refer each other as locolhost) and they have access to the same storage volumes.
This way, we need to have to establish volume sharing or services between the pods to enable communication between them.

To Create a multi-container pod, add the new container to the definition file.

pod-definition file

apiVersion: v1
kind: Pod
metadata:
  name: simple-webapp
  labels:
    name: simple-webapp
spec:
  containers:
  - name: simple-webapp
    image: simple-webapp
    ports:
    - containerPort: 8080

  - name: log-agent
    image: log-agent

There are three common design patterns for multi-container pods.

  • Sidecar
  • Ambassdor
  • Adapter

Example for sidecar:
Deploying a logging agent alongside a webserver to collect logs and forward them to a central log server.

Say we have multiple applications generating logs in different formats, it would be hard to process the various lof formats on the central logging server.For sending the logs to the central server, we would like to convert logs to a common format.For this we deploy the Adapter container.
Adapter container processes the logs before sending it to the central server.

Our application communicates to different database instances at different stages of development. local database for development, one for testing and one for production. We must make sure to modify this connectivity in our application code depending on the environment we are deploying our application to.
We may choose to outsource this logic to a separate container within a pod, so that our application can always refer to a database at locolhost and the new container will proxy that request to the right database. This is known as ambassador container. These are the different design pattern in multi-container pods.

Implemention of these patterns using the pod-definition file will be same, that is just having multiple containers in the pod-definition file.