Vanilla K8S mit Cilium auf Ubuntu 22.04 in Virtualbox
Moin. Heute bauen wir uns einen Kubernetes Cluster
Kubernetes Cluster in Virtualbox, ohne Scripte, und ohne Vagrant. Von Hand halt eben ;)
Zuletzt aktualisiert: 02.11.2023
Level: Anfänger
Reqs: 8GB+ RAM, 100GB+ Disk
Ich entwickle auf Ubuntu 22.10, das ist jedoch weitestgehend irrelevant, es sei denn du benutzt Mac oder Windows. Dann musst du entsprechend PuTTY benutzen oder Binaries mit choco/brew installieren. Dieses Walkthrough ist nur für Ubuntu geschrieben. BTW: Ich habe mein Ubuntu auf Englisch eingestellt, daher sind Labels auch auf Englisch, das sollte dich aber nicht davon abhalten mir zu folgen.
Auf gehts! Vorbereitung und Virtualbox
Was du brauchst:
Lade dir das Ubuntu Server 22.04 ISO herunter
Installiere Virtualbox
Installiere das "VirtualBox Extension Pack" (herunterladen und ausführen, nachdem Virtualbox installiert wurde)
Nun erstellen wir unsere erste VM. Klicke in Virtualbox auf "New".
Name "K8S01" (oder dein eigenes Namensschema)
ISO Image: Die heruntergeladene Ubuntu Server ISO
Checkbox bei "Skip Unattended Installation" (hat bei mir schlichtweg nicht funktioniert und wir wollen es ja von Hand machen)
Auf Next klicken.
Base memory: Mein Rechner hat nur 16 GB, daher belasse ich es bei 2GB. Wir werden später diese VM 2x klonen und damit 6GB verbrauchen. Bleiben 10GB für Host OS, Browser, Spotify, etc...
Processors: Mit dem 2. rechnet man schneller
Enable EFI: Check. Warum nicht.
Next. Die Settings für die Platte belasse ich bei dynamischen 25GB. Wenn wir später persistente Volumes brauchen werden wir das anders lösen. (Weitere Volumes einhängen und mit hostPath volumes oder Rook benutzen)
Finish.
Nachdem die VM erstellt wurde editiere ich sie vor dem Start und mache noch ein paar Anpassungen:
System -> Motherboard -> Boot Order -> "Floppy" entfernen
System -> Processor -> Extended Features -> Alle aktivieren
Storage -> K8S01.vdi -> "Solid-state Drive" aktivieren
Audio -> Audio deaktivieren
Network -> Adapter 1 -> Enable + Bridged Adapter
Starten wir die VM. Das Setup ist recht straightforward. Ich installiere:
Step 1: Sprache: English
Step 2: Mit aktualisiertem Installer
Step 3: Kezboard Lazout: German / German (no dead keys)
Type: Ubuntu Server (minimized)
Network Connection: Keine Änderung (Notiere dir die IP Adresse!)
Proxy: Nö
Mirror: Nö
Storage Config: Passt so!
Storage Config: Ja, es passt wirklich!
Profile Setup: Selbstständig ausfüllen.
SSH Setup: OpenSSH Server installieren und PubKeys von GitHub importieren
Bloß keine Snaps installieren.
Dann startet die Installation. Wenn diese fertig ist starten wir die VM neu und schalten sie dann per ACPI aus, nur um sie danach im Headless Mode neu zu starten.
Den Headless Mode findest du in Virtualbox neben dem Start-Pfeil im Dropdown.
Warum Headless? Es ist natürlich einfacher alles per Copy-Paste in das eigene Terminal einzugeben als in ein VM-Fenster abzutippen ;)
Jetzt installieren wir mal die restlichen Updates und ein paar Basics (und ja, ich nutze nano!)
sudo apt update
sudo apt upgrade -y
sudo apt install -y nano less sed bash-completion
echo "export EDITOR=nano" >> $HOME/.bashrc
Da wir später enorm viel per sudo ausführen müssen stell ich auch gleich mal auf passwordless sudo um. Natürlich auf eigene Gefahr.
sudo sed -i $'s/%sudo\tALL=(ALL:ALL) ALL/%sudo\tALL=(ALL:ALL) NOPASSWD: ALL/' /etc/sudoers
Jetzt brauchen wir eine Container-Runtime. Ich habe mich für containerd entschieden. Ein gute Zusammenfassung für die notwendigen Schritte zur installation habe ich hier gefunden: https://www.nocentino.com/posts/2021-12-27-installing-and-configuring-containerd-as-a-kubernetes-container-runtime/
Ich fasse sie nochmal hier schnell zusammen:
sudo modprobe overlay
sudo modprobe br_netfilter
cat <<EOF | sudo tee /etc/modules-load.d/containerd.conf
overlay
br_netfilter
EOF
cat <<EOF | sudo tee /etc/sysctl.d/99-kubernetes-cri.conf
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-ip6tables = 1
EOF
sudo sysctl --system
sudo apt update
sudo apt install -y containerd
sudo mkdir -p /etc/containerd
sudo containerd config default | sudo tee /etc/containerd/config.toml
sudo sed -i 's/ SystemdCgroup = false/ SystemdCgroup = true/' /etc/containerd/config.toml
sudo systemctl restart containerd
Unsere Container Runtime ist bereit. Jetzt brauchen wir noch die Kubernetes Tools. Die Anleitung gibts von k8s frei Haus: https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/#installing-kubeadm-kubelet-and-kubectl
sudo apt install -y apt-transport-https ca-certificates curl
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.28/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.28/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list
sudo apt update
sudo apt install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl
Kubernetes unterstützt seit 1.22 swap als alpha-feature, aber ich möchte es nicht drauf ankommen lassen. Daher deaktiviere ich Swap für jetzt und immer.
sudo swapoff -a
sudo sed -e '/\/swap/ s/^#*/#/' -i /etc/fstab
Alles klar. Jetzt müssen wir nur noch Kubernetes per kubeadm installieren, oder?
Ich habe Cilium genannt. Nach den Kubernetes Community Days 2022 war ich so davon begeistert, dass ich es einfach einsetzen musste. Grüße gehen raus :D
Ich installiere noch die Cilium und Hubble binaries, bevor wir die Maschinen klonen und K8S fertig aufsetzen. Die Befehle sind aus der offiziellen Doku.
CILIUM_CLI_VERSION=$(curl -s https://raw.githubusercontent.com/cilium/cilium-cli/master/stable.txt)
CLI_ARCH=amd64
if [ "$(uname -m)" = "aarch64" ]; then CLI_ARCH=arm64; fi
curl -L --fail --remote-name-all https://github.com/cilium/cilium-cli/releases/download/${CILIUM_CLI_VERSION}/cilium-linux-${CLI_ARCH}.tar.gz{,.sha256sum}
sha256sum --check cilium-linux-${CLI_ARCH}.tar.gz.sha256sum
sudo tar xzvfC cilium-linux-${CLI_ARCH}.tar.gz /usr/local/bin
rm cilium-linux-${CLI_ARCH}.tar.gz{,.sha256sum}
export HUBBLE_VERSION=$(curl -s https://raw.githubusercontent.com/cilium/hubble/master/stable.txt)
HUBBLE_ARCH=amd64
if [ "$(uname -m)" = "aarch64" ]; then HUBBLE_ARCH=arm64; fi
curl -L --fail --remote-name-all https://github.com/cilium/hubble/releases/download/$HUBBLE_VERSION/hubble-linux-${HUBBLE_ARCH}.tar.gz{,.sha256sum}
sha256sum --check hubble-linux-${HUBBLE_ARCH}.tar.gz.sha256sum
sudo tar xzvfC hubble-linux-${HUBBLE_ARCH}.tar.gz /usr/local/bin
rm hubble-linux-${HUBBLE_ARCH}.tar.gz{,.sha256sum}
Jetzt fahren wir die VM herunter (per sudo shutdown now oder ACPI shutdown) und erstellen einen Snapshot. (Wir können auch einen Live-Snapshot machen).
Dann klonen wir den Snapshot zwei mal und erstellen damit die Maschinen K8S02 und K8S03. Dabei weisen wir allen NICs neue MAC Adressen zu.
Die neuen Maschinen brauchen auch noch neue Hostnames. Dafür starten wir beide normal, loggen uns ein und führen auf der ersten aus:
sudo hostnamectl set-hostname k8s02
sudo sed -i 's/127.0.1.1 k8s01/127.0.1.1 k8s02/' /etc/hosts
Und auf der zweiten:
sudo hostnamectl set-hostname k8s03
sudo sed -i 's/127.0.1.1 k8s01/127.0.1.1 k8s03/' /etc/hosts
In meinem Fall hat meine Fritz!Box der geklonten Maschine die gleiche IP vergeben (muss wohl am hostname liegen). Leider reicht es nicht den Hostname zu ändern. Wenn die IP Adressen der geklonten bei dir auch gleich sind musst du nach dem Ändern des hostname beide Maschinen herunterfahren und dem Bridged Adapter eine neue Mac-Adresse zuweisen.
Fahre beide Klone danach wieder hoch und prüfe, dass die IPs nun unterschiedlich sind. Notiere sie, fahre die VMs herunter und starte alle wieder headless.
Auf der ersten Node K8S01 werde ich nun Kubernetes installieren, allerdings ohne kube-proxy, da wir diesen durch Cilium ersetzen.
sudo kubeadm init --skip-phases=addon/kube-proxy
Nach einiger Zeit bekommen wir den Output:
Ich kopiere mir wie angegeben die Kubeconfig in mein HOME-Verzeichnis.
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
Nun kann ich mit dem kubectl auf der Node mit dem Cluster interagieren. Natürlich kann ich mir die config auch auf meinen Rechner kopieren und von dort aus mit kubectl agieren. Auf meinem Host erstelle ich das gleiche .kube Verzeichnis und lade die config herunter. Glücklicherweise heißt mein Benutzer auf der Node genauso wie auf dem Host. Wenn das bei dir anders ist musst du den Befehl anpassen.
mkdir -p $HOME/.kube
scp 192.168.188.88:/home/oeglseder/.kube/config $HOME/.kube/config
kubectl get nodes
Der letzte Befehl gibt nun aus, dass sich in meinem Cluster eine Node befindet und sie NotReady ist. Das liegt daran, dass wir noch kein Container Network haben.
Nun installieren wir Cilium. Die binary dafür haben wir schon heruntergeladen. BTW mit watch kubectl get pods -A -o wide können wir recht einfach verfolgen was passiert, während wir auch cilium warten. Hubble aktivieren wir noch nicht (aus Gründen).
cilium install
Jetzt joine ich mit den beiden anderen Nodes den Cluster. Dafür benutze ich den Befehl, den mir kubeadm init ausgespuckt hat.
kubeadm join 192.168.188.88:6443 --token birfuv.lxr89c04t2nf5dj1 --discovery-token-ca-cert-hash sha256:b0aca90ac92f5ebd8e0cde9f50cdda75daf81d20a09ac1825e29993a8d24668e
Danach können wir auch Hubble aktivieren
cilium hubble enable
Fertig. Viel Spaß mit deinem 3-Node Vanilla K8S Cluster mit Cilium und Hubble auf Ubuntu 22.04, in einer Virtualbox.