Ter lering ende vermaeck ga ik een Kubernetes Cluster maken met Raspberry PI’s, model 3B, bestaande uit één master en twee workers (minions). De RPI’s krijgen hun spanning via micro-USB connectors, aangesloten op een USB Power Hub. Via ethernetkabels zijn ze allen aangesloten op een netwerk-switch (Gigabit). Een SD card voorziet in het Raspbian OS. (Hypriot)
Een vierde RPi (model 4) is in gebruik als control-station en als NGINX proxy server waarop de (Let’sEncrypt) certificaten zijn geïnstalleerd voor de websites in de K8s-cluster.

De pre-requisites zijn:
- Nieuwe installatie van Hypriot
- Netwerkkabels aangesloten op een Gigabit Network switch waarop ook mijn laptop is aangesloten (en dus SSH toegang)
- USB voedingskabels aangesloten aan een Xtorm USB Power Hub
- Hostname en Static IP adres
- master = 192.168.1.101
- node1 = 192.168.1.102
- node2 = 192.168.1.103
Stap 1. SD card maken
Om Hypriot op een SD card te zetten maak ik gebruik van Etcher. Na het downloaden van de Hypriot image is het zeer eenvoudig om met Etcher de image op een SD card te plaatsen.
Stap 2: IP adres instellen
Standaard login op de Hypriot OS is
username: pirate
password: hypriot
Nadat de Raspberry Pi gestart is en je hebt het IP adres gevonden (bv. via je router-dashboard) kun je inloggen op de RPi en het bestand /etc/dhcpcd.conf aanpassen om een vast IP adres in te stellen. Zoek naar het gedeelte en pas dit aan. Bijvoorbeeld:
# Example static IP configuration: interface eth0 static ip_address=192.168.1.101/24 static routers=192.168.1.254 static domain_name_servers=192.168.1.254 8.8.8.8
Hierna geven we ook elke Raspberry Pi een eigen unieke hostname via cloud-init:
$ sudo vi /boot/user-data
Plaats hier de juiste hostname in het bestand /boot/user-data, bijvoorbeeld:
hostname: master manage_etc_hosts: true
Tevens kun je hier de locatie-gegevens instellen, zoals:
locale: "nl_NL.UTF-8" timezone: "Europe/Amsterdam"
Herhaal dit dan voor de overige RPi’s, uiteraard elk met hun eigen unieke ip adres en hostname. Hierna herstarten:
$ sudo reboot
Stap 3. Kopieer jouw public-key
Om in te loggen met ssh is het raadzaam om dit met een ssh-key-pair te doen. Om jouw public key te kopieren naar de Raspberry Pi’s, gebruik het volgende commando’s:
$ ssh-copy-id pirate@192.168.1.101 $ ssh-copy-id pirate@192.168.1.102 $ ssh-copy-id pirate@192.168.1.103
Nog vestandiger is het om hierna het inloggen met username/password op de ssh-daemon uit te schakelen. Zet daarvoor op elke RPI de volgende regel in /etc/ssh/sshd_config:
PasswordAuthentication no
Hierna de ssh daemon herstarten:
$ sudo systemctl restart sshd
Stap 4. Installatie kubeadm
De volgende stappen gelden voor zowel de master als de workers. Hiermee wordt de Kubernetes repository toegevoegd en kubeadm geïnstalleerd. Voer deze commando’s uit op elke Raspberry Pi:
$ 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 $ sudo apt-get install -y kubeadm
Stap 5. Configureer en start de master
De master node heeft een aantal images nodig en wordt daarna gestart met het ‘kubeadm init‘ commando. De ‘pods’ die later aangemaakt gaan worden geven we een eigen netwerk en dat geven we aan met de ‘pod-network-cidr‘ parameter: (cidr = Classless Inter-Domain Routing)
$ sudo kubeadm config images pull -v3
$ sudo kubeadm init --token-ttl=0 --pod-network-cidr=10.244.0.0/16
De instructies voor de worker-nodes zal op het scherm verschijnen en de token hebben we nodig om de workers te laten ‘joinen‘. Kopieer dus die instructie en gebruik het op de worker nodes.
Stap 6. Container networking
Container networking is één van de belangrijkste onderdelen in Kubernetes en goed werkende controllers voor RPi’s zijn ‘weave’ en ‘flannel’. Om weave te installeren dient het volgende commando:
$ kubectl apply -f "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d '\n')"
Weave heeft een aantal poorten nodig voor communicatie tussen de nodes. Daarom moeten deze opengezet worden in iptables op ALLE nodes:
$ sudo iptables -I INPUT -p tcp -m tcp --dport 6783 -j ACCEPT $ sudo iptables -I INPUT -p udp -m udp --dport 6783 -j ACCEPT $ sudo iptables -I INPUT -p udp -m udp --dport 6784 -j ACCEPT $ sudo iptables-save
Een alternatieve CNI is bv. flannel, deze installeer je zo:
$ kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
Stap 7. De workers configureren en koppelen
De gekopieerde instructie van de master wordt nu gebruikt op de worker-nodes die gekoppeld gaan worden om een cluster te vormen:
$ sudo kubeadm join 192.168.1.101:6443 --token xqpho0.zlujflhkt0 --discovery-token-ca-cert-hash sha256:5034e38d74344df0ef9f8d372c34b9e
Dit is een voorbeeld, uiteraard zal jouw token en hash-waarde anders zijn dan de hier getoonde.
Stap 8. KUBECONFIG environment
Voor elke Kubernetes cluster geldt een configuratie waarmee de instructies gegeven kunnen worden aan het cluster. Deze wordt standaard in /etc/kubernetes/admin.conf op de master-node geplaatst en kunnen we kopieren naar het werkstation waarmee we het beheer willen doen. Je kunt deze een willekeurige naam geven of de standaard naam (config) als dit de enige cluster is waarmee gecommuniceerd wordt. Op de master, voer de volgende commando’s uit:
$ sudo apt install -y kubectl $ mkdir -p $HOME/.kube $ sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config $ sudo chown $(id -u):$(id -g) $HOME/.kube/config
Hierna kun je op je eigen werkstation dit bestand kopieren, bv. met scp: (Windows gebruikers zouden ‘Windows Subsystem for Linux‘ moeten gaan gebruiken)
$ scp pirate@master:/$HOME/.kube/config .
Hierna zou het volgende commando de nodes laten zien van je nieuwe cluster: (als je tenminste kubectl op je werkstation hebt geïnstalleerd)
$ kubectl get nodes -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME master Ready master 47h v1.16.2 192.168.178.201 <none> Raspbian GNU/Linux 9 (stretch) 4.19.66-v7+ docker://19.3.4 node1 Ready <none> 47h v1.16.2 192.168.178.202 <none> Raspbian GNU/Linux 9 (stretch) 4.19.66-v7+ docker://19.3.4 node2 Ready <none> 47h v1.16.2 192.168.178.203 <none> Raspbian GNU/Linux 9 (stretch) 4.19.66-v7+ docker://19.3.4
Stap 9. Testen
Als test kunnen we nu een nginx webserver installeren en een nodeport-service maken die een random-poort doorstuurt. De commando’s:
$ kubectl run nginx --image=nginx --restart=Never --port=80 $ kubectl expose pod nginx --type=NodePort
De nginx service poort-nummer kunnen we vinden met
$ kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 443/TCP 24h nginx NodePort 10.110.34.151 80:32456/TCP 85m
en in dit geval zien we dat de poort op 32456 geconfigureerd is op alle nodes. Met een browser kunnen we nu naar het IP adres en poort-nummer op één van de nodes en dat zal dan de NGINX welkom pagina laten zien.

Na het installeren van de CNI provider Flannel of Weave werkt de aanroep van services alleen voor de nodes waarop de deployments (of pods) actief zijn. Forwarding van de aanroep op de overige nodes werkt niet, totdat het volgende commando is uitgevoerd op alle nodes:
$ sudo iptables -P FORWARD ACCEPT