Aus Linux-Magazin 02/2016

Container mit Systemd

© chuyu, 123RF

Ursprünglich als Tool für Systemd-Tester gedacht, mausert sich Systemd-nspawn zu einer eigenständigen Containerlösung. Bei Rkt von Core OS ist es bereits als Low-Level-Tool im Einsatz. Rkt-Entwickler Jonathan Boulle stellt Systemd-nspawn vor.

Dank Systemd-nspawn [1], einem schlanken Containertool im Systemd-Ökosystem, laufen einzelne Befehle, umfangreiche Dienste oder gar komplette Betriebssysteme in einer abgekapselten Umgebung unter Linux. Anfangs diente das Tool den Systemd-Entwicklern eigentlich nur dazu, Systemd [2] selbst zu bauen und zu betreiben, ohne damit dem Hostsystem in die Quere zu kommen, auf dem sie arbeiteten.

Seitdem hat es sich jedoch weiterentwickelt und schließt inzwischen eine Reihe von Funktionen ein, die von einer fortgeschrittenen Netzwerkkonfigurationen über eine SE-Linux-Integration bis hin zur Unterstützung für ein natives Overlay-Dateisystem reichen. Das aktuelle Systemd-nspawn ist also ein vielseitiges und funktionsreiches Tool und deckt eine ganze Palette verschiedener Einsatzszenarien für den Betrieb von Anwendungen unter Linux ab.

Um näher herauszufinden, was Systemd-nspawn ausmacht, lohnt es sich, Bekanntschaft mit einigen der mit ihm verwandten Tools zu machen.

Chroot

Chroot [3] bietet einen der ältesten und einfachsten Wege, um einen bestimmten Grad an Prozess-Isolation auf Linux zu erreichen. Der »chroot« -Systemaufruf erlaubt es dem aufrufenden Prozess, in eine isolierte Dateisystem-Umgebung zu wechseln. Ab diesem Punkt betrachtet Linux jede Referenz auf einen Pfad im Dateisystem, den die Anwendung geht, als relativ zu ihrem Chroot-Verzeichnis. Ein Beispiel für dieses Verhalten wäre:

chroot /home/redaktion/images/jessie/ /bin/ls

Der zweite Teil der Zeile versucht dank des ersten, den Befehl »ls« in der Chroot-Umgebung auszuführen (Abbildung 1). Das neue Wurzelverzeichnis befindet sich dann auf dem Host unter »/home/redaktion/images/jessie/« . Nach dem Einsatz des »chroot« -Befehls sieht der Prozess auf dem Host allerdings keine Dateien außerhalb von »/home/redaktion/images/jessie/« mehr.

Abbildung 1: Eine Chroot-Umgebung bietet eine einfache, wenn auch unsichere Form der Isolation.

Abbildung 1: Eine Chroot-Umgebung bietet eine einfache, wenn auch unsichere Form der Isolation.

Letztlich verändert »chroot« lediglich den Mechanismus, den Linux verwendet, um Pfadnamen aufzulösen. Das tut es, sobald ein Prozess versucht auf das Dateisystem zuzugreifen. Damit gewährt Chroot zwar einen rudimentären Level an Isolation auf Dateisystemebene, der aber lässt sich unglücklicherweise recht einfach brechen.

Es gibt mehrere Wege, aus dem Chroot zu entkommen, etwa indem ein Prozess bereits vor seinem Aufruf per File Descriptor auf eine Datei außerhalb des Chroot verweist. Daher lässt sich diese Form der Isolation nicht als sicherer Mechanismus bezeichnen. Des Weiteren fehlen Chroot fortgeschrittene Möglichkeiten der Prozess-Isolation, die für Linux wünschenswert erscheinen, wenn es zum Beispiel um die Speichernutzung oder die Netzwerkschnittstellen geht.

Besser isoliert

Glücklicherweise haben in den letzten fünf Jahren einige ausgefeiltere Containment-Tools die Bühne betreten, zu denen neben Systemd-nspawn auch Docker [4] und das von uns entwickelte Rkt [5] gehören. Sie nutzen spezielle Kernelfeatures, um eine bessere Isolation zwischen den Prozessen des Systems zu erreichen. Während aber Docker und Rkt auf eine Nutzergruppe abzielen, die vorwiegend Anwendungen in Containern laufen lassen möchte, handelt es sich bei Systemd-nspawn eher um ein Low-Level-Tool, das sich an Entwickler richtet.

Rkt

Rkt heißt die von uns entwickelte Laufzeitumgebung für Anwendungs-Container, sie implementiert die App-Container-Spezifikation (Appc, [6]). Diese definiert, aus welchen Komponenten ein Container-Image bestehen sollte und welche Anforderungen erfüllt sein müssen, um Anwendungen in einem Container zu betreiben.

Intern setzt Rkt auf eine abgestufte Architektur und betreibt Container im Drei-Stufen-Modell. Die Rkt-Kommandozeile bildet die erste Stufe (Stage 0). Sie spürt Application Container Images (ACI) im Internet oder in Repositories auf, lädt sie per HTTP oder Bittorrent herunter, verifiziert ihre GPG-Signaturen und verwaltet den lokalen Festplattencache.

In der zweiten Stufe (Stage 1) setzt Rkt die isolierte Umgebung auf, indem es die nötigen Kernelfeatures verwendet, um die Anwendungen vom Host zu isolieren. Die dritte Stufe (Stage 2) betrifft schließlich die vom User spezifizierte Anwendung selbst. Im Fall von Rkt dürfen das eine oder mehrere Anwendungen sein, weil die das Fundament bildende ausführende Einheit, der Pod, per Definition aus einer oder mehreren Anwendungen bestehen darf.

Die von Core OS ausgelieferte Rkt-Version überlässt in Stage 1 standardmäßig Systemd-nspawn den Hauptteil beim Einrichten der Container. Aktuell gibt es noch eine weitere Stage-1-Variante, die Kvmtool [7] für diese Dienste einspannt. Das setzt eine schlanke virtuelle Maschine auf, die den KVM-Treiber des Kernels sowie dessen Hardware-Isolation verwendet. Wer Rkt in diesem Modus betreibt, braucht Systemd-nspawn nicht. Weil die Systemd-nspawn-Variante aber für vorhersehbare Zeit der Standard bleiben soll, arbeiten die Rkt-Entwickler eng mit dem Systemd-Projekt zusammen.

Docker

Auf höchster Ebene referiert der Begriff Docker auf eine Containerplattform, die aus vielen Teilen besteht, die vom Ausführen eines individuellen Containers auf einem Host bis hin zum Orchestrieren von Containern über große Servercluster hinweg reicht. Zu Vergleichszwecken lässt sich Docker aber auf zwei prinzipielle Modi begrenzen, die das zugehörige Kommandozeilentool abdeckt.

Da wäre einmal der Daemon-Modus (die Docker-Engine), der den Großteil der Arbeit beim Betreiben und Verwalten der Container übernimmt. Zum anderen gibt es den Client-Modus, in dem die meisten Anwender mit der Docker-Engine interagieren. Gibt ein User beispielsweise ein simples »docker run« ein, verwandelt Docker dies in einen API-Aufruf und reicht ihn an die lokale Docker-Engine weiter, die dann den vom User gewählten Container konfiguriert und startet.

Die Docker-Engine zeichnet für eine Vielzahl Funktionen verantwortlich. Sie empfängt die Container-Images über das Internet, begleitet die Container auf dem System und bietet dem Docker-Client oder anderen HTTP-Clients das erwähnte REST-HTTP-API an. Die Docker-Engine läuft daher dauerhaft, denn sie verwaltet sämtliche Docker-Container auf einem System. Startet sie neu, betrifft das auch die Container.

Systemd-nspawn

Nun zu Systemd-nspawn selbst. Dies lässt sich treffender mit dem Teil der Docker-Engine vergleichen, der sich um das Einrichten der Container kümmert. Intern macht Systemd-nspawn von zahlreichen Features Gebrauch, die der Linux-Kernel anbietet, um Prozesse und Ressourcen zu isolieren. Das erste und wichtigste sind die Namespaces [9].

Namespaces

Kernel-Namespaces isolieren verschiedene Systemressourcen auf eine von den Prozessen abstrahierte Weise, indem sie den Prozessen zuvorkommen. Befindet sich ein Prozess beispielsweise in seinem eigenen PID-Namespace, sieht er nur andere Prozesse auf dem System, die sich im selben Namespace befinden. Auf diese Weise verhindern die Anwender, dass die Prozesse über verschiedene Achsen miteinander interagieren. Der Linux-Kernel bietet eine Anzahl verschiedener Namespaces an, welche das zurzeit sind, verrät Tabelle 1.

Tabelle 1

Kernel-Namespaces

Namespace

Funktion

IPC

System-V-Interprozesskommunikation, Posix-Nachrichten-Warteschlangen

Network

Netzwerkgeräte, Stacks, Ports und so weiter

Mount

Mountpoints

PID

Prozess-IDs

User

Benutzer- und Gruppen-IDs

UTS

Hostname und NIS-Domainname

Ein Prozess erzeugt die Namensräume, indem er einen Systemaufruf namens »unshare()« [10] absetzt. Das trennt den aufrufenden Prozess von seinem existierenden Namespace und erzeugt einen neuen. Ein Prozess kann zudem den »setns()« -Aufruf anwenden, um einen auf dem System existierenden Namensraum zu modifizieren.

Systemd-nspawn verwendet Namespaces ziemlich intensiv, was auch der Name des Tools reflektiert: Nspawn verweist auf die Tatsache, dass das Tool neue Namensräume generiert. Standardmäßig betreibt Systemd-nspawn Prozesse allerdings in ihren eigenen IPC-, Mount-, PID- und UTS-Namensräumen. Es bietet auch Optionen an, um einem Container einen unabhängigen Network-Namespace zu spendieren sowie ein Flag, um einen rudimentären User-Namespace zu verwenden. Weitere Informationen zu Namensräumen liefert eine Serie von LWN-Artikeln [11].

Cgroups

Eine weitere Schlüsseltechnologie beim Betrieb von Containern unter Linux sind die Cgroups (Control Groups, [12]). Ist die Rede von Linux-Containern, meinen die Leute in der Regel diese Kombination aus Namespaces und Cgroups. Letztere organisieren Prozesse auf einem Linux-System in hierarchischen Baumstrukturen. Sie weisen einzelnen Bereichen der Hierarchie optional verschiedene Parameter zur Ressourcenverwaltung zu. Damit lassen sich etwa Speicherlimits für einen bestimmten Prozess oder eine Gruppe von Prozessen festlegen, die der Kernel durchsetzt.

Allerdings hat Systemd-nspawn mit Cgroups eher wenig zu tun. Es stellt sicher, dass der Cgroup-Tree in dem Mount-Namespace verfügbar ist, den es einrichtet. Interessant wird es, wo Systemd-nspawn zum Einsatz kommt, um ein Initsystem zu starten, das ebenfalls Cgroup-Management betreibt wie beispielsweise Systemd selbst.

Das tangiert auch Rkt. Führt es Systemd-nspawn in Stage 1 aus, startet es eine Instanz von Systemd als PID 1 innerhalb einer Containerumgebung. Diese Instanz schafft dann eine eigene Baumstruktur von Cgroups, um die Anwendungen zu verwalten, die es startet. Um Systemd-nspawn aufzurufen, verwendet Rkt einen rohen Systemaufruf [13].

Systemd-nspawn in Aktion

Das Tool ist Bestandteil jeder aktuellen Linux-Distribution, die auch Systemd als Initsystem verwendet. In seiner simpelsten Form übergibt ihm der Anwender einfach ein Verzeichnis und fordert es auf, darin ein Binary auszuführen. Mehr Komplexität bieten die über 30 Kommandozeilen-Optionen, die mehrere Aspekte des zu erzeugenden Containers beeinflussen. Die neuesten Versionen von Systemd-nspawn lassen sich zudem mit einer Konfigurationsdatei füttern, die die meisten der verfügbaren Flags in ein wiederverwendbares Format bringt.

Ein einfaches Beispiel in Listing 1 zeigt Systemd-nspawn in Aktion. Es lädt ein Image der Debian-Distribution Jessie [14] herunter und startet es dann in einem Container (Abbildung 2). Die Schritte sind mit Rootrechten auszuführen. Zudem muss der Admin, will er Jessie nutzen, zuvor in der Datei »/home/redaktion/jessie/etc/passwd« das Passwort von Root löschen.

Abbildung 2: Mit Systemd-nspawn lässt sich Jessie in ein paar einfachen Schritten als Container starten.

Abbildung 2: Mit Systemd-nspawn lässt sich Jessie in ein paar einfachen Schritten als Container starten.

Mit Rkt sieht der Prozess übrigens ganz ähnlich aus (Listing 2). Die dort gezeigten Befehle laden ein ACI von Etcd in Version 2.0.0 herunter und starten es (Abbildung 3). In dem Szenario hat Rkt das notwendige Dateisystem in dem Verzeichnis schon eingerichtet – inklusive einer Kopie von Systemd, das es über »systemd-nspawn […]« aufruft.

Abbildung 3: Auch Rkt holt und startet Container mit nur einem Befehl, im konkreten Fall handelt es sich um Etcd 2.0.0. Im Hintergrund setzt es dazu standardmäßig auf Systemd-nspawn.

Abbildung 3: Auch Rkt holt und startet Container mit nur einem Befehl, im konkreten Fall handelt es sich um Etcd 2.0.0. Im Hintergrund setzt es dazu standardmäßig auf Systemd-nspawn.

Listing 1

Jessie holen und starten

01 apt install debootstrap
02 debootstrap jessie /home/redaktion/jessie
03 systemd-nspawn -bD /home/redaktion/jessie

Listing 2

Rkt in Aktion

01 wget https://github.com/coreos/rkt/releases/download/v0.13.0/rkt-v0.13.0.tar.gz
02 tar xvzf rkt-v0.13.0.tar.gz
03 cd rkt-v0.13.0
04 ./rkt run coreos.com/etcd:v2.0.0

Ausblick

Aber auch wenn Systemd-nspawn bereits viele Features im Gepäck hat, gibt es einige Bereiche, in denen wir auf künftige Verbesserungen hoffen. Zentral sind dabei die User-Namespaces [15], die in ihrer jetzigen Form noch nicht wirklich zu gebrauchen sind. Mit ihrer Hilfe lassen sich Benutzer- und Gruppen-IDs in eigene Namensräume mappen. Im Klartext heißt das: In einem User-Namespace können die Nutzer- und Gruppen-IDs anders lauten als außerhalb dieses Namensraums. Das erlaubt es, einem Prozess innerhalb eines Namespace, etwa in einem Container, Rootrechte zu verleihen, während er außerhalb lediglich über einfache oder gar eingeschränkte Benutzerrechte verfügt.

Abseits solcher Wünsche lässt sich jedoch feststellen, dass Entwickler und Systemadministratoren auch dank »systemd-nspawn« mittlerweile über zahlreiche Optionen verfügen, um Anwendungscontainer zu verwalten.

Reifegrad

Sehr lange enthielt die Manpage von Systemd-nspawn [1] deutliche Warnhinweise gegen den Einsatz in Produktivumgebungen. Das lag unter anderem daran, dass die Entwickler das Tool tatsächlich eher für den Eigenbedarf geschrieben hatten und dass die Realität den Erwartungen an die Fähigkeiten in Sachen Sicherheit und Isolation in den frühen Tagen der Container-Technologie oft hinterherhinkte.

Lennart Poettering entfernte die Warnung auf Anregung von Core OS später, als ihm klar wurde, dass Systemd-nspawn bereits bei vielen Usern produktiv im Einsatz ist und auch die Systemd-Entwickler reichlich Zeit hatten, es auf Herz und Nieren zu prüfen.

Die Systemd-Entwickler lassen im Umgang mit dem Tool jedoch nach wie vor Vorsicht walten. So stellt die Manpage klar, dass Systemd-nspawn noch nicht für ein sicheres Container-Setup tauge, es sei vielmehr für Debugging- und Testzwecke gemacht. Für uns als Rkt-Entwickler spielt das keine Rolle, da die Anwendungsentwickler und Anwender mit der Application Container Runtime als Interface interagieren und Systemd-nspawn lediglich als Low-Level-Tool dient.

Der Autor

Jonathan Boulle arbeitet bei Core OS an verteilten und Container-bezogenen Anwendungen. Er steuert Code zu Fleet und Etcd bei und leitet sowohl die Entwicklung der App-Container-Spezifikation (Appc) als auch die von Rkt, der ersten Appc-Runtime, und steuert Code zu Kubernetes bei.

DIESEN ARTIKEL ALS PDF KAUFEN
EXPRESS-KAUF ALS PDFUmfang: 4 HeftseitenPreis €0,99
(inkl. 19% MwSt.)
LINUX-MAGAZIN KAUFEN
EINZELNE AUSGABE Print-Ausgaben Digitale Ausgaben
ABONNEMENTS Print-Abos Digitales Abo
TABLET & SMARTPHONE APPS Readly Logo
E-Mail Benachrichtigung
Benachrichtige mich zu:
0 Kommentare
Älteste
Neuste Beste Bewertung
Inline Feedbacks
Alle Kommentare anzeigen
Nach oben