The Raspberry Pi is a cheap and fun piece of kit for geeks. My QNAP NAS is running a few too many applications on Docker, and I have a few Raspberry Pi’s laying around, so I thought it’d be a fun weekend project to turn them into a Docker Swarm.
Before getting into the automation side of things, let’s set up a prototype of the swarm itself. I’ll be setting up;
- A Raspberry Pi Rev 1 Model B,
- A Raspberry Pi Rev 3 Model B,
The Raspberry Pi’s will be running Raspberry Pi OS Buster
(2020-08-20). While the Rev 3 is 64 bit, I’ll be using the
both. All the machines are on the same network.
The Docker Swarm has two types of nodes; managers and workers. The managers keep the state of the swarm in a distributed store by using the Raft Consensus Algorithm. For best results, the amount of managers should be odd. I only have three machines to work with, so I’ll stick with a single manager for now. This cluster doesn’t need to be highly available. The Rev 3 is the most powerful RPi, so I’ll be electing it as the manager.
[email protected]:~$ sudo docker swarm init Swarm initialized: current node (eseiud89bm9gl3eail1tnnznx) is now a manager. To add a worker to this swarm, run the following command: docker swarm join --token SWMTKN-1-6814zqm6wpp4q43fe9a9m2ezxcsecjnlmvcayvm5ydzpwkegdh-4n5qaw4ujge9xcmi2vcr0mcrn 192.168.0.2:2377 To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
[email protected]:~$ sudo docker node ls ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION eseiud89bm9gl3eail1tnnznx * manager Ready Active Leader 19.03.13
Docker is nice enough to provide instructions for the workers. Let’s do that.
[email protected]:~$ sudo docker swarm join --token SWMTKN-1-6814zqm6wpp4q43fe9a9m2ezxcsecjnlmvcayvm5ydzpwkegdh-4n5qaw4ujge9xcmi2vcr0mcrn 192.168.0.2:2377 This node joined a swarm as a worker.
All management commands need to be run on the manager, so let’s check the list of nodes;
[email protected]:~$ sudo docker node ls ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION eseiud89bm9gl3eail1tnnznx * manager Ready Active Leader 19.03.13 bcm9cnme7ewvx224klfun1qfn worker Ready Active 19.03.13
Now let’s run an application on the swarm. For demonstration purposes
let’s just use some random image, like
[email protected]:~$ sudo docker pull nginxdemos/hello Using default tag: latest latest: Pulling from nginxdemos/hello 550fe1bea624: Pull complete d421ba34525b: Pull complete fdcbcb327323: Pull complete bfbcec2fc4d5: Pull complete 0497d4d5654f: Pull complete f9518aaa159c: Pull complete a70e975849d8: Pull complete Digest: sha256:f5a0b2a5fe9af497c4a7c186ef6412bb91ff19d39d6ac24a4997eaed2b0bb334 Status: Downloaded newer image for nginxdemos/hello:latest docker.io/nginxdemos/hello:latest
[email protected]:~$ sudo docker service create -p 8080:80 nginxdemos/hello:0.2 image nginxdemos/hello:0.2 could not be accessed on a registry to record its digest. Each node will access nginxdemos/hello:0.2 independently, possibly leading to different nodes running different versions of the image. 9ldqvus6y2zzp64pj187mmb52 overall progress: 1 out of 1 tasks 1/1: running [==================================================>] verify: Service converged
[email protected]:~$ sudo docker service ls ID NAME MODE REPLICAS IMAGE PORTS 9ldqvus6y2zz jolly_rhodes replicated 1/1 nginxdemos/hello:0.2 *:8080->80/tcp
[email protected]:~$ sudo docker service ps jolly_rhodes ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS hfebnhjrg0v7 jolly_rhodes.1 nginxdemos/hello:0.2 manager Running Running 7 minutes ago
Fantastic. We have a service running in the swarm. Let’s see if it works;
[email protected]:~$ links -dump http://localhost:8080 NGINX Logo Server address: 10.0.0.35:80 Server name: 2c704cbf842b Date: 12/Nov/2020:19:53:43 +0000 URI: / [ ] Auto Refresh Request ID: e620aa94f6e13add9a69cd03340b1551 © NGINX, Inc. 2018
Now you can do all the typical things with Docker Swarm; adding replicas, deploying stacks and adding more nodes. In the next post we’ll go through how this can be automated using Ansible to easily scale to more nodes.