Kubernetes ist in aller Munde, doch hat sich die Lösung längst weit von ihren einst einfachen Ursprüngen entfernt und ist zu einem hyperkomplexen Konstrukt geworden. Acorn verspricht, das Deployment von Anwendungen in Kubernetes dennoch in Sekundenschnelle zu ermöglichen.
Wer sich in der hippen Welt der Cloud-Readiness bis heute noch immer nicht zurechtgefunden hat, erntet insbesondere von der jüngeren IT-Generation oft nur mitleidige Blicke. Dass gerade die jüngeren Vertreter der Branche erst noch lernen müssen, dass neu nicht automatisch dasselbe ist wie gut, sei dahingestellt. Fakt ist, dass – wie einst das Cloud-Prinzip selbst – das darauf aufbauende Prinzip der Cloud-bereiten Anwendungen der Industrie eine ganze Weile erhalten bleiben dürfte. Distributoren wie Red Hat und Suse arbeiten längst daran, ihre großen Enterprise-Distributionen in Container-Laufzeitumgebungen zu verwandeln, um einen großen Teil der Mühsal mit der Paketwartung an die Hersteller der jeweiligen Programme auszulagern. Und auch sonst gilt vielerorts mittlerweile die Devise “Kubernetes first”: Infrastructure as Code und CI/CD-Pipelines mit allerlei Automatismen inklusive impliziter Fehlerkorrektur sind Attraktivitätsfaktoren, die bei konventionellen Deployment-Modellen schlicht fehlen.
Für manche Admins wird die Gewöhnung an die neue Welt mit Containern und Flottenverwaltern allerdings schnell zum Albtraum. Zwar versprechen Kubernetes und die Container-Lobby, dass mit ihnen alles viel einfacher und leichter handhabbar wird. Wer dann jedoch zum ersten Mal Kubernetes aufsetzt und irgendeine Konfiguration braucht, die in den Standardeinstellungen der jeweiligen K8s-Distribution nicht vorgesehen ist, steht schnell wie der sprichwörtliche Ochse vor dem Berg (Abbildung 1). Dasselbe gilt für das Ausrollen von Apps in Kubernetes selbst: Wer sich schon einmal mit Custom Resource Definitions (CRDs), Operatoren von Drittherstellern und den diversen Storage- und Netzwerkmethoden von Kubernetes befassen durfte, verliert schnell den Glauben daran, dass der Dienst wirklich irgendetwas leichter macht. Zumal das Format, in dem Kubernetes per Kubectl Ressourcendefinitionen entgegennimmt, auch nicht sonderlich intuitiv oder einfach zu durchdringen ist. Statt Container-Lust stellt sich bei vielen Administratoren nach den ersten K8s-Gehversuchen schnell Container-Frust ein, und zwar aus gut nachvollziehbaren Gründen.

Abbildung 1: Kubernetes ist zwar mächtig, aber auch mächtig komplex: Die Summe der verschiedenen Technologien und Funktionen, die sich um K8s gebildet haben, lässt vor allem Einsteiger ratlos zurück. Quelle: CNCF
Hier tritt Acorn auf den Plan: Das Werkzeug verspricht, sich als Schicht zwischen Kubernetes und Anwender zu legen und viel der Komplexität von Kubernetes durch sinnvolle Defaults zu ersetzen, sodass der Admin gar nicht mehr die volle Komplexität des Container-Flottenverwalters abbekommt. Innerhalb kürzester Zeit sollen Administratoren so zu Erfolgserlebnissen kommen, etwa zu einer laufenden Nginx-Instanz, deren Start insgesamt keine Minute dauert. Dazu bringt Acorn eine Art eigenes Build-System mit, unterstützt aber auch spezielle Container und das Anbinden an externe Werkzeuge. Mit den üblichen Buzzwords wie “secure by design” geizen die Entwickler der Lösung selbstverständlich ebenfalls nicht. Da stellt sich schnell die Frage: Ist Acorn wirklich der Stein der Weisen in Sachen Kubernetes-Usability, oder verspricht das Marketing-Material zum Produkt mehr als die Software selbst hält? Dieser Artikel stellt Acorn im Detail vor und fühlt der Lösung auf den Zahn.
Packaging und Deployment
“Etwas wirklich zu wissen bedeutet, die Gründe dafür zu kennen”, postulierte schon Francis Bacon, und im Kontext von Acorn bewahrheitet sich diese Erkenntnis einmal mehr. Denn um Acorn zu verstehen, empfiehlt es sich, das Blabla der Marketing-Abteilung auszublenden und sich zunächst mit der Frage zu beschäftigen, was Acorn eigentlich sein will. Daraus ergibt sich nämlich bereits, was Endanwender und Administratoren von der Software erwarten dürfen und was nicht. In der eigenen Dokumentation beschreibt Acorn sich als Werkzeug zum Paketieren und zum Deployment von Anwendungen, das die Aufgabe signifikant erleichtern will, Apps auf K8s zu betreiben. Wie das im Detail funktionieren soll, zeigt ein Blick hinter die Kulissen.
Hier tut Acorn etwas, das im ersten Augenblick eigentlich den Zielen des Tools diametral entgegenzulaufen scheint: Es fügt eine zusätzliche Schicht der Abstraktion hinzu, also mehr Komplexität. In genau dieser Schicht befindet sich aber die Secret Sauce der Lösung: Acorn erfindet hier quasi eine Art neue Deklarationssprache, die deutlich intuitiver zu benutzen sein soll als die von Kubernetes selbst. Anhand eines Beispiels lässt sich das gut nachvollziehen. Listing 1 enthält ein Acornfile (in Analogie zum Dockerfile), das einen Nginx-Container mit einer einfachen »index.html« startet.
Listing 1
Einfaches Acornfile
containers: {
web: {
image: "nginx"
ports: publish: "80/http"
files: {
// Simple index.html file
"/usr/share/nginx/html/index.html": "<h1>My First Acorn!</h1>"
}
}
}
Der entstehende Container heißt in Kubernetes im Anschluss »web« und lässt sich über den Port 80 erreichen. Er enthält eine veränderte Datei, nämlich jene in »/usr/share/«, und legt deren Inhalt als »<h1>My First Acorn!</h1>« fest. Steuert man im Anschluss die IP-Adresse des Containers auf Port 80 an, erwartet einen dort tatsächlich der beschriebene Willkommensgruß.
Was schnell auffällt: Um den Container wie beschrieben zu starten, genügt es, das Acornfile in einem Ordner zu haben und darin »acorn build .« aufzurufen. Der Rest passiert im Hintergrund automatisch. Das bedeutet freilich auch, dass sich Definitionen für virtuelle Infrastruktur in Acorn hervorragend in Git verwalten lassen. Damit gehört die Lösung auch zu jenen, die Infrastructure as Code ermöglichen und das relativ leicht umzusetzen erlauben.
Vorbereitung ist nötig
Geübte Kubernetes-Nutzer fragen sich an dieser Stelle möglicherweise, woher Acorn denn überhaupt weiß, mit welchem Kubernetes-Cluster es sprechen soll und woher es die Login-Daten dafür bekommt. Dafür existiert ein eigener Arbeitsschritt, den es vor dem ersten Build-Befehl aufzurufen gilt: »acorn install«. Damit der Befehl funktioniert, muss der ihn ausführende Nutzer mit den Rechten eines Kubernetes-Administrators in der RBAC von Kubernetes ausgestattet sein. Diese Rechte müssen zudem per Umgebungsvariable in der aktuellen Kommandozeilensitzung verfügbar sein. Grundsätzlich gilt es, für den Aufruf von »acorn« dieselben Vorkehrungen zu treffen wie für den Aufruf von »kubectl« an derselben Stelle. Ist diese Bedingung erfüllt, erstellt Acorn nach dem Aufruf des Install-Kommandos seine in K8s benötigten Ressourcen und lässt sich im Anschluss wie beschrieben benutzen.
Das setzt allerdings voraus, dass der verwendete Kubernetes-Cluster zwei Bedingungen erfüllt. Zunächst ist die Implementierung von persistentem Storage in Acorn ausgesprochen rudimentär. Das Programm verlässt sich darauf, dass Kubernetes ihm persistente Volumes zur Verfügung stellt, wenn es solche anfragt. Damit das funktioniert, muss in Kubernetes jedoch eine Default-Storage-Klasse definiert sein, denn sonst liefe ein Acorn-Request ins Leere. Die meisten handelsüblichen Kubernetes-Distributionen definieren eine Standard-Storage-Klasse, sodass es hier zu keinen Problemen kommt. Schlägt ein »acorn build« aber wegen eines Storage-Fehlers fehl, ist die Wahrscheinlichkeit hoch, dass das an der fehlenden Standardklasse für Volumes liegt.
Die zweite Bedingung ist nicht ganz so strikt wie die erste, denn auch ohne sie lässt sich theoretisch ein Acorn-Container in Kubernetes betreiben. Praktisch ist das aber nicht sehr sinnvoll, denn die in Acorn veröffentlichten Dienste sind dann von außen nicht zu erreichen. Damit Acorn Dienste als Endpunkt direkt durch die Kubernetes-API hin zur Außenwelt exponieren kann, muss mindestens ein Ingress-Controller definiert sein, den Acorn für die entsprechende Definition des Diensts verwenden kann. Obendrein muss dieser Ingress-Controller sämtlichen Anforderungen genügen, um Ressourcen des Typs »LoadBalancer« für Nicht-HTTP-Endpunkte anzulegen.
Was in der Theorie ziemlich sperrig klingt, ist in der Praxis üblicherweise kein Problem: Auch hier gilt, dass beinahe alle am Markt etablierten Kubernetes-Distributionen die nötigen Voraussetzungen mitbringen. In ihrer Dokumentation listen die Acorn-Entwickler verschiedene Kubernetes-Distributionen auf und geben Hinweise, inwiefern die Konfiguration ab Werk zu verändern ist, damit Acorn reibungslos funktioniert [1].
TLS-Unterstützung ab Werk
Das zuvor gezeigte Beispiel mit der simplen HTML-Datei ist freilich kein sehr praxisnahes Beispiel für Workloads, wie Administratoren sie üblicherweise in Kubernetes betreiben. Und selbst dieses banale Beispiel enthält bereits ein Problem, das vor allem jenen sofort aufgefallen sein dürfte, die für das Thema Security verantwortlich zeichnen: Es öffnet den HTTP-Port 80 und liefert Seiten unverschlüsselt aus. Für das rudimentäre Beispiel ist das kein Problem, aber in der Realität ist es heute bei den allermeisten Web-basierten Diensten absolute Pflicht, Verschlüsselung zu benutzen.
Die indes ist in Kubernetes gar nicht so leicht einzubinden. Entweder legt man die SSL-Schlüssel und Zertifikate im Versionskontrollsystem ab und muss sich dann mit Speicherlösungen für Passwörter und Geheimnisse herumschlagen und diese irgendwie in den CI/CD-Prozess einbauen, oder man entscheidet sich für die – mittlerweile vielerorts favorisierte – Lösung auf Basis von Let’s Encrypt. Deren korrekte Umsetzung in Kubernetes mag für einen Profi kein Hindernis darstellen. Wer mit den Abläufen und Diensttypen in Kubernetes aber noch nicht ganz so vertraut ist, kann an dieser Stelle schon mal verzweifeln.
Acorn bietet hier eine erste echte Machtdemonstration. Gibt der Administrator anstelle von »acorn install« eingangs das Kommando aus Listing 2 ein, installiert Acorn sämtliche für Let’s Encrypt benötigten Dienste gleich mit in den Ziel-Cluster. Rollt man im Anschluss eine Anwendung per Acorn aus, genügt es, im Acornfile den Endpunkt der Anwendung auf »443/https« zu ändern. Acorn generiert dann beim Deployment nicht nur einen dynamischen Host-Namen auf Basis der im Cluster voreingestellten Domäne, sondern gleich auch das passende SSL-Zertifikat dazu, das Acorn im Load Balancer für den Ingress-Treiber direkt auch noch passend hinterlegt (Abbildung 2). In Summe dürfte Acorn damit zu den Lösungen gehören, die Entwicklern den schnellsten Weg hin zu einem technisch korrekten, dynamisch verschlüsselten Endpunkt in Kubernetes ebnen.
Listing 2
Verschlüsselung
# acorn install \ --lets-encrypt enabled \ --lets-encrypt-tos-agree=true \ --lets-encrypt-email Adresse
Abbildung 2: Acorn verbindet einfache und komplexe Kubernetes-Funktionen und hat manches Knaller-Feature im Gepäck. Dazu gehört die komplett automatische Integration von Let’s Encrypt.
Acorn-Abbilder sind speziell
An dieser Stelle darf ein kleiner Exkurs zu den Acorn-Abbildern nicht fehlen, denn diese sind durchaus speziell. Formal handelt es sich um reguläre und standardkonforme Docker-Abbilder. Entsprechend lassen Acorn-Abbilder sich auch beim Docker-Hub hochladen oder bei jeder anderen Container-Registry, die die OCI-Spezifikation für Container-Abbilder unterstützt.
Im Gegensatz zu reinen Docker-Abbildern enthalten Acorn-Images in ihren Metadaten und im Overlay zum Basis-Image aber deutlich mehr Informationen und Material. Im Grundsatz ist die Anforderung an einen Acorn-Container nämlich stets, dass er ausnahmslos alle für den Betrieb einer Applikation benötigten Komponenten enthält. Aus diesem Grund lassen sich existierende Images auch nicht problemlos mit Acorn nutzen: Acorn versteht sich wie beschrieben als eine Anwendung, die das Image mitsamt der Applikation als ein Quasi-Paket in Form eines Containers nutzt.
Das bedeutet allerdings nicht, dass sich die Standard-Abbilder der großen Hersteller nicht zumindest als Grundlage für eigene Abbilder in Acorn verwenden lassen. Der Prozess, von einem vorgefertigten Image zu einem eigenen Image mit passender Konfiguration zu kommen, ist dabei unkompliziert.
Das eigene Abbild
An der Art und Weise, wie ein Acorn-Abbild entsteht, lässt sich die Funktion von Acorn im Detail gut nachvollziehen. Ihren Anfang nimmt die Entwicklung stets mit einem leeren Verzeichnis. In diesen Ordner kopiert der Entwickler zunächst die Dateien eigener Provenienz, die später im Container vorhanden sein sollen. Hier sind der Fantasie keine Grenzen gesetzt. Wenn das Docker-Basisabbild, das später zum Einsatz kommt, Debian oder Ubuntu als Basis nutzt, könnte hier etwa auch ein DEB-Paket liegen, das in den Container installiert werden soll.
Im Grunde legt sich das Acorn-Container-Format um bestehende Docker-Container herum wie ein Kokon. Das kommt auch dadurch zum Ausdruck, dass innerhalb des Arbeitsordners für das neue Acorn-Abbild ein ganz normales Dockerfile vorhanden sein muss (Abbildung 3), das allen formalen Ansprüchen genügen muss. Per »FROM«-Direktive ist hier etwa festzulegen, welches Basisabbild zum Beispiel vom Docker Hub zum Einsatz kommen soll. Dateien, die im Arbeitsordner des neuen Acorn-Abbilds liegen, fügt man mittels »ADD« hinzu. Sämtliche Details für die Konstruktion von Docker-Containern finden sich in etlichen Anleitungen überall im Netz [2]. Ist das Dockerfile entsprechend vorbereitet, geht es mit dem Acornfile weiter.

Abbildung 3: Ohne Dockerfile bringt ein Acornfile nichts: Den eigenen, lokalen Container baut Acorn mittels »docker build«. Dafür muss eine Datei namens »Dockerfile« vorliegen und syntaktisch korrekt sein.
Hier übernimmt nun die lose auf CUE aufbauende Syntax von Acorn. Sie erinnert entfernt an JSON oder YAML und ist glücklicherweise nicht sonderlich schwer zu erlernen. Das Acornfile teilt sich in mehrere Blöcke auf, über die die Acorn-Dokumentation wiederum detailliert Auskunft gibt [3]. Ein eigener Block namens »args« ermöglicht es beispielsweise, Variablen zu definieren, deren Inhalt Acorn dann später beim Zugriff auf die Variable automatisch substituiert. Der wichtigste Abschnitt ist aber der »containers«-Abschnitt. Er legt einerseits die Parameter des von Acorn selbst zu bauenden Anwendungs-Containers fest, listet zugleich aber auch noch andere Container auf, die gegebenenfalls Teil des Deployments sein sollen. Der App mit der Bezeichnung »app« kommt dabei die Schlüsselrolle zu, denn das ist der direkte Verweis auf die lokale App, die Acorn in einen Container verpacken soll. Wenn ein Dockerfile existiert, sorgt die Anweisung »build: “.”« innerhalb des »app«-Abschnitts dafür, dass Acorn den Build-Prozess auch wirklich anstößt.
Die Möglichkeit, weitere Container gleich mitzukonfigurieren, sollte der Admin dabei keinesfalls unterschätzen. Benötigt die App im Container beispielsweise PostgreSQL als Datenbank, lässt sich direkt aus dem Acornfile heraus ein passender Container (»postgres:alpine«) starten und mit den passenden Parametern für den späteren Betrieb versehen. Das umfasst in den meisten Fällen zumindest den Port, der per »ports«-Anweisung definiert wird, wie im Beispiel aus Listing 1 gezeigt.
Sollen von Herstellern fertig gelieferte Container um lokale Dateien ergänzt werden, klappt das in der Definition des jeweiligen Containers mittels der »files«-Direktive. Über den Parameter »dirs« lassen sich zudem Ordnern innerhalb des Containers Volumes zuweisen. Damit das funktioniert, muss das Acornfile außerhalb des »containers«-Abschnittes aber auch noch einen »volumes«-Abschnitt mit der passenden Volume-Definition umfassen. Sonst legt Acorn beim Deployment in Kubernetes das referenzierte Volume nicht an, und die Referenz läuft ins Leere.
Besonders elegant: Wer ein Passwort im Container braucht, kann es mittels der »secrets«-Direktive in Acorn automatisch anlegen und in Kubernetes hinterlegen lassen. Per K8s-API lässt sich das Passwort später notfalls auch anzeigen. Das sollte allerdings nur in den seltensten Fällen notwendig sein. So oder so verhindert Acorn hier die endlose Verwendung desselben Passworts, indem es kein Standard-Passwort akzeptiert, sondern dynamisch eines anlegt und als Parameter für die Anwendungen in den Containern nutzbar macht. Referenzen zwischen festlegten Werten wie Argumenten und Passwörtern und anderen Direktiven sind in Acorn ausdrücklich vorgesehen. Auf das definierte Passwort »pg-pass« könnte man anderswo im Acornfile etwa mit »secret://pg-pass/token« zugreifen.
Weiter geht es dann entweder mit dem Kommando »acorn run -n acorn-test .«, was in Kubernetes einen Container namens »lm-test« mit den Inhalten des lokalen Verzeichnisses anlegt. Oder der Entwickler entscheidet sich dafür, aus seiner Anwendung ein richtiges Abbild zu machen, das sich verteilen lässt: Nach »acorn login Host-Name« zum Login bei einer Container-Registry und »acorn build -t Host-Name/Label/Tag .« erledigt »acorn push Host-Name/Label/Tag« diesen Schritt.
Wichtig: »Host-Name« ist durch den Hostnamen der Docker-Registry zu ersetzen, »Label« durch ein eindeutiges Identifikationsmerkmal (etwa »lm-test«) und »Tag« durch eine valide Versionsnummer wie »v0.1«. Hat der Push geklappt, lässt das Image sich in jedem beliebigen Kubernetes-Cluster mittels »acorn run -n lm-test Host-Name/Label/Tag« starten und nutzen.
Infrastructure as Code
Eine der großen Stärken Acorns ist sicherlich, die gesamte Infrastruktur einer virtuellen Container-Umgebung in Kubernetes in einfacher Template-Sprache zu verfassen. Da liegt es auf der Hand, diesen Vorteil für echtes Infrastructure as Code zu verwenden.
Die Idee: Die Entwicklung von Containern für Acorn findet in einem Git-Verzeichnis statt, das zugleich als klassische Versionskontrolle dient. Dienste wie Gitlab oder Github unterstützen allesamt die Verwendung von Hooks, also das Auslösen von Aktionen als Reaktion auf bestimmte Ereignisse. Ein »push«-Befehl in ein von Git verwaltetes Verzeichnis zum Bau von Acorn-Containern kann so ein Ereignis sein. In der eigenen Doku beschreiben die Entwickler im Detail, wie sich Hooks in Github nutzen lassen, um bei jeder Veränderung der Dateien im Ordner ein neues Image mit neuer Version anzulegen und in eine Container-Registry hochzuladen.
Davon profitieren gerade jene Umgebungen, die Acorn in großem Stil nutzen und Container auf vielen verschiedenen Kubernetes-Plattformen ausrollen wollen: Der Automatismus stellt sicher, dass unmittelbar nach einem Git-Commit das aktuellste Image überall in der Umgebung zur Verfügung steht.
Features für Fortgeschrittene
Die bis hierhin beschriebenen Acorn-Fähigkeiten beziehen sich eher auf die grundlegenden Eigenschaften von Containern. Das bedeutet aber nicht, dass komplexere Setups und Container-Umgebungen mit Acorn unmöglich wären. Dessen Autoren gehen offensichtlich davon aus, dass sich beim Administrator nach einer Weile der Arbeit mit Acorn bessere Fähigkeiten einstellen und der Wunsch nach der Nutzung von fortgeschrittenen Features aufkommt.
Diesem Umstand trägt Acorn durchaus Rechnung, indem es verschiedene komplizierte Kubernetes-Funktionen unterstützt. Dabei gelingt den Entwicklern jederzeit das Kunststück, Acorn nicht einfach zur Konfigurationsschaufel zu machen, also zu einem Werkzeug, das Konfigurationsdirektiven einfach von einer Syntax in eine andere überträgt, ohne dabei die Komplexität zu reduzieren. Im Gegenteil: Auch bei komplexen Aufgaben und Konfigurationen innerhalb des Acornfile dürfen Autoren stets darauf vertrauen, dass diese von Docker her bekannt sind.
Funktioniert eine Acorn-App zum Beispiel nicht so, wie der Administrator es erwartet, lassen sich deren Log-Dateien mittels »acorn logs« anzeigen. Per »acorn exec« kann man in den laufenden Containern einer Acorn-App direkte Befehle ausführen. Mittels »acorn update« ist es sogar möglich, die Container eines laufenden Stacks auszutauschen, falls eine neue Variante des Applikations-Containers zur Verfügung steht.
Abbildung 4: Das CLI-Werkzeug »acorn« entpuppt sich als nützlicher Tausendsassa. Es vereint unter einer Haube Funktionen von »kubectl« und »docker«, bezieht sich dabei jedoch stets auf per Acorn ausgerollte Apps.
Fazit: Solide Arbeit
Acorn gehört zu jenen Werkzeugen, die am Anfang etwas wirr wirken, die man als Entwickler oder Administrator aber sehr schnell zu schätzen lernt. Wer nicht seit Jahren Kubernetes nutzt und als eingefleischter Kubernaut gilt, ist mit der technischen Komplexität des Betriebs von Anwendungen unter Kubernetes anfangs oft komplett überfordert. Acorn eilt hier zu Hilfe und schafft es tatsächlich, einen erheblichen Teil der Komplexität von Kubernetes vor dem Endanwender zu verstecken. Zugleich gelingt Acorn das Kunststück, auch komplexere Kubernetes-Funktionen zu nutzen, ohne dabei so komplex und kompliziert zu werden wie Kubernetes selbst.
Damit richtet sich das Werkzeug an erfahrene Kubernetes-Administratoren ebenso wie an jene, die sich in Kubernetes erst noch zurechtfinden müssen: Gut möglich, dass beide von den Fähigkeiten Acorns profitieren. Vorrangig ist Acorn aber ein Signal an die, die möglicherweise bereits einen Kubernetes-Versuch hinter sich haben und dabei auf die Nase gefallen sind. Zwar ist bei der Nutzung von Acorn K8s nicht weniger komplex, aber der Benutzer sieht sich anfänglich wesentlich geringerer Komplexität gegenüber (Abbildung 5). Wer also den (Wieder-)Einstieg in Kubernetes wagen möchte, sollte sich Acorn unbedingt genauer anschauen. (jcb)

Abbildung 5: Die Vogelperspektive auf die Acorn-Architektur macht klar: Das Programm will den Anwender vor Komplexität schützen und fungiert zu diesem Zweck als Proxy zwischen K8s und Nutzer. Quelle: Acorn
Infos
- Kubernetes-Distributionen und Acorn: https://docs.acorn.io/installation/installing
- Docker: Hans-Georg Eßer, “Sauber angedockt”, LU 12/2022, S. 70, https://www.linux-community.de/47282
- Acornfiles schreiben: https://docs.acorn.io/authoring/overview






