Set up kubernetes on a raspberry pi cluster running raspbian
I wanted to play around with OpenFaas and could generally use a local kubernetes setup that is not minikube but an actual cluster.
There are a couple of nice guides from the OpenFaas community and I am mostly following their steps.
Where I ran into trouble though was the setup of the k8 dashboard - all guides i found were either outdated or missing information. I had to piece together things and got it to work. I kept my notes and also put my script into a gist as things in k8 land are moving so fast your links to external docs can quickly die or not reflect what you saw when you did it yourself.

DHCP setup
You don't want your cluster nodes IPs to be changing. Set up fixed IPs for your nodes on your router. If you have no local DHCP available you need to use the original version of the make-rpi.sh script that also sets up a DHCP server. See below.
In my case i set up the IPs 192.168.42.[40~43] for my nodes .40 being the master node.
Provision base system
Get a Raspbian Stretch Lite image from here.
I used 2018-11-13-raspbian-stretch-lite.img
"Burn" that image onto an SD card using dd or if you prefer a GUI use etcher.
Modify the base system
This is a modified version of this script - I use a separate DHCP server and did not want to have it run on the pi. Everything else is the same.
The script will create two mount points: /mnt/rpi/root and /mnt/rpi/boot. Make sure there is nothing in the way.
Put your ssh pub key into a file template-authorized_keys in the same directory as the make-rpi.sh script.
export DEV=sda
export IMAGE=2018-11-13-raspbian-stretch-lite.img
DEV should be the SD cards device and IMAGE the name of the raspbian image. Edit if necessary.
sudo ./make-rpi.sh pikube-master
sudo ./make-rpi.sh pikube-node-0
sudo ./make-rpi.sh pikube-node-1
sudo ./make-rpi.sh pikube-node-2
to modify the four SD cards/images
Then boot the system on all pis.
Install docker
On all nodes
curl -sLS https://get.docker.com | sudo sh
sudo usermod -aG docker pi
Prepare k8s installation
Do the following on all nodes:
Disable swap on all nodes
sudo dphys-swapfile swapoff && \
sudo dphys-swapfile uninstall && \
sudo update-rc.d dphys-swapfile remove
This should show no entries
sudo swapon --summary
Edit /boot/cmdline.txt
sudo nano /boot/cmdline.txt
Add this text at the end of the line, but don't create any new lines:
cgroup_enable=cpuset cgroup_memory=1 cgroup_enable=memory
Now reboot all nodes (do not skip this)
sudo reboot
Install kubernetes
Setup the package manager and 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
On master
sudo kubeadm config images pull -v3
And init master
sudo kubeadm init --token-ttl=0
...
Your Kubernetes master has initialized successfully!
To start using your cluster, you need to run the following as a regular user:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
https://kubernetes.io/docs/concepts/cluster-administration/addons/
You can now join any number of machines by running the following on each node
as root:
kubeadm join 192.168.42.40:6443 --token 80zx1c.1kz4g133riual7qf --discovery-token-ca-cert-hash sha256:804d2fa237ddbacf125b6b350d8a4a9b33bca4338bddad567f40a1268a4dd94d
Install weave net driver
kubectl apply -f \
"https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d '\n')"
pi@pikube-master:~ $ kubectl get pods --namespace=kube-system
NAME READY STATUS RESTARTS AGE
coredns-86c58d9df4-h8rwq 0/1 Pending 0 5m56s
coredns-86c58d9df4-pwhpq 0/1 Pending 0 5m56s
etcd-pikube-master 1/1 Running 0 5m57s
kube-apiserver-pikube-master 1/1 Running 0 4m57s
kube-controller-manager-pikube-master 1/1 Running 0 6m2s
kube-proxy-g59t9 1/1 Running 0 5m56s
kube-scheduler-pikube-master 1/1 Running 0 4m51s
weave-net-rw2nz 0/2 ContainerCreating 0 27s
eventually
pi@pikube-master:~ $ kubectl get pods --namespace=kube-system
NAME READY STATUS RESTARTS AGE
coredns-86c58d9df4-h8rwq 1/1 Running 0 7m9s
coredns-86c58d9df4-pwhpq 1/1 Running 0 7m9s
etcd-pikube-master 1/1 Running 0 7m10s
kube-apiserver-pikube-master 1/1 Running 0 6m10s
kube-controller-manager-pikube-master 1/1 Running 0 7m15s
kube-proxy-g59t9 1/1 Running 0 7m9s
kube-scheduler-pikube-master 1/1 Running 0 6m4s
weave-net-rw2nz 2/2 Running 0 100s
Join nodes
This has to happen within 24 hours - the token expires. And apparently it's a pain in the butt to get a new token, so make sure you do this right away...
sudo kubeadm config images pull -v3
sudo kubeadm join 192.168.42.40:6443 --token 80zx1c.1kz4g133riual7qf --discovery-token-ca-cert-hash sha256:804d2fa237ddbacf125b6b350d8a4a9b33bca4338bddad567f40a1268a4dd94d
Checking on master
pi@pikube-master:~ $ kubectl get nodes
NAME STATUS ROLES AGE VERSION
pikube-master Ready master 12m v1.13.2
pikube-node-0 NotReady <none> 13s v1.13.2
and enventually
pi@pikube-master:~ $ kubectl get nodes
NAME STATUS ROLES AGE VERSION
pikube-master Ready master 13m v1.13.2
pikube-node-0 Ready <none> 78s v1.13.2
Joining the other nodes
pi@pikube-master:~ $ kubectl get nodes
NAME STATUS ROLES AGE VERSION
pikube-master Ready master 16m v1.13.2
pikube-node-0 Ready <none> 4m7s v1.13.2
pikube-node-1 NotReady <none> 2s v1.13.2
pikube-node-2 NotReady <none> 1s v1.13.2
and then
pi@pikube-master:~ $ kubectl get nodes
NAME STATUS ROLES AGE VERSION
pikube-master Ready master 19m v1.13.2
pikube-node-0 Ready <none> 6m24s v1.13.2
pikube-node-1 Ready <none> 2m19s v1.13.2
pikube-node-2 Ready <none> 2m18s v1.13.2
Do not auto-update k8 packages
sudo apt-mark hold kubelet kubeadm kubectl
Get the dashboard running
create a role (this has admin privs - dont do this on prod)
Not 100% sure this is needed. This was in a couple of other guides that were older and ended up not working for me in the end.
echo -n 'apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: kubernetes-dashboard
labels:
k8s-app: kubernetes-dashboard
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: kubernetes-dashboard
namespace: kube-system' | kubectl apply -f -
Deploy the dashboard
I kept a gist copy of the yaml file below here.
wget https://raw.githubusercontent.com/kubernetes/dashboard/master/aio/deploy/recommended/kubernetes-dashboard-arm.yaml
kubectl apply -f ./kubernetes-dashboard-arm.yaml
pi@pikube-master:~ $ kubectl get pods --all-namespaces
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system coredns-86c58d9df4-h8rwq 1/1 Running 1 23h
kube-system coredns-86c58d9df4-pwhpq 1/1 Running 1 23h
kube-system etcd-pikube-master 1/1 Running 1 23h
kube-system kube-apiserver-pikube-master 1/1 Running 2 23h
kube-system kube-controller-manager-pikube-master 1/1 Running 1 23h
kube-system kube-proxy-g59t9 1/1 Running 1 23h
kube-system kube-proxy-ngv8h 1/1 Running 1 23h
kube-system kube-proxy-ngx7l 1/1 Running 1 23h
kube-system kube-proxy-ws7xb 1/1 Running 1 23h
kube-system kube-scheduler-pikube-master 1/1 Running 1 23h
kube-system kubernetes-dashboard-56bcddb89b-rjzdk 0/1 ContainerCreating 0 24s
kube-system weave-net-dk8np 2/2 Running 5 23h
kube-system weave-net-r92kj 2/2 Running 5 23h
kube-system weave-net-rw2nz 2/2 Running 5 23h
kube-system weave-net-wxhsz 2/2 Running 4 23h
Either start the proxy on master and then tunnel to it
kubectl proxy
ssh -N -L 8001:localhost:8001 pi@pikube-master
Or (better) set up your cluster in your local ~/.kube/config (copy the stuff from ~/.kube/config on master) and then locally do
kubectl proxy
You can then access the dashboard (in both cases) here:
http://localhost:8001/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy
To log in you need to create a user/token:
See also: https://github.com/kubernetes/dashboard/wiki/Creating-sample-user
echo -n 'apiVersion: v1
kind: ServiceAccount
metadata:
name: admin-user
namespace: kube-system' | kubectl apply -f -
echo -n 'apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: admin-user
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: admin-user
namespace: kube-system' | kubectl apply -f -
pi@pikube-master:~ $ kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | grep admin-user | awk '{print$1}')
Name: admin-user-token-trlxs
Namespace: kube-system
Labels: <none>
Annotations: kubernetes.io/service-account.name: admin-user
kubernetes.io/service-account.uid: 65a7d5be-1e52-11e9-91c0-b827eb3539fa
Type: kubernetes.io/service-account-token
Data
====
namespace: 11 bytes
token: eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJhZG1pbi11c2VyLXRva2VuLXRybHhzIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImFkbWluLXVzZXIiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiI2NWE3ZDViZS0xZTUyLTExZTktOTFjMC1iODI3ZWIzNTM5ZmEiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6a3ViZS1zeXN0ZW06YWRtaW4tdXNlciJ9.fbaUgCE-x_bfiTphiLuUPEH8v_v-eELn5uEVQndIPG6wt7vfULCDNS3757LUWRR-AAkhZDk-cb0PeXXUse7WPVuN8ZAVXRv-N-IqU_uZEaKtUU-saCUx9T0BikLFyvh9gIDmNAywF-librhRIJpdXPe_O9JPy5TXzcZwnWn5CVsKKXiGZ4yqWcSUUECtmybvfluBOS9gTHvylzVxRdiz0a9zMwNNIWUKNQOo-Pldx8npKMvh-OvQj4HfR2bSgAzu7-anWfQrQ1Wlm-lu8zM0U-F-J797KnU8CAqOHm571qt9t5lBa4V4rGspAWRqwWlQNyYIofr9yLvuo4Q3SUjDXQ
ca.crt: 1025 bytes
Login with a token using the secret from above
Done.
Helpful Links
- https://gist.github.com/alexellis/a7b6c8499d9e598a285669596e9cdfa2
- https://github.com/alexellis/k8s-on-raspbian
- https://github.com/alexellis/k8s-on-raspbian/blob/master/GUIDE.md
- https://github.com/kubernetes/dashboard/wiki/Access-control
- https://kubernetes.io/docs/reference/kubectl/cheatsheet/
- https://github.com/kubernetes/dashboard