Kubernetes auf ODROID mit zram
Im Artikel Kubernetes Cluster mit Raspberry Pi wurde ein Cluster-Setup mit Raspberry Pi Computern gezeigt. Als Alternative dazu bieten ODROID-C2 Maschinen doppelt so viel RAM und auch etwas mehr CPU Leistung. Viel wichtiger ist dabei jedoch die deutlich bessere Netzwerkanbindung mit 1Gbit, die auch tatsächlich erreicht werden. Der ODROID unterstützt schnellen eMMC Speicher und UHS-1 SDR50 MicroSD, der preislich deutlich günstiger als die eMMC Module sind. Der ODROID besitzt als Hauptspeicher DDR3 SDRAM Module, die rund doppelt so hoch getaktet sind, wie die LPDDR2 des Raspberry Pi 3. Preislich liegt ein Raspberry Pi 3 bei ca. 36 Euro und ein ODROID C2 bei 58 Euro - je nach Einsatzzweck ist das Preis-Leistungsverhältnis bei dem ODROID deutlich besser. Die ARMv8 Architektur des ODROID C2 wird von Arch Linux und Ubuntu Cloud als 32 und 64 bit Variante unterstützt, Raspian gibt es bisher lediglich als 32 bit Variante.
Ein Nachteil beim 64bit Betrieb ist der etwas höhere Speicherbedarf. Zwar hat der ODROID mit 2GB RAM doppelt so viel Speicher wie der Raspberry Pi, doch für den Betrieb vieler Container kann man nie genug Speicher haben. Hier kann man nun von einem Trick profitieren, der in ähnlicher Form bereits auch von Apple standardmässig eingesetzt wird, um Nutzern auch mit relativ wenig Speicher ein gutes Gesamterlebnis zu bieten.
Der Trick besteht darin, den Hauptspeicher zu komprimieren. Unter Linux existiert dazu das zram-Modul, dass Swap-Speicher komprimiert im normalen RAM ablegt. Doch zunächst zur Einrichtung des ODROID C2 als Server.
ODROID C2 optimal konfigurieren
Der ODROID ist in der Lage 4K Video wiederzugeben. Dazu nutzt die GPU einen Teil des Hauptspeichers, der für Anwendungen nutzbare RAM Anteil verringert sich dadurch um rund 300 MB. Mit der folgenden Konfiguration wird die Grafikkarte deaktiviert und damit der Speicher nach einem Reboot freigegeben. Möchte man KVM als Virtualisierung nutzen, muss der Kernel-Timer umkonfiguriert werden, der standardmäßig den proprietären Timer des SoC-Herstellers verwendet, um optimales Video-Playback sicherzustellen. Dies wird in diesem Schritt direkt mit erledigt.
sed -i 's/setenv nographics "0"/setenv nographics "1"/g' /boot/boot.ini
sed -i 's/setenv mesontimer "1"/setenv mesontimer "0"/g' /boot/boot.ini
Nun kann das zram Modul aktiviert und eine Swap-Partition konfiguriert werden. In vielen Anleitungen ist zu lesen, dass am besten entsprechend der Anzahl CPU-Kerne zram-Partitionen erzeugt werden, um darüber von allen CPU-Kernen bei der De-/Kompression zu profitieren. Aktuelle Kernel erzeugen jedoch bereits pro Partition entsprechend der CPU-Kerne eigene Compression-Streams, sodass eine einzelne Partition ausreicht. Bei der Größe kann man von einem typischen Kompressionsverhältnis von 1:2 ausgehen, sodass eine konservative Einstellung von 2Gb in jedem Fall funktionieren sollte.
echo "zram" > /etc/modules-load.d/zram.conf
echo "options zram num_devices=1" > /etc/modprobe.d/zram.conf
echo 'KERNEL=="zram0", ATTR{disksize}="2G" RUN="/usr/bin/mkswap /dev/zram0", TAG+="systemd"' > /etc/udev/rules.d/99-zram.rules
echo '/dev/zram0 none swap defaults 0' > /etc/fstab
Nach einem Reboot steht der Swapspeicher zur Verfügung:
$ free -m
total used free shared buff/cache available
Mem: 1974 57 1812 0 104 1896
Swap: 2047 0 2047
Kubernetes Konfiguration für zram swap
Kubernetes verweigert - aus guten Gründen - die Arbeit, wenn aktivierter Swap-Speicher erkannt wird. Hintergrund ist dabei das Scheduling, mit dem gerade erzielt werden soll, dass Pods so auf Nodes verteilt werden, dass diese nicht überlastet werden und beginnen, Auslagerungsspeicher zu nutzen. Swap-Speicher befindet sich typischerweise im Sekundärspeicher, Speicherzugriffe wären damit entsprechend Größenordnungen langsamer als Hauptspeicherzugriffe.
Dies Verhalten lässt sich durch den Schalter --fail-swap-on=false
übersteuern.
Typischerweise kann dies in der Konfigurationsdatei für das kubelet Environment in /etc/kubernetes/kubelet
eingestellt werden.
(Das zugehörige systemd unit kann man sich mit systemctl cat kubelet
ansehen.)
KUBELET_ARGS="--cgroup-driver=systemd --fail-swap-on=false"
Anschließend wird der kubelet Dienst aktiviert und der Kubernetes Cluster kann eingerichtet werden.
Wenn kubeadm verwendet wird, so muss hier noch durch den Schalter --ignore-preflight-errors Swap
der Check auf aktivierten Swap-Space deaktiviert werden.
$ systemctl enable kubelet.service
$ sudo kubeadm init --token-ttl=0 --ignore-preflight-errors Swap
I0722 19:08:34.134832 17333 feature_gate.go:230] feature gates: &{map[]}
[init] using Kubernetes version: v1.11.1
[preflight] running pre-flight checks
[WARNING Swap]: running with swap on is not supported. Please disable swap
I0722 19:08:34.219972 17333 kernel_validator.go:81] Validating kernel version
I0722 19:08:34.220318 17333 kernel_validator.go:96] Validating kernel config
[preflight/images] Pulling images required for setting up a Kubernetes cluster
[preflight/images] This might take a minute or two, depending on the speed of your internet connection
[preflight/images] You can also perform this action in beforehand using 'kubeadm config images pull'
...
Die weitere Einrichtung des Kubernetes Clusters erfolgt dann wie gewohnt.
Zu den Themen Kubernetes, Docker und Cloud Architektur bieten wir sowohl Beratung, Entwicklungsunterstützung als auch passende Schulungen an:
Auch für Ihren individuellen Bedarf können wir Workshops und Schulungen anbieten. Sprechen Sie uns gerne an.