Exploring the World of Container Patterns
Understanding Sidecar and Ambassador Patterns
Introduction
Imagine you are hosting a party and want to ensure all your guests are having a good time. You may designate a few friends as ambassadors to greet and assist guests as they arrive, or hire a sidecar bartender to mix and serve drinks. These roles help ensure a seamless and enjoyable experience for your guests, just like how container patterns such as ambassadors and sidecars can improve the performance and reliability of your applications.
In the world of software development, containers are virtualized environments that package applications and their dependencies, allowing for efficient and scalable deployment. However, managing containers can become complex as the number of services and applications grow. This is where container patterns such as ambassadors and sidecars come into play. They provide additional functionality to help manage and optimize the performance of your containers. In this article, we'll explore these two container patterns and how they can improve the reliability and efficiency of your applications.
Why we need Container Patterns:
With the rise of microservices and distributed computing, containerization has gained widespread popularity in software development. It involves wrapping software code and its dependencies in a container, which ensures that it runs consistently and efficiently on any infrastructure.
In distributed architecture that consists of many microservices, it's important to keep the microservices code focused on the business logic while keeping non-functional aspects like security, service discovery, proxy, logging, and platform configuration separate. This is where container patterns come in handy.
There are two popular container patterns known as Sidecar and Ambassadors. The Sidecar pattern involves running a supplementary process alongside a main application to provide additional functionality. On the other hand, the Ambassador pattern uses a sidecar proxy to manage network traffic between microservices, providing a cleaner separation of concerns and greater flexibility. These container patterns can help developers create more efficient, scalable, and maintainable microservices-based applications.
Sidecar pattern:
The sidecar pattern is a common approach in which a workload is scheduled on the same host with the intent of performing specific functions that are not directly related to your application. There are various use cases for this pattern, such as request authentication/authorization, service discovery, and adding HTTPS to legacy services.
One example of this pattern is updating static website content on a web server without the need for rebuilding a Docker image in a Kubernetes cluster. Kubernetes pods can support multiple containers with shared volumes, which we can utilize to accomplish our requirements. We will create a separate container called a sidecar that is responsible for downloading the latest content from the repository periodically or on-demand, based on the configuration. Once the new content is downloaded, it will place in the shared volume for the application server container to access. As a result, all our clients will be able to see the latest content without the need for rebuilding the container image.
Ambassador:
The Ambassador pattern is a powerful tool in containerization that facilitates interactions between the application container and external services. Essentially, the ambassador container serves as a broker that manages interactions between the application container and the outside world, while also taking on responsibilities such as load distribution, monitoring, and retries. This creates a symbiotic pairing between the two containers, as they are tightly linked and dependent on each other.
Without the Ambassador pattern, microservices may struggle to communicate with each other effectively, as they may not know the exact location of other microservices. However, with the Ambassador pattern, microservices can interact with each other seamlessly, using service discovery mechanisms to locate each other by name. This service discovery can occur at the DNS level or at an application level, making the Ambassador pattern a versatile and valuable tool for facilitating efficient communication between microservices.
Usecase: Let's assume we have one database server which is not able to handle the application load. We want to shard the data but without changing the application.
Sharding splits up the data into multiple disjoint pieces, each hosted by a separate machine. One approach is to build all of the sharding logic into the sharded service itself. In this approach, the sharded service also has a stateless load balancer that directs traffic to the appropriate shard. Effectively this load balancer is a distributed ambassador as a service. The alternative is to integrate a single-node ambassador on the client side to route traffic to the appropriate shard. We can introduce an ambassador container that contains all of the logic needed to route requests to the appropriate storage shard. Thus, your front end or middleware application only connects to what appears to be a single storage backend running on localhost.
Another interesting application of an ambassador-type container is in the deployment architecture called Canary: let’s imagine we want to test the deployment of a new version of our microservice, transferring only a small percentage of the total requests. This deployment mode can be managed with a container ambassador who rotates the desired percentage of traffic to the new container.
Summary
The article discusses two container patterns, Ambassador and Sidecar, which are used to manage interactions between microservices in a distributed architecture. The Ambassador container acts as a mediator between the application container and the outside world, taking on the responsibility of distributing network load, retries, and monitoring. On the other hand, the Sidecar pattern is used to keep non-functional aspects like security, service discovery, and logging separate from the microservices code.