Microservice Pattern – Kubernetes Sidecar Pattern

Overview:

Design Patterns are repeatable & reusable solutions for commonly occurring problems in the software/architectural design and they encourage the developers to design a highly cohesive and loosely coupled applications. Design patterns can be used in the infrastructure/deployment design as well in this modern microservices era! We are going to take a look one such design pattern – Sidecar pattern in this article.

Sidecar pattern can be related to Decorator design pattern in the software design which can add additional functionality to the existing instance at run time.

Problem Statement:

Microservices follow the single responsibility principle and they are designed to handle the specific business sub-domain/bounded-context well. A developer while developing the microservice application might have some assumptions like some properties/jars/files should be present on certain path for the application to work fine. For ex: Let’s consider nginx – a webserver – running inside a docker container to serve some static content for our application. The nginx application is able to successfully serve the content from certain path from the container.

 

Even though this approach works just great, some recent business requirement might say once in a while they would like to change the theme of the static html page. Developers will be able to quickly apply the change and push it to the version control system. But any change in the html content will require rebuilding the docker image and re-deployment with new image. This is a problem. We need a solution for our nginx server to serve the content by pulling the latest changes.

Lets see how we could solve using sidecar pattern. [This example is chosen to explain the sidecar pattern. In real life, We might go with AWS Cloudfront + S3 combination to serve the static content. Also not everyone uses cloud. There are many organizations which are still using the on-prem solutions].

Sample Application:

  • I have a very simple HTML file as shown here.
<html>

<body bgcolor="#FFFFFF">
    <h1><strong>This is sidecar pattern demo!</strong></h1>
</body>

</html>
  • I create a Dockerfile as shown here and build a docker image with the name vinsdocker/nginx
FROM nginx

ADD index.html /usr/share/nginx/html/index.html
  • If I can run the below command, I am able to see the content at localhost
docker run -p 80:80 vinsdocker/nginx

Kubernetes Resources:

I am going to deploy the above docker container in a kubernetes cluster. For that I am creating deployment and service resources.

  • Deployment yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: nginx
  name: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - image: vinsdocker/nginx
        name: nginx
        ports:
        - containerPort: 80
  • service yaml
apiVersion: v1
kind: Service
metadata:
  labels:
    app: nginx
  name: nginx
spec:
  ports:
  - name: 80-80
    port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: nginx
  type: LoadBalancer
  • After applying these commands, I am able to access the application from the Kubernetes cluster. At this point, all the end users can access the application.
kubectl apply -f deployment.yaml
kubectl apply -f service.yaml

  • Our requirement is to periodically change the content based on the business requirement and make the nginx serve the latest content w/o rebuilding docker image in a kubernetes cluster.

Shared Volume:

In kubernetes pod, we can run multiple containers. All these containers can share volumes. We are going to make use of this concept to accomplish our requirement. That is, we would be creating a separate container called sidecar which is responsible for downloading the latest content. Once it is downloaded, it will place the new content for the nginx container to access in the shared volume. So that nginx can serve the latest content.

 

Sidecar:

Aim of this sidecar container is to add the required additional functionality without touching the main app we have built above.

  • Let’s add simple shell script to pull the content from some source every 5 seconds. I use an environment variable STATIC_SOURCE through which I would be passing the github file path.
#!/bin/bash

while :
do
    wget --no-cache -O temp.html $STATIC_SOURCE
    mv temp.html html/index.html
    sleep 5
done
  • Dockerfile – build this as vinsdocker/sidecar
FROM alpine

WORKDIR /usr/share/nginx

ADD content-refresher.sh content-refresher.sh

ENTRYPOINT sh content-refresher.sh
  • The above deployment.yaml is updated to include the sidecar container now.
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: nginx
  name: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - image: vinsdocker/sidecar
        name: sidecar
        env:
        - name: STATIC_SOURCE
          value: https://raw.githubusercontent.com/vinsguru/vinsguru-blog-code-samples/master/kubernetes/sidecar-pattern/static-content/index.html
        volumeMounts:
        - name: shared-data
          mountPath: /usr/share/nginx/html   
      - image: vinsdocker/nginx
        name: nginx
        ports:
        - containerPort: 80
        volumeMounts:
        - name: shared-data
          mountPath: /usr/share/nginx/html/
      volumes:
      - name: shared-data
        emptyDir: {}
  • Apply this command to redeploy our app with sidecar.
kubectl apply -f deployment.yaml
  • Now whenever we change the content in the static file and push it to github, sidecar pulls the content and make nginx serve the updated content.

Summary:

We were able to successfully demonstrate sidecar pattern in this article and it is a good idea to add additional functionalities to the existing app without modifying the app. For ex: We can add logging, monitoring etc to the existing app. It is also reusable and not language specific. For ex: If someone else with apache-server instead of nginx needs a similar feature, we can simply include the sidecar container we have built.

Happy coding 🙂

 

 

Share This:

4 thoughts on “Microservice Pattern – Kubernetes Sidecar Pattern

  1. This example is for html file so can you please let us know about the jar file addition in sidecar container & how it will impact without redeploy?

  2. @vlns : Thank you for your reply . So in place of the HTML file I can use the jar file from the repo.

    1. Sidecar containers are great to provide any content to the app & archive any files generated by app. However I would not prefer the jar approach you are suggesting!

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.