Renaissance der Container-Virtualisierung mit Docker - Container-Terminal
Docker verhilft dem Linux-Container zu einem publikumswirksamen Comeback und baut rund um die Virtualisierungslösung die Funktionen ein, die beim Original fehlen.
Wenn im IT-Kontext der Begriff Virtualisierung fällt, dann verbinden das die meisten Admins fast automatisch mit den Standard-Tools wie Qemu, VMware oder Xen. All diesen Lösungen ist gemein, dass sie umfassende Virtualisierer sind, die ganze Systeme emulieren. Sämtliche Werkzeuge dieser Kategorie verursachen einen großen Overhead, auch wenn es nur darum geht, einzelne Programme in virtuellen Umgebungen zu betreiben.
Wenig Overhead
Dass Virtualisierung auch mit deutlich weniger Nebengeräuschen möglich ist, beweisen Containerbasierte Lösungen. Diese sperren Prozesse lediglich in ein virtuelles Gefängnis ein, benötigen dafür aber nicht den Overhead eines eigenen Betriebssystems, sondern begnügen sich mit den Ressourcen, die ihnen das Host-Betriebssystem zur Verfügung stellt. Praktisch alle Betriebssysteme verfügen über eine eigene Container-Implementation: FreeBSD hat seine Jails, auf Windows war Virtuozzo eine ganze Weile hip und natürlich hat auch Linux Container, sogar in mehrfacher Ausfertigung: OpenVZ, LXC und Linux-VServer buhlen um die Gunst der Nutzer.
Bemerkenswert ist dabei vor allem LXC: Einst ein kleiner Hype, ist die Technologie zwischenzeitlich weitestgehend aus den Nachrichten verschwunden und eher zum Randthema geworden. Sehr zu unrecht: In LXC-Containern lassen sich Aufgaben erledigen, für die das Virtualisieren eines ganzen Betriebssystems definitiv zu großer Aufwand wäre. Den Entwicklern vom Linux-Container (dafür steht LXC) dürfte es insofern gefallen, dass über Umwege derzeit ihr Projekt wieder im Mittelpunkt steht: Docker verbreitet sich wie ein Lauffeuer in der Community und es basiert auf den Funktionen von LXC.
Container as a Service?
Die Entwickler hinter Docker haben im Grunde die Hausaufgaben gemacht, die die LXC-Entwickler hätten machen sollen: Sie haben – womöglich gar nicht bewusst – die Frage beantwortet, wieso LXC sich in der breiten Masse bisher nicht durchgesetzt hat. Einerseits fallen sicherlich die bereits genannten und sehr viel PR-trächtigeren Vollvirtualisierer ins Gewicht, andererseits scheint es aber auch so, als habe sich vielen Anwendern der Sinn hinter Containern im Computing-Umfeld nur unzureichend erschlossen.
Docker macht LXC nun attraktiv: Das erklärte Ziel des Projektes ist es, jedwede Applikation in einen Container zu packen, um diesen Container anschließend verteilen zu können. Die Idee ist brillant: Sie rückt die technischen Details in den Hintergrund, damit im Vordergrund ein leicht zu nutzender Dienst steht. De facto ergänzt Docker LXC um die Usability, die LXC selbst zum Erfolg stets gefehlt hat.
Und das Werkzeug kommt an bei den Nutzern: Kaum jemand, der in den letzten Wochen von der Lösung noch nicht gehört hätte. Grund genug, sich einmal genauer mit Docker zu beschäftigen: Wie funktioniert die Lösung und wie lässt Docker sich konkret nutzen, um sich selbst Arbeit zu ersparen oder sich Arbeit wenigstens leichter zu machen? Im Backend verlässt Docker sich ausschließlich auf LXC. Die Frage nach den Fähigkeiten von Docker ist insofern auch die Frage nach den Funktionen, die in LXC enthalten sind: Im Grunde ist LXC ja zunächst nichts anderes als eine Sammlung von Funktionen, die der Linux-Kernel zu Sandboxing-Zwecken anbietet.
Cgroups
Dabei stechen zwei Funktionen hervor: Cgroups und Namespacing. Cgroups steht für Control Groups und bezeichnet eine Kernel-Funktion in Linux, mit der sich Prozessgruppen definieren lassen, um anschließend die verfügbaren Ressourcen für diese Gruppen zu beschränken. Vornehmlich geht es um Hardware: Für Cgroups lässt sich festlegen, wieviel RAM, Platz auf der Platte oder Disk-I/O eine Gruppe verwenden darf. Die Liste der verfügbaren Kriterien ist dabei freilich weit länger als diese Beispiele. Seit der Version 2.6.24 sind Cgroups fester Bestandteil des Kernels, und über die Jahre haben die Kernel-Entwickler die Cgroup-Funktionen deutlich ausgebaut. Neben der oben erwähnten Begrenzung von Ressourcen lassen sich Cgroups nämlich mittlerweile auch priorisieren sowie von außen ordentlich steuern.
Namespacing
Namespacing spielt in Linux zusätzlich eine zentrale Rolle, wenn es um das Thema Sicherheit geht. Cgroups per se sind nämlich nicht vorrangig dafür da, Prozesse voneinander abzugrenzen – sie kümmern sich bevorzugt um Ressourcen. Den Sicherheitsaspekt werfen Namespaces in die Waagschale: Über Namespaces lassen sich nämlich einzelne Prozesse oder Cgroups vor anderen Prozessen oder Cgroups verstecken.
Feingranular ist die Technik obendrein: Namespaces unterscheiden zwischen den Prozess-IDs, dem Netzwerkzugriff, dem Zugriff auf den gemeinsamen Hostnamen, Mountpoints oder der Kommunikation aller Prozesse miteinander (IPC). Network-Namespaces sind mittlerweile zum Beispiel recht beliebt, um auf dem gleichen Host eine Trennung zwischen den Paketen von mehreren Benutzern herbeizuführen: Ein Prozess innerhalb eines Namespaces kann dabei weder die Host-Interfaces noch die Interfaces in den Namespaces anderer Kunden sehen – und schon gar nicht anzapfen.
Während Cgroups und Namespaces für sich genommen nette Features sind, werden sie im Team zur attraktiven Virtualisierungstechnik. Denn durch die Option, Prozesse zu kontrollierbaren Gruppen zusammenzufassen, um sie anschließend in ihren Möglichkeiten zu begrenzen, ergibt sich ein simpler, aber effektiver Container-Ansatz. Diese Funktionen bietet LXC, und Docker baut auch auf dieser Grundfunktionalität auf.
Portierbare Container
Hinzu kommen bei Docker allerdings viele praktische Features. Vermutlich die wichtigste Funktion sind die portierbaren Container: In Docker ist es leicht, vorhandene Container zwischen zwei Hosts umzuziehen. Purem LXC ist dieser Stunt eher zuwider: Letztlich läuft es dort auf einen manuellen Umzug der Dateien hinaus – insgesamt ein wenig komfortabler Vorgang. Obendrein hat ein Benutzer keine Garantie, dass er am Ende tatsächlich Erfolg hat: Container in „purem“ LXC sind hochgradig abhängig von der Umgebung, in der sie etwa auf System A laufen. Ist das Ziel-System B diesem nicht zumindest ähnlich, endet die Umzugsfreude, noch bevor sie angefangen hat. Problematisch sind hier diverse Faktoren wie die genutzte Distribution oder die verfügbare Hardware für den Container. Die Entwickler von Docker haben ein eigenes Container-Format konstruiert, das die Sache leichter macht: Docker abstrahiert die Ressourcen, welche eine VM sieht, und kümmert sich um die Kommunikation mit dem realen System auf der anderen Seite selbst. Die Dienste, die innerhalb eines Docker-Containers laufen, sehen insofern stets das gleiche System. Will ein Benutzer nun einen Container von einem System auf ein anderes umziehen, übernimmt Docker den größten Teil der Arbeit: Der Benutzer exportiert den Container in das dafür erfundene Docker-Format, zieht die Datei auf einen anderen Rechner um, spielt den Container wieder in Docker ein, fertig.
Die Docker-Philosophie
Wer sich mit Docker beschäftigt, merkt schnell, dass die Docker-Entwickler offensichtlich andere Grundauffassungen bezüglich der Container vertreten, als es zum Beispiel die LXC-Verantwortlichen tun. Die Docker-Entwickler selbst bezeichnen Docker als Applikationszentrisch. Gemeint ist, dass in Docker die innerhalb eines Containers laufende Applikation der wirklich wichtige Aspekt ist, nicht der Container selbst. LXC genießt ja gerade in Entwicklerkreisen Beliebtheit, weil sich ein LXC-Container relativ gut als schnellbootender Ersatz für eine komplette virtuelle Maschine nutzen lässt. Bei Docker geht es nicht um diesen Faktor, sondern darum, dass ein Container die kleine aber feine Umwelt für nahezu jede Applikation sein kann. Vor diesem Hintergrund wird auch deutlich, was es mit dem genannten Container-Feature auf sich hat: Die Kernmotivation beim Erfinden dieses Features war die Tatsache, dass man Apps quasi als Appliances schnell von einem Host auf einen anderen umziehen können sollte.
Eigenbau-Images
Docker unterstützt Benutzer übrigens auch dabei, vorbereitete Container für den Export in Docker herzustellen. Ein Container ist ja im Normalfall nichts anderes als das komplette Dateisystem einer Linux-Installation; Docker bietet die Möglichkeit, jedes beliebige Verzeichnis problemlos in ein Docker-Image umzuwandeln. Wer es gerne spartanisch mag, kann sich also beispielsweise auf einem Debian- oder Ubuntu-System mittels »debootstrap« ein Mini-System aus dem Ärmel zaubern, darin die Abhängigkeiten für eine beliebige Applikation und diese selbst installieren und am Ende Docker den Ordner übergeben – fertig ist das Image, das sich beliebig verteilen lässt. Das Image-Bauen in Docker ist übrigens obendrein denkbar einfach, denn mittels des »docker«-Programms ist ein einzelner Befehl völlig ausreichend:
debootstrap precise ./rootfs;
U tar ‑C ./rootfs ‑c . | docker import
U ubuntu/mybase
Fertig ist das Image.
Das Ziel: PaaS
Docker passt mit seinem Funktionsportfolio sehr gut in die aktuell durch Cloud-Computing und Everything-as-a-Service-geprägte IT-Szene. Denn letztlich ist das Ziel bei Docker klar: Über vorgefertigte Container, die sich beliebig im Netz verteilen lassen, kann der Admin Platform-as-a-Service-Anwendungen leicht und komfortabel unters Volk bringen. Das PaaS-Konzept passt zu Docker, weil es ebenfalls die Applikation in den Vordergrund rückt und nicht so sehr das Betriebssystem, auf dem eben jene Applikation läuft. Docker tut genau das. Mittlerweile steht auch ein auf den Namen »Docker Index« getaufter Dienst zur Verfügung (Abbildung 1), der quasi als Container-Marktplatz dient: Benutzer, die sich einen Container für bestimmte Zwecke gebaut haben, können diesen in den Index hochladen, damit er anschließend anderen Benutzern zur Verfügung steht. Die Teilnahme am Docker Index ist kostenlos, lediglich eine Registrierung wird vorausgesetzt. Die Zahl der verschiedenen Images, die sich in Docker finden, ist beeindruckend: Neben Basis-Images für praktisch alle gängigen Distributionen stehen auch spezielle Images parat, so zum Beispiel mehrere Tomcat-Images, mit denen sich quasi per Mausklick eine komplete Java-Tomcat-Instanz starten lässt. MySQL, Apache oder Drupal als fertige Plattform, sogar einige OpenStack-Komponenten: Für all das stehen bereits Docker-Images zur Verfügung, und täglich kommen neue hinzu. Das ist auch deshalb praktisch, weil es die Einstiegshürde senkt: Hat man Docker erstmal installiert, dauert es bis zum ersten selbst deployten Programm nicht mehr lange.
Mitgedacht: Automatischer Build
Für die Docker-Entwickler endet PaaS aber offensichtlich nicht dort, wo ein Nutzer einen Container startet, um anschließend seine Applikation darin zu installieren. Denn auch diesen letzten Schritt wollen die Docker-Entwickler den Benutzern noch erleichtern: Ein automatisches Build-System ist direkt in Docker integriert und richtet sich vorrangig an die Entwickler von Programmen, die ihre App gern als Docker-Container verteilen möchten. Über die sogenannten Dockerfiles lässt sich nämlich ebenfalls die Konfiguration eines Containers bis ins Detail festlegen. Über Dockerfiles steht dem Entwickler anschließend die Möglichkeit zur Verfügung, Docker-Container automatisiert anzulegen. Das wäre beispielsweise dann von Vorteil, wenn man von der eigenen Applikation neben einer Stable-Version auch eine Snapshot-Version anbieten wollte, die sich nachts jeweils einen aktuellen GitHub-Checkout des Programms besorgt und dann daraus ein fertiges Docker-Image baut. Wer sich diese Funktion genauer ansehen mag, findet in der Docker-Dokumentation unter [1] entsprechende Details zu den Dockerfiles.
Versionskontrolle
Ebenfalls ein Schmankerl für alle, die Docker-Container produktiv nutzen wollen, sind die Versioning-Features von Docker. Denn für Docker haben dessen Entwickler im Grunde einen kleinen Klon von Git implementiert, der aber auf den Docker-Betrieb spezialisiert ist. Dazu gehören viele Befehle, die in der Tat an Git erinnern: »docker commit«, »docker diff« und »docker history« sind dafür nur einige Beispiele. Diese Funktionen sorgen letztlich da-für, dass nicht für jede neue Version eines Images eine komplette Kopie der ursprünglichen Datei notwendig ist. In Abhängigkeit von den Containern würde das schließlich schnell zu Platznot führen. Docker umgeht das Problem überaus elegant, indem es quasi ein lokales „Container-Repository“ führt, in das sich Änderungen jederzeit committen lassen. Über die vormals beschriebene Funktion des Automated Builds lässt sich obendrein zu jedem Zeitpunkt aus einem Image in einer bestimmten Version jederzeit wieder ein fertiges Container-File zur Weitergabe herstellen. Insgesamt ist der Umgang mit Containern also überaus elegant implementiert.
Die Docker-API
Eleganz kommt auch bei Dockers API zum Ausdruck: Das ist quasi eine zen-trale Schalt- und Schnittstelle einer Docker-Installation, die sich über eine API nach dem ReSTful-Prinzip bedie-nen lässt. Sie ist im Hintergrund dafür verantwortlich, dass mittels »docker« auf der Kommandozeile eingegebene Befehle tatsächlich auch umgesetzt werden. Sämtliche Docker-Befehle sind also letztlich verkappte API-Aufrufe, die Docker-API erledigt die echte Arbeit. Der Vorteil einer solchen Architektur liegt auf der Hand, denn mit der API als abstraktem Befehlsempfänger im Hintergrund sind der Fantasie bei der Entwicklung von Frontends kaum Grenzen gesetzt. Alle gängigen Cloud-Computing-Lösungen setzen auf ähnli-che Designs, und wie bei Amazons EC2 oder OpenStack hat sich das Prinzip auch bei Docker bewährt: Neben dem »docker«-Tool auf der Kommandozeile steht mittlerweile auch eine grafische Oberfläche namens Docker-UI [2] zur Verfügung (Abbildung 2). Und einen Konkurrenten dazu gibt es auch schon: Shipyard [3] buhlt ebenfalls um die Gunst der Nutzer (Abbildung 3).
Cloud-Integration
Docker qualifiziert sich mit seinen Fähigkeiten freilich auch für höhere Aufgaben. Wer kein vollständig virtualisiertes System benötigt, sondern lediglich einen passenden Container – beispielsweise für Entwicklungszwecke – zieht aus Docker große Vorteile. So liegt es nur nahe, Docker auch in typische Cloud- und Virtualisierungslösungen zu integrieren – und in weitere Tools und Werkzeuge, die ebenfalls im Fahr-wasser der großen Cloud-Umgebungen unterwegs sind.
OpenStack dominiert den Markt der Open-Source-Clouds im Augenblick ganz eindeutig, das ist auch den Docker-Entwicklern offenbar nicht entgangen. Denn die Virtualisierungs-komponente von OpenStack, Nova[4], kommt mittlerweile mit Unterstützung für Docker daher.
Nova ist grundsätzlich modular aufge-baut, und die Virtualisierungstechnik, die zum Einsatz kommen soll, lässt sich per Plugin aktivieren. Deshalb lässt sich über einen simplen Eintrag in »nova.conf« steuern, welche Technik die OpenStack-Komponente im Hinter-grund einsetzt; zur Auswahl stehen zum Beispiel KVM, HyperV und VMware. Und neuerdings auch Docker (Abbildung 4): OpenStack startet dann im Hintergrund keine komplette VM, sondern legt einen Docker-Container an, der als virtuel-les System mit eigener Funktionalität aufwartet. Die Integration von Docker ist dabei nahtlos, einen Unterschied er-kennt man zwischen einer mit KVM ge-starteten Voll-VM und Docker zunächst nicht. Im Detail wird aber deutlich, dass qualitative Unterschiede vorhanden sind.
Die hängen zum Teil mit den Anforderungen zusammen, die Docker an sich selbst stellt: Weil die Anwendung nach innen wie beschrieben stets das gleiche System präsentieren möchte, muss sie sich auf der Außenseite verbiegen. Das erfordert einen hohen Grad an Anpass-barkeit im Hinblick auf verschiedene Faktoren, zum Beispiel das Thema Netzwerk.
Der Docker-Treiber in Nova unterstützt aber in der Havana-Release von OpenStack lediglich den alten Netz-werkstack »nova-network«, der ver-mutlich in der übernächsten Release aus OpenStack entfernt werden wird. Ein Bug-Report in Launchpad legt den Verdacht nahe, dass es sich um einen Bug handelt, und nicht etwa um ein bewusst noch nicht implementiertes Feature [5]. Wer OpenStack mit dem zukunftsträchtigen Neutron-SDN-Stack einsetzt, schaut also vorerst ins Leere. Gerade weil Docker gerade ein echtes Hype-Thema ist, dürfte der Fehler al-lerdings in absehbarer Zeit korrigiert werden. Wie reif die Docker-Implementation in Nova ist, lässt sich auf diese Weise allerdings kaum beurteilen.
Fazit
Docker erweitert LXC um eine ganze Reihe nützlicher Features, die die Soft-ware deutlich attraktiver machen. Die Entwickler der Lösung richten Docker zwar maßgeblich auf die Anforderung aus, Anwendungen im Container-Format schnell und einfach verteilen zu können, sodass sie auf jedem System sofort lauffähig sind. Doch in der Realität dürfte Docker vor allem für jene Set-ups interessant werden, in denen zwar Virtualisierung gewünscht ist, jedoch nicht der Overhead eines zur Gänze virtualisierten System.
Hier erlaubt Docker einen attraktiven Mittelweg – es kommt ja auch nicht von ungefähr, dass die Software viele Fans hat und gerade einen ziemlichen Hype erlebt. Gerade in der Kombination mit einem schlanken OpenStack-Setup könnte sich Docker zu einem wirklich nützlichen Werkzeug für viele Aufga-ben entwickeln. Viele praktische Tools bringt es dafür jedenfalls bereits jetzt mit. Allerdings müsste für ein funktions-tüchtiges Setup der Docker-Treiber von OpenStack Nova einen funktionstüchti-gen Zustand erreichen und sollte dabei auch keine Software aus der grauen Vorzeit voraussetzen. Wer Docker ohne Anbindung an Frameworks wie Open-Stack betreiben will, findet allerdings schon heute ein verlässliches Werkzeug.
Verlässlich vor allem deshalb, weil die Docker-API sehr vielseitig ist und beispielsweise neben den bereits erwähnten Features auch eine nahtlose Anbindung an Automatisierungs-Tools wie Puppet und Chef ermöglicht. Alles in allem hat Docker also echte Chan-cen, Admins Darling zu werden. Einen näheren Blick ist es auf alle Fälle wert.
Links
- Docker-Dokumentaton: [https://docs.docker.io/en/latest/]
- Docker-UI: [https://github.com/crosbymichael/dockerui]
- Shipyard: [https://github.com/shipyard]
- OpenStack Nova: [https://nova.openstack.org/]
- Bugreport zu Docker in Nova: [https://bugs.launchpad.net/nova/+bug/1247295]
von Martin Loschwitz Artikel aus dem Admin Magazin Ausgabe 2/2014