Setting up a Swarm cluster
We'll continue using Docker Machine since it provides a very convenient way to simulate a cluster on a laptop. Three servers should be enough to demonstrate some of the key features of a Swarm cluster:
for i in 1 2 3; do
docker-machine create -d virtualbox node-$i
done
At this moment, we have three nodes. Please note that those servers are not running anything but Docker Engine.
We can see the status of the nodes by executing the following ls command:
docker-machine ls
The output is as follows (ERROR column removed for brievity):
NAME ACTIVE DRIVER STATE URL SWARM DOCKER
node-1 - virtualbox Running tcp://192.168.99.100:2376 v1.12.1
node-2 - virtualbox Running tcp://192.168.99.101:2376 v1.12.1
node-3 - virtualbox Running tcp://192.168.99.102:2376 v1.12.1
With the machines up and running we can proceed and set up the Swarm cluster.
The cluster setup consists of two types of commands. We need to start by initializing the first node which will be our manager. Refer to the following illustration:
eval $(docker-machine env node-1)
docker swarm init \
--advertise-addr $(docker-machine ip node-1)
The first command set environment variables so that the local Docker Engine is pointing to the node-1. The second initialized Swarm on that machine.
We specified only one argument with the swarm init command. The --advertise-addr is the address that this node will expose to other nodes for internal communication.
The output of the swarm init command is as follows:
Swarm initialized: current node (1o5k7hvcply6g2excjiqqf4ed) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join \
--token SWMTKN-1-3czblm3rypyvrz6wyijsuwtmk1ozd7giqip0m \
6k0b3hllycgmv-3851i2gays638e7unmp2ng3az \
192.168.99.100:2377
To add a manager to this swarm, run the following command:
docker swarm join \
--token SWMTKN-1-3czblm3rypyvrz6wyijsuwtmk1ozd7giqi \
p0m6k0b3hllycgmv-6oukeshmw7a295vudzmo9mv6i \
192.168.99.100:2377
We can see that the node is now a manager and we've got the commands we can use to join other nodes to the cluster. As a way to increase security, a new node can be added to the cluster only if it contains the token generated when Swarm was initialized. The token was printed as a result of the docker swarm init command. You can copy and paste the code from the output or use the join-token command. We'll use the latter.
Right now, our Swarm cluster consists of only one VM. We'll add the other two nodes to the cluster. But, before we do that, let us discuss the difference between a manager and a worker.
A Swarm manager continuously monitors the cluster state and reconciles any differences between the actual state and your expressed desired state. For example, if you set up a service to run ten replicas of a container, and a worker machine hosting two of those replicas crashes, the manager will create two new replicas to replace the ones that failed. Swarm manager assigns new replicas to workers that are running and available. A manager has all the capabilities of a worker.
We can get a token required for adding additional nodes to the cluster by executing the swarm join-token command.
The command to obtain a token for adding a manager is as follows:
docker swarm join-token -q manager
Similarly, to get a token for adding a worker, we would run the command that follows:
docker swarm join-token -q worker
In both cases, we'd get a long hashed string.
The output of the worker token is as follows:
SWMTKN-1-3czblm3rypyvrz6wyijsuwtmk1ozd7giqip0m6k0b3hll \ ycgmv-3851i2gays638\
e7unmp2ng3az
Please note that this token was generated on my machine and, in your case, it will be different.
Let's put the token into an environment variable and add the other two nodes as workers:
TOKEN=$(docker swarm join-token -q worker)
Now that have the token inside a variable, we can issue the command that follows:
for i in 2 3; do
eval $(docker-machine env node-$i)
docker swarm join \
--token $TOKEN \
--advertise-addr $(docker-machine ip node-$i) \
$(docker-machine ip node-1):2377
done
The command we just ran iterates over nodes two and three and executes the swarm join command. We set the token, the advertise address, and the address of our manager. As a result, the two machines joined the cluster as workers. We can confirm that by sending the node ls command to the manager node node-1:
eval $(docker-machine env node-1)
docker node ls
The output of the node ls command is as follows:
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
3vlq7dsa8g2sqkp6vl911nha8 node-3 Ready Active
6cbtgzk19rne5mzwkwugiolox node-2 Ready Active
b644vkvs6007rpjre2bfb8cro * node-1 Ready Active Leader
The asterisk tells us which node we are currently using. The MANAGER STATUS indicates that the node-1 is the leader:
In a production environment, we would probably set more than one node to be a manager and, thus, avoid deployment downtime if one of them fails. For the purpose of this demo, having one manager should suffice.