Unveiling Sidecar Containers in Kubernetes

To extend the functionality of the application container in the Kubernetes pod

A Sidecar pattern can separate an application’s functionalities into different processes. With the help of the sidecar design pattern, we may expand the functionality of the main application  without modifying its codebase.

From a software point of view, a sidecar is attached to a core application and extends or enhances its functionality, much like a sidecar is linked to a motorcycle. The main application is loosely connected with a sidecar.

In this hands-on lab, we will be learning about different multi-container pod design patterns and learning in deep about side car pattern.

Multi Container Pod Design Patterns

As mentioned below, multiple containers can run inside a single pod for different use cases, which gave rise to multi-container pod design patterns.

Init Containers

Init containers reduce the burden of the main container by preparing the setup. Init containers start and terminate before the main application starts and should be run to completion without fail.

Figure 1: init containers
Figure 1: init containers

Multiple init containers run in a sequence and have to be completed before the application container starts. If any init container crashes, the kubelet resumes again and again until it succeeds. If the restart fulfils backoff time limit and init container fails to succeed then the entire pod is declared as failed.

Sidecar Containers

Application Container is the main container from which the application is served, and sidecar containers provide additional features to the main container. Sidecar containers run along with the main container and follow the lifecycle of the application container. 

They share the resources like storage, network with the main container. It communicates with the main container via localhost to reduce latency between them. If developers need to add extra features to the main app, they can create sidecar containers in the same pod. 

Figure 2: Sidecar containers
Figure 2: Sidecar containers

For example, the main application writes a log file and sidecar reads the log file continuously and process it further.  

Adapter Containers

It adjusts the output in the desired format. They standardize the output and interface for all multi-containers. If a custom container needs output in a particular format required to serve, the adapter container converts and shares with it. 

Figure 3: Adapter containers
Figure 3: Adapter containers

For example, monitoring services like prometheus check if the application is working as expected or not. Data coming from the endpoints must be in a format as prometheus required, for that the adapter container plays a key role in translating the output.

Ambassador Containers

It is a way to connect the containers with the outside world. It gives a proxy to connect with external services.

Figure 4: Ambassador containers
Figure 4: Ambassador containers

For example, providing different database access for local, production or test environments to the main application, ambassador container works as a proxy. Please refer to multi container patterns in detail here.

Benefits of Using Sidecar Containers

Durability: Main container  and  sidecar container can be written in different programming languages. If the application is modified, there is no need to write sidecar logic again to get the same service as before.

Independency: If Application deployed in main container and its working fine. After some time the user needs to add an extra feature using a sidecar container and can deploy sidecar independently as they are loosely coupled.

Module structure: If developers need to add multiple features to the application container they have to create sidecar containers for each feature. Each container works as a different module.

Protect against failure: It is possible to configure sidecar features in the main container, but in that case, if one service fails, it affects the performance of the main application. In sidecar patterns, both containers are independent so if sidecar fails, at least custom services can survive with limited features.

Drawbacks of Using Sidecar Containers

Latency due to loopback interface: Avoid using sidecar containers in applications that require prompt response. Both containers are in the same pod, so latency does not impact much, but applications that can’t afford latency, such as trading, games or live streaming should not use a sidecar pattern.

Difficult to debug: Inter process communication becomes complex with multiple sidecar containers. It is difficult to manage and debug them independently as they follow the main container lifecycle.

Cost: Application and sidecar containers run on the same pod. Half pod can not run so with multiple copies of applications, it creates multiple copies of sidecar also which may lead to more resource consumption. 

Reading Logs of Application through Sidecar

In this part, we’ll build up a multi-container pod with the principal application running in one container and the sidecar application running in the other. The sidecar container will continuously read the log file from a shared volume which will be generated by the main application container.

  • multi-container pod and service are defined in aayu-verse.yaml configuratin file stored in lab environment.
# aayu-verse.yaml
apiVersion: v1
kind: Pod
metadata:
  name: aayu-verse
  labels:
    app: webpage
spec:
  containers:
  - name: main-cont
    image: pratikshahp/aayuverse
    volumeMounts:
    - name: volume
      mountPath: /var/log/nginx
  - name: sidecar-cont
    image: busybox
    command: ["sh","-c","i=1; while true; do echo $i': read log from main-container!!!'; i=$((i+1)); cat /var/log/nginx/access.log; sleep 10; done"]
    volumeMounts:
    - name: volume
      mountPath: /var/log/nginx
  volumes:
  - name: volume
    emptyDir: {}
---
apiVersion: v1
kind: Service
metadata:
  name: svc-aayuverse
spec:
  type: NodePort
  ports:
  - port: 80
    targetPort: 80
    nodePort: 31001
  selector:
    app: webpage
  • Create a pod and service using  aayu-verse.yaml manifest 
kubectl create -f aayu-verse.yaml
Figure 5: Pod and Service created
Figure 5: Pod and Service created
  • To get the pods and services and its status
kubectl get all

Make sure that pods are in running state and retrieve the port of the node from service.

Figure 6: Retrive the details of all resources
Figure 6: Retrive the details of all resources
  • To verify the result, is sidecar container able to read log file?
kubectl logs aayu-verse -c sidecar-cont

As of now we are getting the content only from the side-car container, as no logs have been generated from the main application. 

Figure 7: Verify side-car container
Figure 7: Verify side-car container

But once we access the main application, our sidecar container would be able to read them.  Let’s see that in the next few steps. 

  • To get node ip
kubectl get nodes -o wide
Figure 8: Retrive node ip from INTERNAL-IP column
Figure 8: Retrive node ip from INTERNAL-IP column
  • To access the webpage use node ip and nodeport from service
curl <node_ip>:<node_port>

On the terminal we get a webpage in html format.

                                                                                      OR

  • Click on port-31001 URLs
Figure 9: Access the web page with mapped NodePort
Figure 9: Access the web page with mapped NodePort
  • To verify logs again
kubectl logs aayu-verse -c sidecar-cont
Figure 10: Read and Print log by side-car container
Figure 10: Read and Print log by side-car container

Here we go!!! Logs are generated by main container and read by sidecar container

  • To stop the execution Press ctrl+c

Other Use-cases of Side-car Containers

Authenticating legacy applications with a reverse proxy

A reverse proxy that handles authentication is one application for this design pattern. The plan is to run a Flask application in a container inside a pod. One should construct an nginx container in the same Pod.

Figure 11: Reverse proxy
Figure 11: Reverse proxy

Using the internal pod network, this nginx server will establish a connection with the Flask application and implement authentication.

Authentication in Microservices

Business logic is defined in a custom application in the form of microservices, which is decoupled with a sidecar container where authentication logic is defined. Although both containers are independent, sidecar follows the same lifecycle as their associated service. They are created and terminated with custom service. The main advantage is, there is no need to write authentication logic for each microservices. With a sidecar pattern it will be reusable.

Share a Volume or Network

Applications where users can upload images, audio, video but containers require small size so one can attach sidecar with the compression feature.

Figure 12: Shared volume between application and sidecar container
Figure 12: Shared volume between application and sidecar container

Contents added by user stores in a shared volume, used by sidecar, compressed without compromising in quality and sent back to the storage which is used by the application.

Supports dynamic configuration

To upgrade the main container configuration regularly, create a sidecar container that reads the URL for updated configuration at regular time intervals and stores it in a shared volume so every time the application reads the updated configuration and serves up to date.

Conclusion

If we want to increase the capability of developing applications or already developed applications we can append sidecar as a secondary container. For which features sidecar containers will be deployed is up to the requirements and use case of a particular application. This article is just giving a brief overview of sidecar containers with examples. We would love to hear comments from more people for betterment.

Join Our Newsletter

Share this article:

Table of Contents