Container Orchestration
Container Orchestration
In the modern landscape of software development and deployment,
containers have emerged as a pivotal technology, offering unparalleled
portability and consistency for applications.
Many applications today adopt a microservice based architecture,
where a single application is split into multiple services that communicate
with each other using protocols like HTTP. When using containers with
microservices, each individual service would run in its own container. As an
application grows in size, the number of services increases, thereby increasing
the number of containers. However, managing a large number of containers across
various hosts can quickly become complex and unwieldy. This is where container
orchestration steps in, transforming chaotic deployments into streamlined,
automated operations.
Orchestration is not a new term, and it is not specific to
containers. In the realm of computing, orchestration refers to the
automated configuration, coordination, and management of computer systems,
middleware, and services. When applied to containers, it means the automated
management of containerized applications, including their deployment, scaling,
networking, and availability. Most people would relate the term 'orchestration'
with the musical 'orchestra', and it is the perfect analogy to understand orchestration.
In an orchestra individual musicians are highly skilled, but without a
conductor, they might play out of sync or at different tempos, leading to a
cacophony. The conductor ensures all musicians play harmoniously, starting and
stopping at the right times, and adjusting their volume as needed, creating a
beautiful piece of music. Similarly, a container orchestrator ensures all
containers work together efficiently to deliver a cohesive application.
So how is orchestration performed with containers? There are many
popular technologies to choose from including Docker Swarm, Kubernetes,
HashiCorp Nomad, Apache Mesos, Amazon ECS, and Red Hat OpenShift. To understand
how orchestration works, this article would focus on Docker Swarm.
Manager
and Worker Nodes
While the way each technology
handles orchestration varies, a fundamental concept across all is the existence
of manager and worker nodes. But what are nodes in the first place? A node
refers to a single, distinct computing device or entity within a larger system
or network. In the context of orchestration, a node is a physical or virtual
machine that is part of the 'orchestra' and can run containerized
workloads. It is crucial to understand the differences in capacities and
responsibility of the two types of nodes.
A manager node is the brain of
the orchestration system. Its primary responsibilities include:
·
Deciding where to run containers based on resource availability, desired
state, and other policies. Maintaining the overall state of the cluster,
including information about all running containers, services, and nodes.
·
Providing an interface for users and other tools to interact with the
cluster (e.g., to deploy new applications, scale services).
·
Assigning tasks (containers) to worker nodes.
·
Continuously monitoring the health of worker nodes and running
containers and taking action (like restarting failed containers or moving them
to healthy nodes) to maintain the desired state.
Worker nodes, as implied by
the name, perform the actual work in an orchestration. Their primary
responsibilities include:
·
Running the actual containerized application as instructed by the
manager node.
·
Communicate their status and the status of the containers running on
them back to the manager node
·
Provide the CPU, memory, storage, and network resources for the
containers
Now that you understand what
the responsibilities of worker and manager nodes are, let us explore the
working of Docker Swarm. The purpose is to give a basic understanding of how a
cluster operates internally. Comparison of the pros and cons of different
orchestration technologies is beyond the scope of this article. From here on,
we shall refer to the complete system of orchestration as a 'cluster' or
'swarm'.
Docker
Swarm
Docker Swarm is Docker's
native clustering and orchestration solution. It allows you to create and
manage a cluster of Docker engines, treating them as a single virtual Docker
host. In Docker Swarm, the containers are created declaratively. What does that
mean? Instead of specifying how the containers should be created or
manually creating them through the command line using docker run command, we
only need to specify or declare the intended state of the cluster. This
intended state includes:
·
The Docker image to use.
·
The number of replicas (instances) to run.
·
Port mappings.
·
Environment variables.
·
Network configurations.
·
Resource constraints (CPU, memory).
That's it. We only specify what
the cluster should look like, the how is managed by Docker Swarm.
This desired state is known as a service in Docker Swarm. A service can
be scaled up or down, and the Swarm manager ensures the specified number of
replicas are always running. If one instance (replica) stops or crashes, Docker
Swarm automatically spins up another one to match the desired number of
instances, thereby ensuring availability of the application.
An individual running instance
of a service is known as task. When a service is created, the manager
node schedules tasks on worker nodes. If a task fails or a worker node goes
down, the manager automatically reschedules the task on another available node.
We previously discussed about use of containers in a microservices based
architecture. A typical application includes multiple components like web
server, database, caching etc. To orchestrate such an application, you would
need to write a service for each of them and then run them as well. A better
way to organize such related services is using a stack. A stack allows you to
define and deploy multi-service applications as a single, cohesive unit.
Instead of deploying individual services one by one, a stack bundles all
related services, networks, and volumes into a single YAML file. The Docker
Swarm manager reads this file and orchestrates the deployment of all defined
services, creating necessary networks, and scaling services to the specified
number of replicas across the swarm (cluster).
Next let us see how the nodes
communicate within the swarm. Docker provides multiple network types or
drivers. These include:
1.
Bridge Network (Default): When you run a container without specifying a network, it attaches to
the default bridge network. Containers on the
same bridge network can communicate, and they can reach the outside world via
the host's network. Each container gets its own IP address on this private
bridge network.
2.
Host Network: The container shares the host's network stack, meaning it doesn't get
its own IP address and uses the host's network interfaces directly. This
removes network isolation between the container and the host.
3.
None Network: The container is completely isolated from the network. It has no
network interfaces.
4.
Overlay Network: Overlay networks enable communication between containers running on different
Docker hosts. They create a distributed network across multiple machines,
allowing containers to behave as if they are on the same local network,
facilitating service discovery and load balancing across the cluster.
5.
Macvlan Network: Allows you to assign a MAC address to a container, making it appear as
a physical device on your network.
As you might have guessed from the description, Docker Swarm leverages overlay networks to enable seamless communication between containers across different nodes in the swarm. When you create a service, you can attach it to one or more overlay networks, allowing its tasks to communicate with other services on the same network using service names.
Docker
Swarm Flow
The connection between cluster
manager nodes and worker nodes occurs through tokens. The docker swarm init command when run on a manager
node outputs the token. Then, the worker nodes can use this token to join the
cluster or swarm using the docker swarm join command.
Then, the application is defined as a service or a stack of services using the docker service and docker stack command respectively. The manager node receives the service definition and intelligently schedules the tasks (container instances) on available worker nodes, considering resource availability and any specified constraints. The manager continuously monitors the state of the swarm. If a task (container) fails or a node becomes unresponsive, the manager detects the deviation from the desired state and takes corrective action (e.g., rescheduling the task on a healthy node). When a service is exposed, Swarm provides internal DNS-based service discovery and load balancing. Requests to a service name are automatically distributed across its running tasks. Swarm also supports ingress load balancing for external access.
A
Real-Life Use Case
Let us see how the flow discussed above would apply in a real-life
project. Consider a common web application consisting of a front-end web
server, a back-end API, and a database. We can deploy this entire application
using Docker Swarm as a single stack for scalability and high availability. As
we discussed, each individual component would be defined as a service first. In
this scenario, we would have the following services:
·
A service for the frontend
serving the user interface.
·
An API service for the backed
providing RESTful APIs.
·
A database service for storing
application data (like users, products, etc).
·
A caching service that could
use technologies like Redis.
These services can be combined as a stack and defined in a YAML
file. Then, the swarm is initialized on the manager node.
Figure 1: Docker Swarm Init Command
Using the token generated,
the worker nodes (say 3 in this case) join the swarm. Then, using the docker stack deploy along with the stack YAML file as its argument, the services are
deployed. Docker Swarm creates the four services described above based on the
stack file.
Figure 2: Docker Swarm Stack Definition
In the stack file, we also specify the number of replicas or
instances required for each service at all times. Docker Swarm ensures that the
same number of instances are always running across the swarm. If a container
crashes or a node fails, Swarm automatically starts new instances on healthy
nodes.
Figure 3: Docker Swarm Stack Deploy
Similarly, we can also specify the networks to be created, and which
service connects to which network. Docker Swarm creates the overlay networks
allowing the services in the same network to communicate with each other.
Updating a component, like the image used by a service is as easy as
changing the property in the stack YAML file and deploying the stack again.
Docker Swarm handles the replacement process for the containers.
Orchestration
in CI/CD Pipelines
Continuous Integration (CI) and Continuous Delivery/Deployment (CD)
are modern software development practices that automate the building, testing,
and deployment of applications. Integrating Docker Swarm with a CI/CD pipeline,
using tools like GitHub Actions, significantly streamlines the entire
software delivery lifecycle for containerized applications.
Workflows are defined in GitHub actions using YAML files stored in the .github/workflows directory in the application repository. Whenever developers push to the repository, a GitHub Actions job checks out the latest code. It uses actions like docker/build-push-action to build new Docker images for the updated services. For example, if the API code changed, a new Docker image is built. Automated unit tests, integration tests, and even end-to-end tests are run against these containers. If any tests fail, the GitHub Actions workflow stops, and developers are notified immediately via GitHub's UI, email, or integrated messaging services. If all tests pass, the validated Docker images are pushed to a Docker Registry (e.g., Docker Hub, Google Container Registry, Amazon ECR, a private registry). This makes the images accessible to your Docker Swarm nodes. Once images are successfully pushed to the registry, a deployment job in the GitHub Actions workflow is triggered. This job connects to a Docker Swarm manager node. It then executes the docker stack deploy command on the remote manager node, pointing to the service stack YAML file (which should reference the newly tagged images from the registry). Docker Swarm pulls the new images and orchestrates a rolling update of the services, replacing old containers with new ones.
Conclusion
I hope this brief look at the working of Docker Swarm helper you
understand the core concepts of container orchestration. Container orchestration is an
indispensable component of modern cloud-native architectures. By automating the
deployment, scaling, and management of containers, it empowers organizations to
build resilient, scalable, and highly available applications. I encourage you
to explore the other orchestration tools as well. While Docker Swarm offers
significant advantages for many use cases, Kubernetes stands as the industry
standard for more complex, large-scale deployments, providing a broader range
of advanced features and extensibility. Ultimately, understanding these
powerful orchestration technologies is crucial for anyone looking to efficiently
manage and operate containerized workloads in production environments, driving
agility and innovation in modern software development.
Implemented and written by Mr. Karthik Chandrasekhar, IV year student at VIT Chennai.
Comments
Post a Comment