Docker Swarm on Azure
Introduction
As an application programmer dabbling in infrastructure, I am always looking at abstracting away the complexities of the infrastructure which allows me to focus on my application.
Consequently, I am a big fan of Platform as a Service (PaaS) but I also realize some of it's limitations of it 9;s adoption in the enterprise, primarily around lack of control.
Docker provides a via media. However, its earliest incarnation(s) did not provide the following right off the box tha t most PaaSes provide.
- Scaling
- Self-healing
- Rolling upgrades
- Blue/Green and other deployments
- etc.
Docker Swarm addresses many of these application related issues and tends to take an application-centric approach to infrastructure. So, let's dive right in and look at how to take advantage of some of these features right off the bo x.
Docker Swarm cluster on Azure
In an earlier blog, my colleague introduced Kubernetes using Azure Container Services.
Although Azure Container Services features Docker Swarm, we will be using Docker Swarm in what is referred to as Swarm mode which is not supported in Azure Container Services (yet).
Creating a Docker Swarm cluster in Swarm Mode
Generate an ssh key in preparation. More details are at https://github.com/Azure/acs-engine/blob/master/docs/ssh.md#key-management-and-agent-forwarding-with-windows-pageant. You will use the public key of the key generated as an input to the template below and use the private key to ssh to the VM that will be created.
You can create the cluster by clicking on the Deploy to Azure
button using the https://github.com/ragsns/azure-quickstart-templates/ tree/master/101-acsengine-swarmmode.
The template will generate a swarm mode cluster with a swarm master and agents as shown in the figure below.
Now might be the time to get a cup of coffee or whatever beverage of your liking.
From the Azure portal you should be able to see all the resources created as illustrated below.
Now ssh
to the master node, via the IP address of the master VM and run the following command.
docker node ls
Which should yield and output that looks something like below.
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
lzr9t6hj4wxk795rbo0zfg1ta swarmm-agent-13957614000002 Ready Active
tj1yvivboh6o17ark5wh87ozr swarmm-agent-13957614000000 Ready Active
um7e625teqe4w1z1qucdr73z9 * swarmm-master-13957614-0 Ready Pause Leader
It shows the master and two agents that are part of the swarm. More details of containers in swarm mode is available at https://docs.microsoft.com/en-us/virtualization/windowscontainers/manage-containers/swarm-mode.
We are almost ready to create services on the cluster.
Open up port 80
Before we create a service, there is a minor detail of opening up port 80 on the master which we'll use subsequently.
Start from the Resource Group, find the master load balancer and click on Inbound NAT rules
as shown below.
We will create an inbound rule for port 80 similar to port 22 (ssh
) that is created when the template wa s created as shown below.
Verify that the rule got created successfully as shown below.
Now we're ready to spin up services that can be accessed externally via the load balancer.
Exploring Services
Any Dockerized application can run on a Docker Swarm, but we'll try some simple apps from the Docker public regis try such as ragsns/docker-pets5000
which is a Python/Flask application derived from https://github.com/mark-church/docker-pets and ragsns/spring-boot
, which is a Spring Boot application.
Let's create the service with the following command
docker service create --replicas 1 --name docker-pets --detach=false --publish 80:5000 ragsns/docker-pets5000
Which should show the service starting and eventually to a running state as shown below. It should forward port 5000 from the app to port 80 of the container.
ymwepi7e2njzfip7iirsrx9zp
overall progress: 1 out of 1 tasks
1/1: running
verify: Waiting 1 seconds to verify that tasks are stable...
Run the following command
docker service ps docker-pets
The output shows that the service is running on one of the swarm agents.
ID NAME IMAGE NODE
DESIRED STATE CURRENT STATE ERROR PORTS
v1bjt1fkm44l docker-pets.1 ragsns/docker-pets5000:latest swarmm-agent-13957614000000 Running
Running about a minute ago
If you ssh to the swarm agent and run the following command
docker ps
You should notice that the ID of the service is derived from the name of the container running the docker image on th e respective agent.
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c279df299fcc ragsns/docker-pets5000:latest "/bin/sh -c 'pytho..." 7 minutes ago Up 7 minu
tes (healthy) 5000/tcp docker-pets.1.v1bjt1fkm44l5fjmw80rgy63y
Now, let's verify that the app is running, port is open and so on. Point your browser to the IP address of the master and you should be able to see the app running. It should also list the same container ID.
Let's stop this application and start another application as below.
docker service rm docker-pets
The following command creates a service with port forwarding from 8080 of the container to port 80 of the host VM.
docker service create --replicas 1 --name spring-boot --detach=false --publish 80:8080 ragsns/spring-boot
Let's verify the application is running via the following curl
command.
curl <ip-of-master>
This should yield the single line output as below.
Hello World!
Now, we'll go ahead and scale the application.
Scaling
Let's scale the app to three instances with the following command.
docker service update --replicas=3 spring-boot --detach=false
Which should yield an output that the app is being scaled. Eventually, they will all be running.
spring-boot
overall progress: 1 out of 3 tasks
1/3: running
2/3: preparing
3/3: preparing
Running the ps
command as we did earlier
docker service ps spring-boot
should show the three running instances as below.
ID NAME IMAGE NODE
DESIRED STATE CURRENT STATE ERROR PORTS
g5o7ko1fkxqa spring-boot.1 ragsns/spring-boot:latest swarmm-agent-13957614000000 Running Ru
nning 2 minutes ago
ve355jvyynym spring-boot.2 ragsns/spring-boot:latest swarmm-agent-13957614000002 Running Ru
nning about a minute ago
oij482mwmbh5 spring-boot.3 ragsns/spring-boot:latest swarmm-agent-13957614000002 Running Ru
nning about a minute ago
If you run the following command a few times.
curl -s 13.82.174.216/env | grep HOSTNAME
The output from four runs is shown below.
HOSTNAME = 154ef66b1746
HOSTNAME = b8fe94c04fed
HOSTNAME = 7f15068c4200
HOSTNAME = 154ef66b1746
Notice that the Load balancer is cycling the load to the different containers that are part of the swarm running the application instance.
Next we move to application self-healing.
Application Self-Healing
To illustrate App self-healing, we'll kill off an instance. There are multiple ways of doing this but here's the easiest way.
curl 13.82.174.216/exit
and that should yield an output something like below
curl: (52) Empty reply from server
echoing the death of the particular instance.
However, the instance automatically restarts and this is the self-healing part of the platform.
To check this, we will run the previous command four times as we did before.
The output will list different IDs since the application instance got restarted cycling between the number of replicas we specified.
HOSTNAME = 154ef66b1746
HOSTNAME = b2c824c7de22
HOSTNAME = 9f5c40b71187
HOSTNAME = b2c824c7de22
Run the following command
docker service ps spring-boot
The output below show some instances that shutdown and others that got restarted automagically. There is only one original instance still running. The output shows some instances that were restarted.
ID NAME IMAGE NODE
DESIRED STATE CURRENT STATE ERROR PORTS
4ixl8mnqx9j8 spring-boot.1 ragsns/spring-boot:latest swarmm-agent-13957614000000 Running Ru
nning 24 minutes ago
g5o7ko1fkxqa \_ spring-boot.1 ragsns/spring-boot:latest swarmm-agent-13957614000000 Shutdown Co
mplete 24 minutes ago
ve355jvyynym spring-boot.2 ragsns/spring-boot:latest swarmm-agent-13957614000002 Running Ru
nning about an hour ago
aiazav7gw6tj spring-boot.3 ragsns/spring-boot:latest swarmm-agent-13957614000002 Running Ru
nning 25 minutes ago
oij482mwmbh5 \_ spring-boot.3 ragsns/spring-boot:latest swarmm-agent-13957614000002 Shutdown Co
mplete 25 minutes ago
Conclusions and Summary
We created a Docker Swarm container in swarm mode on Azure using templates and looked at some of the Application deployment features it provides ala Platform as a Service. The concept of a service in Docker Swarm allows the infrastructure to be treated from an application centric viewpoint by permitting scaling, self-healing and other related app deployment features.
The goal of this blog is not to exhaustively go through the myriad features of Docker Swarm. However, using Azure as a platform provides an easy way to deploy apps leveraging newer and industry standard initiatives with more coming in the future.