Setup Rancher on Server

Server Specs

Als Server wurde ein Server mit 2 Intel CPU Cores und 4 GB RAM ausgewählt. Als Image wurde ein custom Image ausgewählt, welches bereits vor längerer Zeit selber erstellt wurde. Es verwendet Debian 11 als OS und beinhaltet die wichtigsten Konfigurationen, welche man grundsätzlich auf allen Server haben sollte, wie z.B. konfigurierte Non Root User mit SSH Key usw. Durch dieses custom Image kann man relativ schnell Server erstellen und das ohne grösseren Aufwand.

Der Server verfügt sowohl über eine öffentliche IP, als auch über eine private IP, mit der er später mit den anderen Nodes kommunizieren kann.

Updaten des Servers

Was allerdings trotz des custom Images noch gemacht werden muss, ist den Server einmal zu updaten. So läuft er z.B. immer noch auf der Linuxkernal Version 5.10.0-19-amd64, der neuste Kernal der zum aktuellen Zeitpunkt für Debian 11 zur Verfügung steht ist 5.10.0-21-amd64.

$uname -a
Linux RancherNode1 5.10.0-19-amd64 #1 SMP Debian 5.10.149-2 (2022-10-21) x86_64 GNU/Linux

Command, um den Server upzudaten und neuzustarten.

$sudo apt update && sudo apt full-upgrade -y && sudo reboot


Installation

Als Erstes wird natürlich eine Docker Engine benötigt. Dafür wurde das docker.io Package verwendet, welches von den offiziellen Debian Repositorys zur Verfügung gestellt wird.

$sudo apt install docker.io apparmor -y

Als Nächstes wurde einen DNS Request gemacht, welcher mit der Domain rancher.bbzbl-it.dev auf die öffentliche IP vom gerade eben genannten Server zeigt.

Starten des Management-Clusters

Als erste musste das Management-Cluster gestartet werden. Dieses ist dafür zuständig, die verschiedensten Cluster zu managen, zu überwachen und stellt auch die Rancher UI zur Verfügung. Theoretisch kann man auch mehrere Server zu einem Management-Cluster verbinden, um die Ausfallsicherheit zu erhöhen. Da allerdings der Ausfall vom Management-Cluster keinen direkten Einfluss auf die deployten Applikationen hat, wurde aus Kostengründen entschieden, das Management-Cluster auf einer einzelnen Node zu deployen.

Um das Management-Cluster einfach zu deployen, wurde das offizielle Docker Image von Rancher verwendet. Dieses deployt alle nötigen Container und das single Node Kubernetescluster in einem einzelnen Dockercontainer. Da das Deployen eines Kubernetescluster direkten Zugriff auf den Linux Kernal benötigt, muss man den Dockercontainer mit der --privileged Flag starten. Dadurch fällt aber auch eine gewisse Isolation zwischen dem Dockercontainer und dem Hostsystem weg. Heisst, wenn ein Angreifer Zugriff auf den Dockercontainer hätte, könnte er auch einfach das ganze System komprimieren.

$sudo docker run -d --restart=unless-stopped \
    -p 80:80 -p 443:443 \
    --privileged \
    rancher/rancher:latest \
    --acme-domain rancher.bbzbl-it.dev


Erstes Einloggen

Nachdem der Dockercontainer nach etwa 15 Sekunden vollständig aufgestartet war, konnte das random generierte initiale Password ganz einfach durch die Logs ausgelesen werden.

$sudo docker logs  $(sudo docker ps -q)  2>&1 | grep "Bootstrap Password:"

Nach dem ersten Einloggen auf der Web-UI, wird man anschliessend dazu aufgefordert, das Passwort abzuändern. Ebenfalls ist es wichtig, dass man den Haken wegnimmt, bei dem steht, dass man sich dazu bereit erklärt, anonyme Nutzerdaten zu senden. Natürlich ist es jedem selber überlassen, ob man anonyme Daten senden möchte. Allerdings muss man es explizit nicht ankreuzen, da es per Default angekreuzt ist.

Screenshot from 2023-04-09 14-34-57

Erstellen eines ersten Clusters

Nach dem Einloggen, wurde als erstes ein neues Cluster erstellt. Auf diesem Cluster wird beabsichtigt, alle Ressourcen zu deployen. Um einfach Clusters zu erstellen, kann man sogenannte Node Drivers verwenden. Diese können je nach Anbieter konfiguriert werden und erstellen automatisiert Server und überwachen diese auch.

Screenshot from 2023-04-09 14-36-35

Leider ist per Default kein Node Driver für unseren Cloud-Anbieter vorhanden. Aus diesem Grund wurde zuerst im Internet nach einem passenden gesucht. Schlussendlich wurde auch ein Node Driver gefunden. Das Hinzufügen des Drivers verlief dann relativ schnell und unkompliziert. Alles was gemacht werden musste war, dass man die URL angeben musste, mit welcher der Node Driver heruntergeladen werden konnte.

Screenshot from 2023-04-09 14-38-01

Nach dem Hinzufügen konnte einfach auf der View Cluster Erstellen unser Cloud-Provider ausgewählt werden. Es war auch cool, dass es Support für VSphere gab. Dadurch könnte man auch ganz einfach in einer private Cloud (wenn man VSphere verwendet), mithilfe von Node Drivers ein eigenes Kubernetescluster aufbauen.

Screenshot from 2023-04-09 14-38-39

Später musste bei unserem Cloud-Provider ein Privates Network und eine Placement Group erstellt werden. Zwar ist dieser Schritt optional, allerdings bietet er grosse Vorteile. Ein Privates Network sorgt dafür, dass bestimmte, möglicherweise sensitive Ports, nicht öffentlich erreichbar sind und zudem Traffic nicht mitgeschnitten werden kann (auch wenn theoretisch jeglicher Traffic encryptet sein sollte). Eine Placement Group sorgt dafür, dass die Server physikalisch und logisch voneinander unabhängig sind. So würde z.B. der Ausfall von einem Networkswitch nur dazu führen, dass ein und nicht gleich alle drei Nodes nicht mehr erreichbar sind.

Nachdem dieser Schritt erledigt war, wurde über die UI das Kluster initialisiert.

Screenshot from 2023-04-09 14-43-49

Anschliessend dauerte es etwa 10 Minuten, bis alle Server korrekt eingerichtet waren und das Cluster erreichbar war.

Screenshot from 2023-04-09 16-05-14

Screenshot from 2023-04-09 16-04-11

Danach wurde ein Test Nginx Container deployt. Das Deployen des Containers und das Erstellen eines Ingres verlief ohne grössere Probleme. Leider stellte sich etwas später heraus, dass der Ingres jedes Mal, nachdem man ihn anspricht, timeouted. Laut dem Internet liegt das häufig daran, dass der Port 8472/UDP nicht geöffnet ist. Also wurde nmap verwendet, um herauszufinden, ob der Port wirklich nicht offen ist.

$nmap -p8472 -sU <IP>
Starting Nmap 7.80 ( https://nmap.org )
Nmap scan report for ****
Host is up (0.0010s latency).

PORT     STATE         SERVICE
8472/udp closed otv

Nmap done: 1 IP address (1 host up) scanned in 0.36 seconds


Und tatsächlich stellte sich heraus, dass der Port geschlossen war. Nach einer etwas längeren Recherche stellte sich heraus, dass für die Kommunikation das Netzwerkinterface eth0 verwendet wird, sofern nichts angegeben wurde. Aus diesem Grund musste in der Netzwerkkonfiguration explizit angeben werden, welches Netzwerk verwendet werden sollte. Nach einem Restart der verschiedenen Nodes hat dann auch der Ingres funktioniert.

  network:
    canal_network_provider:
      iface: <Interface>
    flannel_network_provider:
      iface: <Interface>


Nachdem nun das Cluster voll erreichbar war, konnte nun auch damit anfangen werden, unsere ersten Projekte zu deployen. Wie bereits gesagt, sollte das Cluster dafür verwendet werden. Um das zu realisieren, wurden einfach die Projekte dockerisiert und anschliessend wurde das Image auf ein Repository gepusht, um es anschliessend auf das Cluster zu pullen.
Etwas, was wir allerdings noch nie gemacht haben ist, die ganzen Images als Non Root User auszuführen. In den meisten Fällen wird die Applikation bereits von einem Non Root User ausgeführt. Die einzige Ausnahme dafür stellen unsere nginx Container dar. Glücklicherweise musste lediglich das Baseimage von nginx auf nginx-unpriviliged abgeändert werden, um sie als Non Root User zu starten.

Absichern der Nodes

Da unser Cluster nun funktionierte, wurden die Nodes gesichert. Eine Firewall hatten wir ja bereits. Das heisst, dass wir uns gleich daran machen konnten, einen non-root User zu erstellen, das Login für den root User zu deaktivieren usw.