Kubernetes cluster via kubeadm

Ter lering ende vermaeck ga ik een Kubernetes Cluster maken met Raspberry PI’s, model 4B, bestaande uit één master en twee workers (minions). De RPI’s krijgen hun spanning via USB-C connectors, aangesloten op een USB Power Hub. Via ethernetkabels zijn ze allen aangesloten op een netwerk-switch (Gigabit). Een SD card voorziet in het Linux OS. (Ubuntu)

De pre-requisites zijn:

  • Nieuwe installatie van Ubuntu
  • 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.50
    • node1 = 192.168.1.51
    • node2 = 192.168.1.52

Stap 1. Installeren Ubuntu

Om ubuntu te installeren, volg de stappen zoals beschreven in ‘Installatie Ubuntu op RPi

Stap 2: Installeer docker

Voer de stappen uit zoals hier omschreven: ‘Installatie docker op ubuntu

Stap 3: Swap uitzetten

Disable swap met de volende commando’s:

$ sudo sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab 
$ sudo swapoff -a

Stap 4. cgroup enable limit support

Voeg de volgende opties toe aan het bestand /boot/firmware/cmdline.txt Zorg ervoor dat het aan het eind van de regel wordt toegevoegd en niet op een nieuwe regel!

cgroup_enable=cpuset cgroup_enable=memory cgroup_memory=1

Stap 5. Stel netwerk forwarding in

Gebruik hiervoor de volgende commando’s:

$ sudo modprobe overlay      ## noodzakelijk voor containerd
$ sudo modprobe br_netfilter ## noodzakelijk voor kubernetes

$ sudo tee /etc/sysctl.d/kubernetes.conf<<EOF 
net.bridge.bridge-nf-call-ip6tables = 1 
net.bridge.bridge-nf-call-iptables = 1 
net.ipv4.ip_forward = 1 
EOF
 
$ sudo sysctl --system

Optioneel: installeer Helm op de RPi:

$ curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3
$ chmod 700 get_helm.sh
$ ./get_helm.sh
$ helm version

Optioneel: wijzig de docker cgroup driver naar systemd. Dit is een aanbeveling van Kubernetes. Maak/wijzig hiervoor het bestand /etc/docker/daemon.json met de volgende inhoud:

{
   "exec-opts": ["native.cgroupdriver=systemd"],
   "log-driver": "json-file",
   "log-opts": {
     "max-size": "100m"
   },
   "storage-driver": "overlay2"
 }

Stap 6a. Installatie kubernetes onderdelen (apt)

De volgende stappen gelden voor zowel de master als de workers. Hiermee wordt de Kubernetes repository toegevoegd en kubeadm, kubelet en kubectl geïnstalleerd. Voer deze commando’s uit op elke Raspberry Pi:

$ sudo apt install -y apt-transport-https conntrack
$ curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -

$ cat <<EOF | sudo tee /etc/apt/sources.list.d/kubernetes.list
deb https://apt.kubernetes.io/ kubernetes-xenial main
EOF

$ sudo apt update
$ sudo apt install -y kubeadm kubelet kubectl
$ sudo apt-mark hold kubeadm kubelet kubectl

Stap 7. 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 8. Container networking

Container networking is één van de belangrijkste onderdelen in Kubernetes en goed werkende controllers voor RPi’s zijn ‘weave’ en ‘flannel’.

1. 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

2. 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 9. 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.50: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 10. 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 ubuntu@rpi-1:/$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
NAME    STATUS   ROLES    AGE     VERSION
rpi-1   Ready    master   1h14s   v1.19.4
rpi-2   Ready    <none>   1h13s   v1.19.4
rpi-3   Ready    <none>   1h13s   v1.19.4

Stap 11. 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 --name=nginx-service

De nginx service poort-nummer kunnen we vinden met

$ kubectl get service nginx-service
NAME           TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
nginx-service  NodePort    10.110.34.151   <none>        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. http://192.168.1.51:32456