Swarm made easy
One of the biggest changes presented during DockerCon 2016 (gosh… I wish I was there) is the swarm mode of Engine 1.12. What does that mean ? That you can create a swarm cluster out of the box if you have the Docker daemon 1.12 running.
A command as simple as:
$ docker swarm init
is enough to create a Swarm. A Swarm with a single management node but still a Swarm.
$ docker node ls ID HOSTNAME MEMBERSHIP STATUS AVAILABILITY MANAGER STATUS 7sytb3zk0yswdfky6mbh7nzk2 * moby Accepted Ready Active Leader
Let’s go multi nodes
A Swarm with a single node is of limited use, let’s create one with 2 manager nodes and 2 worker nodes.
We will first start by creating 4 Docker hosts. Docker Machine is a great tool for this purpose, so let’s use it.
$ docker-machine create --driver virtualbox manager1 $ docker-machine create --driver virtualbox manager2 $ docker-machine create --driver virtualbox worker1 $ docker-machine create --driver virtualbox worker2
If you do not have any other hosts created with Machine, you should have an output pretty similar to the following one when listing all the machines.
$ docker-machine ls NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS manager1 - virtualbox Running tcp://192.168.99.100:2376 v1.12.0-rc3 manager2 - virtualbox Running tcp://192.168.99.101:2376 v1.12.0-rc3 worker1 - virtualbox Running tcp://192.168.99.102:2376 v1.12.0-rc3 worker2 - virtualbox Running tcp://192.168.99.103:2376 v1.12.0-rc3
Init the swarm
We saw earlier the simplest command possible to create a Swarm with 1.12 (reminder:
docker swarm init), but we’ll use several additional options here to enable the hosts of the cluster to communicate and to join the cluster without approval)
$ MANAGER1_IP=$(docker-machine ip manager1) $ docker-machine ssh manager1 docker swarm init --auto-accept manager --auto-accept worker --listen-addr $MANAGER1_IP:2377 No --secret provided. Generated random secret: aedac6jbd08g804jkjgyf6mtu Swarm initialized: current node (dj0s04kxqo6bacuvexend0s8v) is now a manager. To add a worker to this swarm, run the following command: docker swarm join --secret aedac6jbd08g804jkjgyf6mtu \ --ca-hash sha256:2da129878f18fea3216348b54eddb81cd1642bc3e5fbc7ab35259bb0f852a975 \ 192.168.99.100:2377
--listen-addr is the address the node will be accessible to the other nodes of the Swarm
note: Docker 1.12 rc4 introduced the creation of secret + ca hash when swarm is initialized. Those parameters will need to be provided when additional nodes (manager or worker) join the cluster, we’ll see that shortly.
Let’s first save the secret and ca hash in env variables, it will be easier to use them later on.
$ SECRET="aedac6jbd08g804jkjgyf6mtu" $ CA_HASH="sha256:2da129878f18fea3216348b54eddb81cd1642bc3e5fbc7ab35259bb0f852a975"
Add the second manager
Several options needs to be provided to the docker swarm command:
* join: to indicate a new node will be added to the Swarm
--manager: to indicates the nature of the node (manager vs worker)
--listen-addr: address the newly added node will be accessible to the other nodes of the Swarm
* the last parameter is the address of the first manager (the node this command will is sent to)
$ MANAGER2_IP=$(docker-machine ip manager2) $ docker-machine ssh manager2 docker swarm join --manager --secret $SECRET --ca-hash $CA_HASH --listen-addr $MANAGER2_IP:2377 $MANAGER1_IP:2377 This node joined a Swarm as a manager.
Note: as the
--auto-accept manager option was provided during the Swarm initialization, the second manager is automatically accepted. Without this option, it needs to be accepted by the first manager.
Add the workers
Worker nodes are added in the cluster in pretty much the same way:
$ WORKER1_IP=$(docker-machine ip worker1) $ docker-machine ssh worker1 docker swarm join --secret $SECRET --ca-hash $CA_HASH --listen-addr $WORKER1_IP:2377 $MANAGER1_IP:2377 This node joined a Swarm as a worker. $ WORKER2_IP=$(docker-machine ip worker2) $ docker-machine ssh worker2 docker swarm join --secret $SECRET --ca-hash $CA_HASH --listen-addr $WORKER2_IP:2377 $MANAGER1_IP:2377 This node joined a Swarm as a worker.
Note: as the
--auto-accept worker option was provided during the Swarm initialization, the worker are automatically accepted. Without this option, it needs to be accepted by a manager.
What does our Swarm look like
Let’s check it
$ docker-machine ssh manager1 docker node ls ID HOSTNAME MEMBERSHIP STATUS AVAILABILITY MANAGER STATUS 109a5ufy8e3ey17unqa16wbj7 manager2 Accepted Ready Active Reachable 4chbn8uphm1tidr93s64zknbq * manager1 Accepted Ready Active Leader 8nw7g1q0ehwq1jrvid1axtg5n worker2 Accepted Ready Active 8rrdjg4uf9jcj0ma2uy8rkw5v worker1 Accepted Ready Active
Every node now belongs to the Swarm and is in the Ready status. Manager1 is the leader. Everything looks good.
What makes it so special ?
This Swarm is TLS secured, with automated certificates updates out of the box.
Also, there is no need to use a KV Store anymore (Consul, Zookeeper, etcd), everything is handled for us.
Let’s use it now
What is the purposes of a Swarm without having anything running on it… ? Of course, we’ll deploy some services on our Swarm, but this is in a next article.
Copy and paste
Below is small shell script that creates the Docker hosts, and deploys a Swarm. Of course, feel free to change the number of manager / worker nodes.
Note: the setup with 2 manager node and 2 worker nodes was used for the example. For a production cluster, we would probably go with a 3 manager nodes and 5 worker nodes (thanks Stefan for pointing this out).
# Define the number of managers/workers MANAGER=3 WORKER=5 # Create the Docker hosts for i in $(seq 1 $MANAGER); do docker-machine create --driver virtualbox manager$i; done for i in $(seq 1 $WORKER); do docker-machine create --driver virtualbox worker$i; done # Init the swarm docker-machine ssh manager1 docker swarm init --auto-accept manager --auto-accept worker --listen-addr $(docker-machine ip manager1):2377 # Add additional manager(s) for i in $(seq 2 $MANAGER); do docker-machine ssh manager$i docker swarm join --manager --listen-addr $(docker-machine ip manager$i):2377 $(docker-machine ip manager1):2377; done # Add workers for i in $(seq 1 $WORKER); do docker-machine ssh worker$i docker swarm join --listen-addr $(docker-machine ip worker$i):2377 $(docker-machine ip manager1):2377; done