Skip to content

Instantly share code, notes, and snippets.

Forked from alexellis/
Last active April 30, 2022 10:05
Show Gist options
  • Save shanselman/5f754fecaf8f3253e0136d030f6d4cb3 to your computer and use it in GitHub Desktop.
Save shanselman/5f754fecaf8f3253e0136d030f6d4cb3 to your computer and use it in GitHub Desktop.
K8s on Raspbian

K8s on (vanilla) Raspbian Lite

Yes - you can create a Kubernetes cluster with Raspberry Pis with the default operating system Raspbian. Carry on using all the tools and packages you're used to with the officially-supported OS.


  • You must use an RPi2 or 3 for Kubernetes
  • I'm assuming you're using wired ethernet (Wi-Fi also works)

Master node setup

  • Flash Raspbian to a fresh SD card.

You can use to burn the SD card.

Before booting set up an empty file called ssh in /boot/ on the SD card.

Use Raspbian Jessie

  • Change hostname

Use the raspi-config utility to change the hostname to k8s-master-1 or similar and then reboot.

  • Install Docker

This installs 17.05 - the latest release for Jessie.

$ curl -sSL | sh && \
sudo usermod pi -aG docker
  • Disable swap

For Kubernetes 1.7 and newer you will get an error if swap space is enabled.

Turn off swap and make it stay off:

$ sudo dphys-swapfile swapoff
$ sudo dphys-swapfile uninstall
$ sudo update-rc.d dphys-swapfile remove

This should now show no entries:

$ sudo swapon --summary
  • Edit /boot/cmdline.txt

Add this text at the end of the line, but don't create any new lines:

cgroup_enable=cpuset cgroup_enable=memory

Now reboot - do not skip this step.

  • Add repo lists & install kubeadm
$ curl -s | sudo apt-key add - && \
  echo "deb kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list && \
  sudo apt-get update -q && \
  sudo apt-get install -qy kubeadm

I realise this says 'xenial' in the apt listing, don't worry. It still works.

  • You now have two new commands installed:

  • kubeadm - used to create new clusters or join an existing one

  • kubectl - the CLI administration tool for Kubernetes

  • Initialize your master node:

$ sudo kubeadm init

Optionally also pass --apiserver-advertise-address= with the IP of the Pi.

Note: This step will take a long time, even up to 15 minutes.

After the init is complete run the snippet given to you on the command-line:

  mkdir -p $HOME/.kube
  sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
  sudo chown $(id -u):$(id -g) $HOME/.kube/config

This step takes the key generated for cluster administration and makes it available in a default location for use with kubectl.

  • Now save your join-token

Your join token is valid for 24 hours, so save it into a text file. Here's an example of mine:

$ kubeadm join --token 9e700f.7dc97f5e3a45c9e5 --discovery-token-ca-cert-hash sha256:95cbb9ee5536aa61ec0239d6edd8598af68758308d0a0425848ae1af28859bea
  • Check everything worked:
$ kubectl get pods --namespace=kube-system
NAME                           READY     STATUS    RESTARTS   AGE                
etcd-of-2                      1/1       Running   0          12m                
kube-apiserver-of-2            1/1       Running   2          12m                
kube-controller-manager-of-2   1/1       Running   1          11m                
kube-dns-66ffd5c588-d8292      3/3       Running   0          11m                
kube-proxy-xcj5h               1/1       Running   0          11m                
kube-scheduler-of-2            1/1       Running   0          11m                
weave-net-zz9rz                2/2       Running   0          5m 

You should see the "READY" count showing as 1/1 for all services as above. DNS uses three pods, so you'll see 3/3 for that.

  • Setup networking

Install Weave network driver

$ kubectl apply -f

Join other nodes

On the other RPis, repeat everything apart from kubeadm init.

  • Change hostname

Use the raspi-config utility to change the hostname to k8s-worker-1 or similar and then reboot.

  • Join the cluster

Replace the token / IP for the output you got from the master node:

$ sudo kubeadm join --token 1fd0d8.67e7083ed7ec08f3

You can now run this on the master:

$ kubectl get nodes
k8s-1     Ready      5m        v1.7.4
k8s-2     Ready      10m       v1.7.4

Deploy a container


apiVersion: v1
kind: Service
  name: markdownrender
    app: markdownrender
  type: NodePort
    - port: 8080
      protocol: TCP
      targetPort: 8080
      nodePort: 31118
    app: markdownrender
apiVersion: apps/v1beta1 # for versions before 1.6.0 use extensions/v1beta1
kind: Deployment
  name: markdownrender
  replicas: 1
        app: markdownrender
      - name: markdownrender
        image: functions/markdownrender:latest-armhf
        imagePullPolicy: Always
        - containerPort: 8080
          protocol: TCP

Deploy and test:

Note the -4 to force ipv4. You can also use the hostname of the master.

$ kubectl create -f function.yml 
$ curl localhost:31118 -4 -d "# test"

Start up the dashboard

Double check the rawgit below to make sure it hasn't moved or 404'ed. Note the -arm version we're using.

$ curl -sSL | \
  sed "s/amd64/arm/" | kubectl create -f -

You can then find the IP and port via kubectl get svc -n kube-system

Copy link

jimib commented Aug 27, 2019

I had to add this to the cmdline.txt:

cgroup_enable=cpuset cgroup_memory=1 cgroup_enable=memory

Otherwise I ran into this "CGROUPS_MEMORY: missing"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment