At last there is a 4G Pi. The 2017 Pi farm melted in the end. After about 8 months of always on the SD cards developed faults. This is almost certainly due to heat in the cases, and stacking them…

But, now I’m all GO, grpc micro services and a Kubernetes old hand I have a new plan! The Pi4, ditch Kafka and Kubernetes as these are resource hogs. Stay in Docker swarm, and, well, that is it.

Before we start

cat /proc/cpuinfo | grep model
cat /etc/os-release

It’s useful!


Refering to my 2017 notes shows things are very similar now:

Using Etcher again. Sadly the old Belkin SD card mounter turned out to have a lose connection, so I spent a fun 30 minutes holding it all in place. I also resurrected my old crippled Pi2 from 2017. The other 4 still worked.

Docker on Pi ARM.

There are so many guides online already, but I tried to get it working on Raspbian 10 before the docker install script had been about 3 hours re-learning debian, apt-get and docker huh images, as below…

Here is a kubernetes guide for docker..

sudo apt-get remove docker docker-engine containerd runc
# Make yourself a work area, change to it
cd /opt/apps/env/setup_docker/
curl -sSL | sh

As of now, there is no support in the script for Raspberian 10. So on those PI’s do the manual docker-ce install from:

lsb_release -cs
# says buster on raspbian 10, but stretch on previous versions. you can also see
# this in the debian package manager
sudo more /etc/apt/sources.list

# On one of the older pi's
docker -v
Docker version 18.09.0, build 4d60db4

On the older pi that worked, the script did:

sudo -E sh -c echo "deb [arch=armhf] stretch stable" > /etc/apt/sources.list.d/docker.list

But on the newer one that failed with ```E: The repository ‘ 10 Release’ does not have a Release file.

This is fixed by changing the 10 below to the actual image that is staged on the download site - ie browse to and you can see there
is only jessie, or stretch.  So rather than:

sudo -E sh -c echo “deb [arch=armhf] 10 stable” > /etc/apt/sources.list.d/docker.list

You need to use the stretch image, so you could do below...but actually see later, adding 10 to the install script is better.

sudo su vi /etc/apt/sources.list.d/docker.list

Remove the 10 and use stretch instead

deb [arch=armhf] stretch stable

It's important to remove the raspian 10 line from that file, it simply doesn't exist as an image.

A better idea is to edit the install script to copy with Raspbian 10:

curl -sSL > vi #Edit the line below with the 9) in to be 9|10) case “$dist_version” in 9) dist_version=”stretch”

i.e. it should look like

case “$dist_version” in 9|10) dist_version=”stretch”

And then run it:

. ./

and finally, as it suggests

sudo usermod -aG docker pi

Useful commands along the way:
```more /etc/os-release
journalctl -u docker.service

Now kubernetes

Disable swap and configure the pi’s

All taken from, recorded my commands below. Wierdly xenial is an ubuntu distro, which stretch (Raspian 9) and buster (v10) are debian, which you would expect for raspian. Instructions suggest use xenial, and indeed if you look it seems only xenial is a full build.

sudo swapon --summary
free -m
sudo dphys-swapfile swapoff
sudo dphys-swapfile uninstall
sudo update-rc.d dphys-swapfile remove
free -m
sudo vi /boot/cmdline.txt
# add this to the end of the line
cgroup_enable=cpuset cgroup_memory=1 cgroup_enable=memory

sudo reboot
sudo vi /etc/apt/sources.list.d/kubernetes.list
#add this line
deb kubernetes-xenial main

sudo curl -s | sudo apt-key add -
sudo apt-get update

Now common kubeadm setup

sudo apt-get install -qy kubeadm

Master node only

Alternatives to weave are listed here.

sudo kubeadm config images pull -v3
sudo kubeadm init --token-ttl=0
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
# Using weave as the pod network.
kubectl apply -f "$(kubectl version | base64 | tr -d '\n')"
sudo sysctl net.bridge.bridge-nf-call-iptables=1


on all the other nodes

 sudo sysctl net.bridge.bridge-nf-call-iptables=1
 kubeadm join ....etc as given by the master

And lo, the cluster is alive.

Handy runall command

Running commands on 6 pi’s can be a chore, so this can be handy,

hosts=( "pi1.local" "pi2.local" "pi3.local" "pi4.local" "pi5.local" )

exec_cmd() {
        echo "[$1] $2"
        echo ""
        ssh $1 $2
        echo ""

for host in "${hosts[@]}"
        exec_cmd $host "$@"