Operations heute und morgen, Teil 3: Virtualisierung und Containerisierung

Seite 3: Container

Inhaltsverzeichnis

Das 2013 gegründete und seit letztem Jahr kaum mehr zu übersehende Docker-Projekt machte den Begriff der "Containerisierung" populär. Zwar ist Docker seit einiger Zeit nicht mehr alleiniger Spieler in diesem Feld, aber sicherlich der bekannteste. Container werden vielfach als Nachfolger oder Ablösung der Virtualisierung gefeiert. Entsprechend finden sich zahlreiche Vergleiche und Gegenüberstellungen, die suggerieren, es handle sich dabei um konkurrierende Ansätze. Doch das ist mitnichten der Fall, stehen doch der VM-basierte Plattform- und der Container-Ansatz weitgehend orthogonal zueinander.

Unter einem Container versteht man eine komplette Anwendung, inklusive ihrer Abhängigkeiten und Konfiguration, verpackt in einem definierten, wiederverwendbaren Format. Im Unterschied zu einer kompletten Virtual Machine enthält ein Docker-Container jedoch kein eigenes Betriebssystem mit eigenem Kernel, Treibern et cetera. Er fällt dadurch deutlich schlanker aus. Vereinfacht gesagt ist ein Container keine virtuelle Maschine, sondern eine Art "virtualisiertes Binary". Man spricht daher auch von Anwendungsvirtualisierung.

Technisch basieren Container auf bereits länger verfügbaren Funktionen, die der Linux-Kernel zur Isolierung von Anwendungen bietet, wie Kernel Namespaces, cgroups und SELinux. Anwendungen verschiedener Container laufen dadurch als weitgehend voneinander abgeschottete reguläre Userland-Prozesse in einer einzigen gemeinsamen Linux-Umgebung. Jeder Prozess bekommt vom Kernel nur seine "eigene kleine Welt" präsentiert: Prozesshierarchie, Rechenkapazität, Netzwerk-Interfaces, Dateisystem – das steht aus Sicht der Anwendung im Container exklusiv zur Verfügung. Das vereinfacht die Konfiguration erheblich. Die Anwendung kann zum Beispiel immer darauf bauen, einen bestimmten Netzwerkport binden zu können – in ihrem Container besteht keine Gefahr, dass ein anderer Prozess diesen bereits belegt hat. Damit entfällt etwa die Notwendigkeit für entsprechende Fehlerbehandlung in der Anwendung oder für viele ansonsten notwendige Konfigurationseinstellungen.

Sollen Anwendungen zusammenarbeiten – beispielsweise Anwendungs- und Datenbankserver – können sie in ihren jeweils eigenen Containern laufen. Die Anwendung erwartet ihre Datenbank zum Beispiel immer auf localhost:3306. Im einfachsten Fall, wenn beide Container auf der gleichen Maschine laufen, sorgt der Container-Daemon durch Einrichtung entsprechender NAT-Regeln dafür, dass die Daten transparent ihren Weg zum Datenbankcontainer und zurückfinden. In komplexeren Setups können die Container auch auf unterschiedliche Hosts verteilt sein, gegebenenfalls mit zwischengeschalteten Load-Balancern und so weiter. Charmanterweise ändert sich jedoch dadurch nichts an der Konfiguration der Anwendungen innerhalb der Container.

Die Vorteile der Container liegen auf der Hand: Der verhältnismäßig große Overhead einer kompletten Virtual Machine, die ein vollständiges Betriebssystem mit eigener Speicherverwaltung, Treibern, Massenspeichern et cetera mit sich bringt, entfällt. Dadurch ist es möglich, einen Container in einem Bruchteil der Zeit zu starten und auch nur einen Bruchteil der Ressourcen zu verbrauchen, die eine VM benötigen würde.

Darüber hinaus kann ein einmal erstellter Anwendungscontainer Bit-identisch sowohl etwa auf dem lokalen Entwickler-PC laufen als auch auf dem Produktivsystem. Im ersten Fall können alle Container, die die Anwendungskomponenten enthalten, auf der gleichen Maschine nebeneinander laufen, in letzterem Fall verteilt im Cluster. Die Fehlerkategorie "bei mir lokal lief es aber" verliert damit deutlich an Schrecken. Mit Orchestrierungssystemen wie Googles Kubernetes oder Apache Mesos werden Container anhand vorgegebener Regeln (z. B. wie viele Instanzen eines bestimmten Dienstes zu jeder Zeit laufen sollen) über die verfügbare Hardware verteilt und überwacht. Damit lassen sich auch große Setups verwalten.

Jedoch sind Container (mal wieder) kein Allheilmittel und bringen bei allen Vorzügen auch eine Reihe wichtiger Einschränkungen mit sich. Naturgemäß bleibt die Isolierung der Container untereinander und gegenüber dem Hostsystem (noch) deutlich hinter klassischer Virtualisierung zurück. Alle Container beziehungsweise die darin enthaltenen Prozesse teilen sich den gleichen Kernel und die gleichen Systembibliotheken – was gegebenenfalls Kompatibilitätsprobleme nach sich zieht und zum Beispiel Windows zumindest derzeit noch ausklammert. Zwar gibt es bereits Docker-Client-Software für Windows, doch erst mit Windows Server 2016 steht die Unterstützung von containerisierten Windows-Anwendungen auf dem Programm.

Da es sich letztlich bei Software in Containern um reguläre Prozesse handelt, beschränkt sich der Virtualisierungs-Overhead auf ein Minimum. Das bringt so eine nahezu ungebremste Ausführungsgeschwindigkeit und die Möglichkeit, mehr Anwendungen auf der gleichen Hardware zu betreiben, als mit VMs möglich. Doch kann ein Softwarefehler oder eine Sicherheitslücke das gesamte System in Mitleidenschaft ziehen. Das ist bei Virtualisierung, die mit ihrer Hardwareunterstützung von "echter" Isolierung profitiert, nicht möglich. Eine Kernel-Panic in einer VM hat keine Auswirkung auf weitere, auch wenn sie auf der gleichen physischen Maschine gehostet sind. Passiert das Gleiche auf einem Container-Host, stürzen alle Container gleichzeitig über die Klippe.

Hypervisor-basierte Virtualisierung erlaubt eine effizientere Ausnutzung der Hardware, bringt aber durch mehrere OS-Instanzen einen nicht zu unterschätzenden Overhead mit sich (Abb. 2).

Last, but not least gilt zu bedenken, dass die wenigsten existierenden Anwendungen sich ohne weiteres in Container stecken lassen. Auch wenn Google intern dem Vernehmen nach all seine Software in Containern verpackt und Entwickler allerorten oft allein aus Spaß am Neuen entsprechende Grundlagen schaffen, dürfte auf absehbare Zeit der Großteil existierender Software – insbesondere bereits seit Jahren laufende Individual- und Branchenanwendungen – schon aus wirtschaftlichen Gründen die nötigen Umbauarbeiten wohl kaum erfahren.

Anwendungen in Containern verursachen einen geringeren Overhead, setzen jedoch eine gemeinsame Betriebssystembasis für alle Anwendungen voraus (Abb. 3).