Kubernetes Running on Raspberry Pi

Getting started with Raspberry Pi and Kubernetes

kubernetes plus raspberrypi

I am starting this project off from a post I found from someone who had done this before. Their write up was the latest I have found and it is pretty comprehensive. So full credit here for the original write up.

Shopping List

Lets first get started with hardware. I used Amazon for the majority of what I needed.

Micro Center:

So Micro Center required me to pick up in store. But what was odd, buying one pi was cheaper than buying 4. So I had to go through the line 4 times to buy all that I needed.

Amazon:

Bare minimum here to get started. So due size I went with 4 Raspberries. This gave me flexibility. I could do single master with three workers. Or multi-masters multi-workers setup. The microSDHC’s were on sale, I didn’t need 32gb but the price was the same as the 16gb.

Where I did splurge and I didn’t have to was the memory for each Raspberry. This project could be done with each Raspberry having 1GB of memory. I went over board and did 4GB.

I have an old 25 port switch I could have used for this project. I am aiming to have this portable so I picked up the 5 port Netgear. But the cluster case is probably the critical component that shouldn’t be overlooked. You don’t need to get one with the cooling fans. That just came with the case I bought. But a case makes this easier to set up and transport.

Lastly that isn’t on here is a microSDHC card reader for your computer. I use a Mac and one of my many adapters has this slot. If your computer doesn’t have this, you will need it.

Now that we have our hardware purchased and assembled we can move on to building out each of the Raspberries. I am not going to cover building out the cluster case or assembling and hooking up wires. Not really needed for what we the overall goal is.

Let’s start with the OS. for this I pulled down the latest version of Raspbian Buster Lite. Make sure it is the lite version. Desktop version is way too big and is not needed.

Prepping the microSDHC Cards

Next I prepped up the microSDHC cards. Opened up disk utility (for us Mac users) and erase and format the microSDHC cards make sure the format is MS-DOS (FAT). They should be in this format and have nothing on them if you just purchased them.

Once the microSDHC cards are ready we need to flash the OS on to them. Because I have had to do this a few times I scripted this out.

#!/bin/sh

# unmount disk
diskutil unmountdisk /dev/disk2

# flash sd card
sudo dd if=2019-09-26-raspbian-buster-lite.img of=/dev/disk2 bs=2m

First this script is located here. But if we break down what this is doing the first line diskutil unmountdisk /dev/disk2 unmounts the disk. Mine kept mounting at /dev/disk2 check and see where your disk mounts to by doing diskutil list. The next line is the command that actually flashes the disk. If we break that down we have a sudo we need elevated permissions on the dd command if=2019-09-26-raspbian-buster-lite.img is the location of the img file. I ran this script in the same directory as that img file. The of=/dev/disk2 part of this location of the disk.

NOTE: The drive must be unmounted for this command to work.

The dd command can a while to run and it will not give you any status on where it is at in its processing. You are going to just have to wait it out. When it is done it should look some thing like this below:

$ sudo dd if=2019-09-26-raspbian-buster-lite.img of=/dev/disk2 bs=2m
Password:
1072+0 records in
1072+0 records out
2248146944 bytes transferred in 556.332139 secs (4041016 bytes/sec)

Remound the microSDHC card, I just simply removed it and reinserted it in to the slot reader.

You will need to enable SSH on the Raspberry the following command will do that.

touch /Volumes/boot/ssh

Unmount the drive from your computer. Insert the microSDHC in to one of your raspberry pi and power it up.

Now you can remote in to the raspberry by this command:

ssh pi@raspberrypi.local

With the defaul password of raspberry but if we do this we are going to have to modify the know_host file when you need to do this with the next raspberry. I looked up the ip address by logging in to my local router and used a command like this:

ssh pi@192.168.1.20

Where the ip address will propably be different.

Setting up Static IP Address

Next steps was setting up the hostname and attach the static ip. I pulled this from the post I have been following here. This worked like a charm and I want to give full credit.

You will have to ssh in to your pi and run the following:

nano hostname_and_ip.sh

This is the script you will need to insert.

#!/bin/sh

hostname=$1
ip=$2 # should be of format: 192.168.1.100
dns=$3 # should be of format: 192.168.1.1

# Change the hostname
sudo hostnamectl --transient set-hostname $hostname
sudo hostnamectl --static set-hostname $hostname
sudo hostnamectl --pretty set-hostname $hostname
sudo sed -i s/raspberrypi/$hostname/g /etc/hosts

# Set the static ip

sudo cat <<EOT >> /etc/dhcpcd.conf
interface eth0
static ip_address=$ip/24
static routers=$dns
static domain_name_servers=$dns
EOT

If you are not familiar with the nano command to save the file hit ^X then Y then hit the enter key.

You can then run the following command (note the name is for my master change the name for each of your raspberries):

sh hostname_and_ip.sh pi-master-01 192.168.1.50 192.168.1.1
NOTE:  make sure the static ip you set (second arguement) is not taken.

Next you will have to reboot the raspberry the following command will do that:

sudo reboot
Then you can log back in via this command remember the password is still raspberry

:

ssh pi@pi-master-01.local

Verify the ip address with the ifconfig, it should be set to the static address you set it to previously.

Change Default Password

We should change the default password from raspberry to something different.

passwd

Installing Docker

Next is the fun part installing Docker. The following command will install docker:

curl -sSL get.docker.com | sh && \
sudo usermod pi -aG docker

Since this is a non production environment the default user will be pi and I ran the following command after installing Docker:

sudo usermod -aG docker pi

Next to disable the swap:

sudo dphys-swapfile swapoff && \
sudo dphys-swapfile uninstall && \
sudo update-rc.d dphys-swapfile remove

We need to set up the daemon next. I had some permissions issues with this so I had to address that first:

sudo chmod u=rwx,g=rx,o=r /etc/docker/

Then added the following file:

cat > /etc/docker/daemon.json <<EOF
{
  "exec-opts": ["native.cgroupdriver=systemd"],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m"
  },
  "storage-driver": "overlay2"
}
EOF

Create the following directory:

sudo mkdir -p /etc/systemd/system/docker.service.d

This will install kubeadm:

curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add - && \
echo "deb http://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list && \
sudo apt-get update -q && \
sudo apt-get install -qy kubeadm

Finally reboot the raspberry pi:

sudo reboot

Now do all of these steps for each of your raspberries.

Initilize Master

We need to Initilize the master node the following command will do that:

kubeadm init

When this is complete you will be prompted to have other nodes join it should look something like this:

kubeadm join 192.168.1.50:6443 --token ahtl01.9h... --discovery-token-ca-cert-hash sha256:tleyckd...

Join Each Other Worker

For each of the workers you will need to ssh in to them and run the output command from the previous step:

kubeadm join 192.168.1.50:6443 --token ahtl01.9h... --discovery-token-ca-cert-hash sha256:tleyckd...
NOTE: the command listed above is not the full command copy the output from your master nodes initilization step.

You now have a running kubernetes instance!

kubernetes plus raspberrypi

Not just yet. You will need to create a config file on your master node:

mkdir .kube
nano .kube/config.yaml
kubectl --kubeconfig=~/.kube/config.yaml

This is a good place to pause and I will focus on configuration in my next post.