Chapter 15. Sidecar

A Sidecar container extends and enhances the functionality of a preexisting container without changing it. This pattern is one of the fundamental container patterns that allows single-purpose containers to cooperate closely together. In this chapter, we learn all about the basic Sidecar concept. The specialized follow-up patterns, Adapter and Ambassador, are discussed in Chapter 16 and Chapter 17, respectively.

Problem

Containers are a popular packaging technology that allows developers and system administrators to build, ship, and run applications in a unified way. A container represents a natural boundary for a unit of functionality with a distinct runtime, release cycle, API, and team owning it. A proper container behaves like a single Linux process—solves one problem and does it well—and is created with the idea of replaceability and reuse. This last part is essential as it allows us to build applications more quickly by leveraging existing specialized containers.

Today, to make an HTTP call, we don’t have to write a client library, but use an existing one. In the same way, to serve a website, we don’t have to create a container for a web server, but use an existing one. This approach allows developers to avoid reinventing the wheel and create an ecosystem with a smaller number of better-quality containers to maintain. However, having single-purpose reusable containers requires ways of extending the functionality of a container and a means for collaboration among containers. The Sidecar pattern describes this kind of collaboration where a container enhances the functionality of another preexisting container.

Solution

In Chapter 1 we described how the Pod primitive allows us to combine multiple containers into a single unit. Behind the scenes, at runtime, a Pod is a container as well, but it starts as a paused process (literally with the pause command) before all other containers in the Pod. It is not doing anything other than holding all the Linux namespaces the application containers use to interact throughout the Pod’s lifetime. Apart from this implementation detail, what is more interesting is all the characteristics that the Pod abstraction provides.

The Pod is such a fundamental primitive that it is present in many cloud-native platforms under different names, but always with similar capabilities. A Pod as the deployment unit puts certain runtime constraints on the containers belonging to it. For example, all containers end up deployed to the same node, and they share the same Pod lifecycle. In addition, a Pod allows its containers to share volumes and communicate over the local network or host IPC. These are the reasons users put a group of containers into a Pod. Sidecar (in some places also called Sidekick) is used to describe the scenario of a container being put into a Pod to extend and enhance another container’s behavior.

A typical example used to demonstrate this pattern is with an HTTP server and a Git synchronizer. The HTTP server container is focused only on serving files over HTTP and does not know how and where the files are coming from. Similarly, the Git synchronizer container’s only goal is to sync data from a Git server to the local filesystem. It does not care what happens to the files once synced, and its only concern is keeping the local folder in sync with the remote Git server. Example 15-1 shows a Pod definition with these two containers configured to use a volume for file exchange.

Example 15-1. Pod with Sidecar
apiVersion: v1
kind: Pod
metadata:
  name: web-app
spec:
  containers:
  - name: app
    image: docker.io/centos/httpd    1
    ports:
    - containerPort: 80
    volumeMounts:
    - mountPath: /var/www/html       3
      name: git
  - name: poll
    image: axeclbr/git               2
    volumeMounts:
    - mountPath: /var/lib/data       3
      name: git
    env:
    - name: GIT_REPO
      value: https://github.com/mdn/beginner-html-site-scripted
    command:
    - "sh"
    - "-c"
    - "git clone $(GIT_REPO) . && watch -n 600 git pull"
    workingDir: /var/lib/data
  volumes:
  - emptyDir: {}
    name: git
1

Main application container serving files over HTTP

2

Sidecar container running in parallel and pulling data from a Git server

3

Shared location for exchanging data between the Sidecar and main application container

This example shows how the Git synchronizer enhances the HTTP server’s behavior with content to serve and keeps it synchronized. We could also say that both containers collaborate and are equally important, but in a Sidecar pattern, there is a main container and a helper container that enhances the collective behavior. Typically, the main container is the first one listed in the containers list, and it represents the default container (e.g., when we run the command: kubectl exec).

This simple pattern, illustrated in Figure 15-1, allows runtime collaboration of containers, and at the same time, enables separation of concerns for both containers, which might be owned by separate teams, using different programming languages, with different release cycles, etc. It also promotes replaceability and reuse of containers as the HTTP server, and the Git synchronizer can be reused in other applications and different configuration either as a single container in a Pod or again in collaboration with other containers.

Sidecar Pattern
Figure 15-1. Sidecar pattern

Discussion

Previously we said that container images are like classes, and containers are like the objects in object-oriented programming (OOP). If we continue this analogy, extending a container to enhance its functionality is similar to inheritance in OOP, and having multiple containers collaborating in a Pod is similar to composition in OOP. While both of these approaches allow code reuse, inheritance involves tighter coupling between containers and represents an “is-a” relationship between containers.

On the other hand, a composition in a Pod represents a “has-a” relationship, and it is more flexible because it doesn’t couple containers together at build time, giving the ability to later swap containers in the Pod definition. On the other hand, compositions in Pods mean you have multiple containers (processes) running, health checked, restarted, and consuming resources as the main application container does. Modern Sidecar containers are small and consume minimal resources, but you have to decide whether it is worth running a separate process or whether it is better to merge it into the main container.

From a different point of view, container composition is similar to aspect-oriented programming, in that with additional containers we introduce orthogonal capabilities to the Pod without touching the main container. In recent months, use of the Sidecar pattern has become more and more common, especially for handling networking, monitoring, and tracing aspects of services, where every service ships Sidecar containers as well.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset