CLI + yaml for the configuration of an at-home Kubernetes fleet with one or more Raspberry Pis.
Read the Blog Post for examples, screenshots, etc. Please open a Github issue for any problems.
Some configuration requried (see Getting Started). Assume you've aliased ln -sf ./tiny-cluster.py /usr/local/bin/tc and your contexts directiry lives within the pwd.
Create Kubernetes cluster, installing kubeadm with weave/flannel and NFS support enabled per yaml config:
tc master create
Create another node, "rpi", installing docker/kubeadm and using fixed IP defined in the yaml:
tc rpi create
Join the cluster:
tc rpi join
Add some labels to the node per the yaml config:
tc rpi label
Set up the node as a "Kiosk", showing a permanent Chromium browser pointed at a web URL:
tc rpi configure
SSH into one of the nodes:
tc rpi ssh
Reboot a node:
tc rpi reboot
Create a second cluster:
tc -c second-cluster master create
- Use
yamlto provide configuration as code. - Set up a brand new Raspberry Pi with a single command.
- Provide "Kiosk Mode" (turn a Raspberry Pi into a dedicated web browser).
- Keep the entire cluster of devices up-to-date using stateless technologies like Docker and Kubernetes.
- Avoid of one-off scripts and backups.
- Easy to integrate with Home Assistant
- Enable password-less SSH access
- Perform system updates (
apt) - Assign a static IP address
- Install Chromium Kiosk scripts (if Kiosk mode enabled)
- Install kubeadm, network add-ons, and NFS
- Apply labels to nodes
- Provide a simple interface for other advanced management features.
This repo is a tool I cobbled together over the course of a good year or so. I am placing it here in the hopes that it will be useful to others. But much of the work comes from sources like these:
- Alex Ellis for his work getting K8s on Raspbian.
- How to Set Up a Raspberry Pi Cluster
- Kubeadm on Raspberry Pi
- Baremetal K8s with Kubeadm
- K8s on Pi
- Kiosk mode for Home Assistant
- Argbash
- What are the Raspberry Pi OUIs?
- Disabling Swap in Linux
- The
controllingcomputer is, presumably, the computer you're currently using. It's what will run the commands. - The
masterandnodesare Kubernetes terms. Your cluster will first need to have a master set up, and then the nodes can join the cluster.
- Your current "controlling" (this) computer must have Python3 installed.
- One or more Raspberry Pis with
sshenabled, connected to the same network as the controlling computer.
Note: any time you use tiny-cluster.py below, you can append -l DEBUG to change the log mode to be more verbose. You can also run ./tiny-cluster.py --help for assistance with any command.
- Clone this repository:
git clone [email protected]:zaneclaes/tiny-cluster.git - Install the required python packages:
pip3 install pyyaml deepmerge argparse - Run
cd tiny-clusterand./tiny-cluster.py setupto scan the local network and follow the prompts.
If a Raspberry Pi is connected to the network, it should be discovered and walk you through the setup. Note that the auto-detect feature requires the arp tool. The auto-detect feature is generally less well-tested than the following manual setup steps, and should presently be considered "beta."
See the defaults.yaml file in this repository for a sense of all the options available. Tiny Cluster will look in contexts/home.yaml for your configuration (do not modify defaults.yaml). If you want to run Tiny Cluster in multiple locations, see "Advanced Configurations" below.
The following is an sample contexts/home.yaml file which is used in the example setup steps below. Key concepts to understand:
- It assumes you know the IP addresses of the Raspberry Pis you wish to configure (192.168.0.1, etc.). Tiny Cluster will ensure these IP addreses are static at a later point.
- It defines a Kubernetes master, as well as two nodes (if you look closely, you'll note the master actually shares an IP address with one of the nodes, which implies that the master also acts as a node).
- Both of the two nodes will have Kiosk mode enabled, which means that they will open Chromium on boot to the URL
http://192.168.0.1:8123/lovelace/home?kioskandhttp://192.168.0.1:8123/lovelace/rpi?kiosk, respectively. - The
rpinode will have a Kubernetes label oftiny-cluster/node-pi-beacon=true. This is helpful in the later steps for deploying a Docker container to this node.
kubernetes:
master:
address: 192.168.0.1
connect: ssh
username: pi
nodes:
192.168.0.1:
name: main
kiosk:
url_slug: home
192.168.0.2:
name: rpi
labels:
- tiny-cluster/node-pi-red=true
kiosk:
url_slug: rpi
defaults:
kiosk:
url_base: http://192.168.0.1:8123/lovelace/
url_query_params:
- kiosk
url_slug: null
The following command will install kubeadm and then perform the necessary configuration steps:
./tiny-cluster.py --node master create
The configuration steps are equivalent to running the following commands:
./tiny-cluster.py master create_context: generate a.kube/home.confconfiguration file which is downloaded to the controlling computer so that it may subsequently access the cluster../tiny-cluster.py master install_network_add_on: Installflannelorweave./tiny-cluster.py master configure_nfs: Create a network file system at/mnt/tiny-clusterwhich may be accessed by the local network./tiny-cluster.py master untaint: If this master is also anode(the same IP is used within thenodescondfig), then remove themastertaint.
The folloting command will set up the rpi node, as defined in the above configuration:
/tiny-cluster.py rpi create
It begins by updating the device, assigning the static IP address, and installing the required scripts. Then it performs commands equivalent to running the following:
./tiny-cluster.py rpi configure: write the configuration files (e.g., the kiosk startup URL) to the device and join the Kubernetes cluster../tiny-cluster.py rpi update: make sure all packages are up-to-date../tiny-cluster.py rpi reboot: restart the device.
The following additional commands may be useful:
./tiny-cluster.py rpi ssh: SSH into the device./tiny-cluster.py rpi join: (Re)join the Kubernetes cluster./tiny-cluster.py rpi label: (Re)label the node in the cluster
Included in the ./kubernetes folder are a number of sample deployments for Docker containers I have created.
For example, you can use kubectl apply -f ./kubernetes/rode-red.yaml to deploy Node Red. In the above example configuration file, we used the label tiny-cluster/node-pi-red=true, which is what tells Kubernetes to deploy to that node in particular.
The following sample deployments are included:
./kubernetes/node-red.yaml: Node Red./kubernetes/beacon.yaml: A BTLE beacon that advertises the presence of your phone via MQTT. Useful in conjunction with Home Assistant to determine which room you are in../kubernetes/obd-monitor.yaml: OBD Monitor. Useful for monitoring vehicles.
You may have more than one configuration, known as a Context. The default context is home, thus the fact that your configuration usually resides at contexts/home.yaml. If you were to create a second file named contexts/work.yaml, then you could run ./tiny-cluster.py -c work master create (or any other command), where the context name is the first argument.
Configurations are loaded in the following way:
defaults.yamlis loaded.contexts/the-context-name.yamlis merged on top of those values.- From the resulting config, the
defaultsentries are merged with the specific values provided withinkubernetesandnodes. For example, in the above sample configuration, there is no need to re-define theurl_basefor the kiosk in each node, because it is inherited fromdefaults.kiosk.
Tiny Cluster supports using a Kubernetes master IP that is not a Raspberry Pi. It has specifically been tested on Ubuntu 18.04. It should generally work with Debian-flavors, but has not been tested beyond that. However, it may require some manual tuning. For example:
- Your SSH user must be able to sudo without a password, like this for Ubuntu
- You may wish to make systemd the default.
Also, be aware that Tiny Cluster will symlink ~/.kube/config to the config file for the kubeadm master it creates.
defaults:
node:
dns: 192.168.0.1 # Set the DNS server
hdmi: false # Turn off the HDMI
interface: wlan0 # Default network interface
usb_ethernet: true # Turn on USB/Ethernet card
See the comments in defaults.yaml
- Raspbian Jessie
- Raspbian Buster
- Raspberry Pi 4 B+
- Raspberry Pi 3 B+
- Raspberry Pi 3 B
- Raspberry Pi Zero W