# 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. ## Pre-reqs: * 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 [Etcher.io](https://etcher.io) to burn the SD card. Before booting set up an empty file called `ssh` in /boot/ on the SD card. Use Raspbian Jessie https://downloads.raspberrypi.org/raspbian_lite/images/raspbian_lite-2017-07-05/ * 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 get.docker.com | sh && \ sudo usermod pi -aG docker ``` * Disable swap For Kubernetes 1.7 and newer you will get an error if swap space is enabled. Use the `swapoff` tool to turn off any swap files set up by the system. Make this permanent by editing `/etc/fstab` and commenting out the swap line. ``` $ sudo swapon --summary Filename Type Size Used Priority /var/swap file 102396 0 -1 $ sudo swapoff /var/swap $ 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 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 ``` > 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=192.168.0.27` 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 192.168.0.27:6443 --discovery-token-ca-cert-hash sha256:95cbb9ee5536aa61ec0239d6edd8598af68758308d0a0425848ae1af28859bea ``` * Check everything worked: ``` $ kubectl get pods --namespace=kube-system NAME READY STATUS RESTARTS AGE etcd-k8s-1 1/1 Running 0 4m kube-apiserver-k8s-1 1/1 Running 0 4m kube-controller-manager-k8s-1 1/1 Running 0 4m kube-dns-2459497834-63fw6 3/3 Pending 0 3m kube-proxy-jzt2r 1/1 Running 0 3m kube-scheduler-k8s-1 1/1 Running 0 4m ``` 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 https://git.io/weave-kube-1.6 ``` ### 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 192.168.0.27:6443 ``` You can now run this on the master: ``` $ kubectl get nodes NAME STATUS AGE VERSION k8s-1 Ready 5m v1.7.4 k8s-2 Ready 10m v1.7.4 ``` ## Deploy a container *function.yml* ``` apiVersion: v1 kind: Service metadata: name: markdownrender labels: app: markdownrender spec: type: NodePort ports: - port: 8080 protocol: TCP targetPort: 8080 nodePort: 31118 selector: app: markdownrender --- apiVersion: apps/v1beta1 # for versions before 1.6.0 use extensions/v1beta1 kind: Deployment metadata: name: markdownrender spec: replicas: 1 template: metadata: labels: app: markdownrender spec: containers: - name: markdownrender image: functions/markdownrender:latest-armhf imagePullPolicy: Always ports: - containerPort: 8080 protocol: TCP ``` Deploy and test: ``` $ kubectl create -f function.yml $ curl localhost:31118 -d "# test" ``` ## Start up the dashboard ``` $ curl -sSL https://rawgit.com/kubernetes/dashboard/master/src/deploy/kubernetes-dashboard.yaml | \ sed "s/amd64/arm/" | kubectl create -f - ``` You can then find the IP and port via `kubectl get svc -n kube-system`