Docker swarm — services and high availability

Docker swarm allows you to deploy services distributed to the nodes of the swarm, this allows high availability and high performance of…

Docker swarm — manage services and high availability

Docker swarm allows you to deploy services distributed to the nodes of the swarm, this allows high availability and high performance of the service. To start a single service we can enter something very simple like this

Create a simple service and cause a on the running node$ docker service create nginx
spesyzvgu8pkh1eidhpjcti7d
overall progress: 1 out of 1 tasks
1/1: running   [==================================================>]
verify: Service converged

This command started a new service with the container nginx.

To see details about the services we can run$ docker service list
ID                  NAME                MODE                REPLICAS            IMAGE               PORTS
spesyzvgu8pk        nifty_lehmann       replicated          1/1                 nginx:latest

Note that the replicas are 1 and does not equal the number of my worker nodes which are 3 in my setup, This is because by default docker swarm creates one replica but still enjoys high availability, in case of a failure of the node that runs this container the service will move to another node. Lets first find on which node it runs$ docker service ps nifty_lehmann
ID                  NAME                IMAGE               NODE                                     DESIRED STATE       CURRENT STATE           ERROR               PORTS
md9qwxb69y56        nifty_lehmann.1     nginx:latest        worker_node3  Running             Running 5 minutes ago

To do this we need to pass the name of the container to docker service ps which is nifty_lefmann.1 in mycase and the host of the swarm that executes the container is worker_node3.

Lets simulate a real world scenario, lets stop docker on this worker which equals to a problem in the node.worker_node3$ sudo systemctl stop docker

We can verify the status of the nodes with docker node ls. Using this command we can see that the status of workder_node3 is “Down”.$ docker node ls
ID                            HOSTNAME                                 STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
ncold3meymr0sl9pd9v71dweb *   swarm_manager  Ready               Active              Leader              18.09.5
d913ucvquyjigsl4mnwmcxn4s     worker_node2  Ready               Active                                  18.09.5
ch02clvvojp6qosy20i9k9nim     worker_node3  Down                Active                                  18.09.5

Now lets see the state of the service from the swarm managerswarm_manager$ docker service ps nifty_lehmann
ID                  NAME                  IMAGE               NODE                                     DESIRED STATE       CURRENT STATE            ERROR               PORTS
pqkvpdxtyumm        nifty_lehmann.1       nginx:latest        swarm_manager  Running             Running 26 seconds ago                      
md9qwxb69y56         \_ nifty_lehmann.1   nginx:latest        worker_node3  Shutdown            Running 46 seconds ago

Here we can see that the container is in shutdown state on worker_node3 and in running state in the swarm_manager, this is happening because if not configured the swarm managers are workers as well

Lets bring back to life docker on node worker_node3worker_node3$ sudo systemctl start docker

Verify that the node is backswarm_manager$ docker node ls
ID                            HOSTNAME                                 STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
ncold3meymr0sl9pd9v71dweb *   swarm_manager  Ready               Active              Leader              18.09.5
d913ucvquyjigsl4mnwmcxn4s     worker_node2 Ready               Active                                  18.09.5
ch02clvvojp6qosy20i9k9nim     worker_node3  Ready               Active                                  18.09.5

Lets see what happens to the service$ docker service ps nifty_lehmann
ID                  NAME                  IMAGE               NODE                                     DESIRED STATE       CURRENT STATE            ERROR               PORTS
pqkvpdxtyumm        nifty_lehmann.1       nginx:latest        swarm_manager  Running             Running 14 minutes ago                      
md9qwxb69y56         \_ nifty_lehmann.1   nginx:latest        worker_node3  Shutdown            Shutdown 8 minutes ago

Nothing changes! despite that the node is up the container runs in the swarm_manager node.

Delete a service

To delete a running service enterswarm_manager$ docker service rm nifty_lehmann
nifty_lehmann

Its very simple! it should return the name of the service

Run a service with more than one replicas

Lets do something more complicated, lets define the number of replicas of the service along with some optionsswarm_manager$ docker service create --name nginx --replicas 3 -p 8080:80 nginx
x8cgelqviid3e5l4icybsclg2
overall progress: 3 out of 3 tasks
1/3: running   [==================================================>]
2/3: running   [==================================================>]
3/3: running   [==================================================>]
verify: Service converged

With this command we did the following

  • The name of the service is nginx
  • The number of replicas are 3
  • We exposure port 80 of each container to port 8080 of each node

Running docker service ps nginx we can see the following$ docker service ps nginx
ID                  NAME                IMAGE               NODE                                     DESIRED STATE       CURRENT STATE           ERROR               PORTS
ek8llokh8ia8        nginx.1             nginx:latest        swarm_manager  Running             Running 7 minutes ago                      
st654bmojc4u        nginx.2             nginx:latest        worker_node2 Running             Running 7 minutes ago                      
copaz24xs2zf        nginx.3             nginx:latest        worker_node3  Running             Running 7 minutes ago

Each node has a running container for service nginx

How Load balancing works

Lets do something very interesting, run this on any host of your swarm that is a worker nodefor i in {1..100}; do curl -l localhost:8080 &> /dev/null; done

Then run the following in a swarm nodedocker service logs nginx | grep -i http | cut -d " " -f1 | sort -n | uniq -c

No matter how many times you will run it and no matter on which host you should see that the number of requests should be divided equal to each worker node that runs this container184 nginx.1.ek8llokh8ia8@swarm_manager
184 nginx.2.st654bmojc4u@worker_node2
182 nginx.3.copaz24xs2zf@worker_node3

And this is happening because docker swarm internally load balance the requests in a round-robin fashion despite on which node we perform the request and this is great for simple solutions that do not require a very specialized load balancing scheme.

Changing the number of replicas

We can on the fly increase or decrease the number of running replicas for a service, to do this we can enter in a swarm manager$ docker service update --replicas 2 nginx
nginx
overall progress: 2 out of 2 tasks
1/2: running   [==================================================>]
2/2: running   [==================================================>]
verify: Service converged

This will reduce the number of nginx replicas from 3 to 2, we can verify this by running$ docker service ps nginx
ID                  NAME                IMAGE               NODE                                     DESIRED STATE       CURRENT STATE            ERROR               PORTS
ek8llokh8ia8        nginx.1             nginx:latest        worker_node2  Running             Running 30 minutes ago                      
st654bmojc4u        nginx.2             nginx:latest        swarm_manager  Running             Running 30 minutes ago

To increase the number of replicas$ docker service update --replicas 6 nginx
nginx
overall progress: 6 out of 6 tasks
1/6: running   [==================================================>]
2/6: running   [==================================================>]
3/6: running   [==================================================>]
4/6: running   [==================================================>]
5/6: running   [==================================================>]
6/6: running   [==================================================>]
verify: Service converged
$ docker service ps nginx
ID                  NAME                IMAGE               NODE                                     DESIRED STATE       CURRENT STATE            ERROR               PORTS
ek8llokh8ia8        nginx.1             nginx:latest        worker_node2   Running             Running 32 minutes ago                      
st654bmojc4u        nginx.2             nginx:latest        swarm_manager  Running             Running 32 minutes ago                      
xpw6gl4sos46        nginx.3             nginx:latest        worker_node3   Running             Running 15 seconds ago                      
9m286xjd6mnn        nginx.4             nginx:latest        swarm_manager  Running             Running 15 seconds ago                      
zkkaxktfozz6        nginx.5             nginx:latest        worker_node2   Running             Running 15 seconds ago                      
qxvqa3svz6js        nginx.6             nginx:latest        worker_node3  Running             Running 14 seconds ago

Note that the containers have been equally balanced to each running node

How to disallow a node running containers

A good practice is not to use swarm managers to run heavy load containers because this can disrupt the consistency of the swarm managers statuses which can cause problems to the quorum of the swarm, to avoid this you can configure a node not to run containers$ docker node update --availability drain swarm_manager
swarm_manager

And to verify that the swarm_manager does not execute any containers we run docker service ps nginx$ docker service ps nginx
ID                  NAME                IMAGE               NODE                                     DESIRED STATE       CURRENT STATE             ERROR               PORTS
ek8llokh8ia8        nginx.1             nginx:latest        worker_node2  Running             Running 38 minutes ago                        
pnvff40fy745        nginx.2             nginx:latest        worker_node3  Running             Running 56 seconds ago                        
st654bmojc4u         \_ nginx.2         nginx:latest        swarm_manager   Shutdown            Shutdown 57 seconds ago                      
xpw6gl4sos46        nginx.3             nginx:latest        worker_node3  Running             Running 6 minutes ago                        
wu3u0lw42gq9        nginx.4             nginx:latest        worker_node2  Running             Running 57 seconds ago                        
9m286xjd6mnn         \_ nginx.4         nginx:latest        swarm_manager   Shutdown            Shutdown 57 seconds ago                      
zkkaxktfozz6        nginx.5             nginx:latest        worker_node2  Running             Running 6 minutes ago                        
qxvqa3svz6js        nginx.6             nginx:latest        worker_node3  Running             Running 6 minutes ago

We can see that swarm_manager does not execute any containers but the number of replicas are still 6 and distributed equal to the 2 workers.

How to automatically use all nodes of a swarm

In case you want to use all nodes of the swarm there is not need to define the number of replicas, you can instead use the global option

docker service create --name nginx --mode global nginx

This command will create as many replicas as the number of nodes that can run containers in the swarm.

I hope you found my article interesting! :)

Join Medium with my referral link - Konstantinos Patronas
As a Medium member, a portion of your membership fee goes to writers you read, and you get full access to every story…