Allgemein Balena - OTH-AW/isac-oth-aw GitHub Wiki
Balena ist ein Unternehmen, dass sich auf die Entwicklung von Lösungen für die Unterstützung von Docker entsprechenden Endgeräten spezialisiert hat. Wichtig für uns war vor allem die native 64-Bit Unterstützung des Raspberry Pi 4. Dadurch war ist es uns um einiges einfacher, Docker-Container auf den Endgeräten zu verteilen.
Hier eine kurze Liste an für uns interessanten Balena-Tools:
- Balena-Etcher
- BalenaOS
- BalenaEngine
- BalenaCloud
Der aus Balena optimal bevorzugte Workflow sieht hierbei wie folgt aus:
- Einrichten der Endgeräte mit Balena-Etcher (Flashen des vorkonfigurierten Betriebssystems BalenaOS)
- Push der aktuellen Version auf die BalenaCloud (Damit werden die entwickelten Docker-Images auf die Endgeräte verteilt)
- Auf den Endgeräten wird dann im BalenaOS mit der BalenaEngine (Ein Docker Fork)
Siehe:
Für uns war die Entwicklung mit einer 64 Bit Version ein wichtiges Anliegen. Unsere Endgeräte (Raspberry Pi 4) unterstützen das hardwaremäßig. Wir hatten aber mehrere Probleme bei der Verwendung des offiziellen OS Raspbian. Unser ursprüngliches Ziel war die Konfiguration von Docker und Git auf den Geräten, um manuell die aktuellen Versionen pullen und dann mit Docker ausführen zu können. Dazu mussten außerdem diverse Berechtigungen für die SSH-Konfigurationen angelegt werden zusätzlich zu der Tatsache, dass Raspbian standartmäßig relativ viele Resources im Leerlauf im Vergleich zu BalenaOS benötigt.
Ziel ist es unter anderem, ein System zu konfigurieren, dass 64-Bit Images für Docker ausführen kann. Da wir auf dem Raspberry Pi 4 eine arm64v8 bzw. aarch64 Bit Version vorliegen haben, müsste dies grundsätzlich funktionieren. Das Problem hierbei: Das Betriebssystem Raspbian unterstützt zwar grundsätzlich einen 64 Bit Kernel, bietet aber noch keinen 64 Bit Userspace dafür an. Das hat zur Folge, dass Docker nur im 32 Bit Modus ausgeführt werden kann.
Ein weiteres Ziel ist es außerdem, auf den Entwicklermaschinen Änderungen am Code ausführen zu können, ohne dass man sich zu viele Gedanken über die Architektur auf dem Raspberry Pi 4 machen muss. Deshalb hatte sich Docker grundsätzlich überhaupt erst angeboten. Die Entwicklung soll mindestens unter Windows 10 und MacOS möglich sein.
Bei den Docker-Images werden oft verschiedene Kürzel für die CPU-Architekturen verwendet.
- i386: Kommt vom Intel 80386, steht für eine 32-Bit Edition
- amd64: Ist auch bekannt als **x86_64 **oder x64, erweitert einfach den Befehlssatz vom i386, ist die 64-Bit Edition. Die älteren Befehlssätze funktionieren trotzdem noch.
i386 und amd64/x86_64/x64 sind Bezeichnungen jeweils für Intel/AMD CPUs, das sind nur andere Namen.
Also selbst wenn man eine Intel CPU (mit 64 Bit Unterstützung) hat, sollte man, wenn man etwas installieren möchte, aber nur die Auswahl zwischen i386 und amd64 hat, amd64 wählen.
Jetzt haben wir aber natürlich das "Problem", dass wir einen Raspberry Pi 4 verwenden. Der hat als CPU einen ARM Cortex-A72 verbaut. Dieser hat einen anderen Befehlssatz: ARMv8 64-bit, mit Abwärtskompatibilität zu: ARMv7 (32-bit)
Wenn man diese Erläuterungen jetzt mit Docker kombiniert:
Es gibt einen Doku-Eintrag von Docker: (Multi-CPU Architecture): Docker bietet unter Mac ("Docker for Mac VM") die Möglichkeit, arm32v7 über den Emulator QEMU (qemu-static) auszuführen. Deshalb klappt das auch unter Windows, da das alles über QEMU zu laufen scheint.
Das heißt, dass wenn es ein Image gibt, dass für ARMv8 und amd64/i386 konfiguriert wurde, auf dem PI die v8 und auf unseren Entwicklungsmaschinen amd64/i386 verwendet wird und somit ohne weitere Probleme ausgeführt werden kann.
Das ist zum Beispiel bei der MongoDB der Fall: https://hub.docker.com/_/mongo?tab=tags
Nur wenn man ein Image verwendet, dass amd64 und ARMv8 unterstützt, kann der reibungslose Ablauf garantiert werden.
Bei uns zum Beispiel: Node-Server mit Erweiterungen, Opcua-Server, Jupyter_kernel_gateway-Server
Wenn es kein vorgefertigtes Image für amd64 und ARMv8 gibt, muss man sich ein eigenes Image mit den gewünschten Programmen erstellen. Man kann sich hierbei grundsätzlich als Basis-Image jedes auswählen. Empfohlen wird aber natürlich ein kleines, schlankes Image. Hier sind wir das erste Mal auf Balena gestoßen. Balena bietet eine zahlreiche Menge an Basis-Images in verschiedensten Konfigurationen an.
Siehe:
- https://www.balena.io/docs/reference/base-images/base-images/
- https://www.balena.io/docs/reference/base-images/base-images-ref/
Für unsere API basierend auf jupyter_kernel_gateway verwenden wir zum Beispiel folgendes Basis-Image mit der folgenden Konfiguration zur Installation des gateways:
FROM balenalib/raspberrypi4-64-python:3.7.6-buster
RUN install_packages tini libblas-dev liblapack-dev libatlas-base-dev gfortran pkg-config python3-pandas python3-numpy python3-pymongo python3-ipykernel jupyter jupyter-notebook
RUN pip install --no-cache-dir jupyter_kernel_gateway
COPY . /home/isac/
# Configure container startup, letting the user pass command line args through
# easily without disrupting the use of tini or the kernelgateway entry point by adding
# those commands with CMD for example by docker-compose.yml
ENTRYPOINT ["tini", "--"]
Mit diesem neuem Image kann man unsere API basierend auf dem jupyter_kernel_gateway sowie unsere erstellten Analysen in den Jupyter-Notebooks hosten. Die Entwicklung dieser ist Host-unabhängig und ist lauffähig auf Windows, MacOS und dem Raspberry Pi 4.