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.

DockerSwarmMode

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.

DockerSwarmModeRG 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.

NATrules1

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.

NATrules2

Verify that the rule got created successfully as shown below.

NATrules3

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.