Workshop: Anwendungsvirtualisierung mit Docker

Ordnung im System

Auf dem Virtualisierungsmarkt werden die Halbwertszeiten der Produkte immer kürzer. War in den letzten Jahren noch KVM das Zugpferd in der Open Source-Virtualisierungswelt, so ist es seit diesem Jahr Docker. Anwendungen werden hiermit in Containern verpackt, die sich dann sehr einfach, auch über Rechnergrenzen hinweg, einsetzen lassen.
Zum Jahresende dreht sich im IT-Administrator alles rund um das Thema 'Client- und Applikations-Virtualisierung'. So lesen Sie in der Dezember-Ausgabe, welche ... (mehr)

Anwendungen werden natürlich längst nicht mehr nur auf lokalen Maschinen entwickelt und betrieben. Im Cloud-Zeitalter findet all dies in virtuellen Cloud-Umgebungen statt. Solche Plattform as a Service-Umgebungen (PaaS) bieten eine Menge Vorteile. Skalierbarkeit, Hochverfügbarkeit, Konsolidierung, Multi-Tenancy und Portabilität sind nur einige Anforderungen, die sich in einer Cloud nun einmal leichter umsetzen lassen als auf herkömmlichen Bare Metal-Systemen.

Klassische virtuelle Systeme, unabhängig vom eingesetzten Hypervisor, reichen aber heute nicht mehr aus, um die oben genannten Anforderungen zu erfüllen. Sie sind einfach zu unflexibel geworden und bringen zuviel Ballast mit. Entwickler wollen sich nicht damit herumschlagen, erst ein Betriebssystem zu installieren, es im Anschluss zu konfigurieren und dann noch alle Abhängigkeiten, die zum Entwickeln und Betreiben einer Anwendung notwendig sind, zu erfüllen.

Container feiern Comeback

Die Container-Technologie existiert eigentlich schon sehr lange – man denke nur an Solaris Zones, BSD Jails oder Parallels Virtuozzo –, rückte aber erst in den letzten zwei Jahren wieder ins Rampenlicht und gewinnt jetzt massiv an Popularität. Container bekommen die Ressourcen eines Rechners, also beispielsweise Speicher, CPU, Netzwerk und Block-Speicher, isoliert voneinander zur Verfügung gestellt. Anwendungen laufen innerhalb eines Containers komplett unabhängig voneinander ab und haben jeweils ihre eigene Sicht auf die vorhandenen Prozesse, Dateisysteme oder das Netzwerk. Lediglich der Kernel des Host-Systems wird zwischen den einzelnen Containern geteilt. Das ist deshalb notwendig, da die meisten Funktionen einer solchen Umgebung durch diverse Funktionen im Kernel zur Verfügung gestellt werden. Da in diesem Fall eine Virtualisierung lediglich auf Betriebssystemebene stattfindet und keine Emulation der Hardware oder eine virtuelle Maschine notwendig ist, steht der Container unmittelbar zur Verfügung und es ist nicht notwendig, ein BIOS zu durchlaufen oder eine System-Initialisierung durchzuführen (Bild 1 und 2).

Bild 2: Container greifen auf die Ressourcen des Host-Systems zurück. Mit Hilfe von Kernel-Funktionen findet eine Isolierung der Ressourcen innerhalb der Container statt.

Mit LXC (LinuX Containers) stand schon recht früh eine Lösung für Linux zur Verfügung, die auf die Container-Funktionen des Kernels zurückgreift. LXC kann dabei sowohl System-Container (Bild 3), also komplett virtualisierte Betriebssysteme, als auch Anwendungs-Container (Bild 4), zum Virtualisieren einer ganz bestimmten Anwendung, inklusive deren Laufzeitumgebung, bereitstellen. Die Konfiguration von LXC, gerade für das Bereitstellen von Anwendungs-Containern, ist jedoch recht umfangreich und erfordert eine Menge Handarbeit, weshalb die Software nie den ganz großen Durchbruch schaffte. Dies änderte sich jedoch schlagartig mit dem Erscheinen von Docker.

Docker konzentriert sich darauf, Anwendungen in portable Container zu verpacken, um sie dann in einer beliebigen Umgebung ausführen zu können. Teil des Containers ist dabei auch eine Laufzeitumgebung, also das Betriebssystem inklusive der von der Applikation benötigten Abhängigkeiten. Diese Container lassen sich dann sehr leicht zwischen verschiedenen Hosts transportieren und es ist somit ein Leichtes, eine komplette Umgebung, bestehend aus Betriebssystem und Anwendung, innerhalb kürzester Zeit zur Verfügung zu stellen. Der lästige Overhead, wie er bei virtuellen Maschinen noch vorhanden ist, entfällt hierbei komplett.

Container 2.0 mit Docker

Docker ist ein echter Shooting Star. Das erste öffentliche Release kam erst im März 2013 auf den Markt, doch bereits heute wird es von vielen bekannten Firmen unterstützt. So ist es beispielsweise möglich, Docker-Container innerhalb einer Amazon Elastic Beanstalk Cloud oder Google Kubernetes ablaufen zu lassen. Red Hat stellt mit dem Project Atomic sogar ein eigenes Betriebssystem zur Verfügung, das als reines Host-System für Docker-Container dient, unterstützt Docker allerdings auch im neuen Red Hat Enterprise Linux 7. Das Google Kubernetes-Projekt, dem sich mittlerweile viele Firmen angeschlossen haben, versucht, Docker-Container auf allen privaten, öffentlichen und hybriden Cloud-Lösungen lauffähig zu machen. So bietet sogar Microsoft bereits Support für Docker innerhalb der Azure-Plattform an.

Das erste Docker-Release arbeitete noch auf Grundlage von LXC, um auf die Container-API des Linux-Kernels zurückgreifen zu können. Mit der Version 0.9 aus dem aktuellen Jahr hat sich dies jedoch geändert und Docker arbeitet unabhängig von LXC. Die in der Programmiersprache Go geschriebene Libcontainer-Bibliothek kommuniziert nun direkt mit der Container-API im Kernel, um so auf die notwendigen Funktionen für den Betrieb eines Docker-Containers zurückgreifen zu können.

 Diese Funktionen decken im wesentlichen drei grundlegende Komponenten des Linux-Kernels ab: Namespaces, Control-Groups (Cgroups) und SELinux. Namespaces haben dabei die Aufgabe, eine globale System-Ressource zu abstrahieren und sie einem Prozess innerhalb des Namespaces als isolierte Instanz zur Verfügung zu stellen. Die Cgroups sind dafür verantwortlich, System-Ressourcen wie beispielsweise Speicher, CPU oder Netzwerk einer Gruppe von Prozessen zur Verfügung zu stellen (Isolating) und die Nutzung dieser Ressourcen zu kontrollieren (Limiting) und zu protokollieren (Accounting).

Bild 3: System-Container teilen sich üblicherweise das Betriebssystem mit dem Host-System und virtualisieren lediglich eine einzelne Anwendung.

SELinux hilft dabei, Container untereinander zu isolieren, sodass es unmöglich ist, von einem Container auf Ressourcen eines anderen Containers zurückzugreifen. Sichergestellt wird dies, indem jeder Container-Prozess ein eigenes Security-Label bekommt und eine SELinux-Policy festlegt, auf welche Ressourcen ein Prozess mit einem bestimmten Label zugreifen darf. Docker greift hierfür auf die bekannte SELinux-sVirt-Implementierung zurück.

 Bei den Namensräumen unterscheidet der Linux-Kernel zwischen den folgenden:

- UTS (Host- und Domänennamen): Hiermit kann jeder Container einen eigenen Host- und Domänennamen verwenden.

- IPC (Interprozess-Kommunikation): Container verwenden voneinander unabhängige IPC-Mechanismen.

- PID (Prozess-Ids): Jeder Container verwendet einen eigenen Raum für die Prozess-IDs. Somit können Prozesse in unterschiedlichen Containern die gleiche PID besitzen, obwohl diese auf dem gleichen Host-System ablaufen. Jeder Container kann beispielsweise einen Prozess mit der ID 1 enthalten.

- NS (Mountpoints des Dateisystems): Prozesse in unterschiedlichen Containern haben einen individuellen "View" auf das Dateisystem und können somit Zugriff auf unterschiedliche Objekte bekommen. Diese Funktionalität ist mit dem altbekannten Unix chroot vergleichbar.

- NET (Netzwerkressourcen): Jeder Container kann sein eigenes Netzwerkgerät mit eigener IP-Adresse und Routing-Tabelle besitzen.

- USER (Benutzer- und Gruppen-Ids): Prozesse außerhalb und innerhalb eines Containers können voneinander unabhängige Benutzer- und Gruppen-IDs besitzen. Das ist hilfreich, da somit ein Prozess ausserhalb des Containers eine unprivilegierte ID besitzen kann, während er innerhalb des Container als ID 0 abläuft und somit komplette Kontrolle über den Container, nicht aber über das Hostsystem besitzt. User-Namespaces stehen aber erst seit der Kernel-Version 3.8 zur Verfügung und sind somit noch nicht in allen Linux-Distributionen enthalten.

Bild 4: Die individuelle Laufzeitumgebung kann sich zwischen den einzelnen Containern eines Hosts durchaus unterscheiden. Somit sind unterschiedliche Betriebssysteme auf einem einzelnen Host möglich.
comments powered by Disqus
Einmal pro Woche aktuelle News, kostenlose Artikel und nützliche ADMIN-Tipps.
Ich habe die Datenschutzerklärung gelesen und bin einverstanden.

Konfigurationsmanagement

Ich konfiguriere meine Server

  • von Hand
  • mit eigenen Skripts
  • mit Puppet
  • mit Ansible
  • mit Saltstack
  • mit Chef
  • mit CFengine
  • mit dem Nix-System
  • mit Containern
  • mit anderer Konfigurationsmanagement-Software

Ausgabe /2023