Prinzipien der Container-Virtualisierung

Prinzipien der Container-Virtualisierung

Container-Technologie verstehen

Container sind eine Art Sandbox-Technologie. Wie der Name schon sagt, ist eine Sandbox eine Technologie, die Anwendungen wie einen Container „verpacken“ kann, sodass sich Anwendungen aufgrund festgelegter Grenzen nicht gegenseitig stören. Darüber hinaus können Anwendungen in diesen „Containern“ migriert und in verschiedenen Systemumgebungen ausgeführt werden. Bevor wir uns mit den Prinzipien hinter der Container-Technologie befassen, ist es wichtig, das Konzept von Prozessen zu verstehen. Die statische Darstellung eines Prozesses ist ein Programm, das normalerweise ruhig auf einer Festplatte liegt. Sobald es ausgeführt wird, verwandelt es sich in die Summe von Daten und Zuständen innerhalb des Computers – seine dynamische Darstellung. Die Kernfunktionalität der Container-Technologie besteht darin, eine „Grenze“ für Prozesse zu schaffen, indem ihr dynamisches Verhalten eingeschränkt und verändert wird.

Docker-Container-Technologie

Für die meisten Linux-Container, einschließlich Docker, wird hauptsächlich Cgroups-Technologie verwendet, um Einschränkungen aufzuerlegen, während die Namespace-Technologie die primäre Methode zur Änderung der Prozessansicht ist. Stellen Sie sich vor, Sie haben ein Docker-Projekt, das auf einem Linux-Betriebssystem läuft, z. B. Ubuntu 22.04. Lassen Sie uns einen Container erstellen, um zu experimentieren:

$ docker run -it busybox /bin/sh

Dieser Docker-Befehl startet einen Container basierend auf dem busybox-Image und führt eine interaktive Shell-Sitzung darin aus.

  • docker run: Erstellt und startet eine neue Container-Instanz.
  • -i: Hält STDIN offen, auch ohne angeschlossenes Terminal, und ermöglicht die Interaktion mit dem Container.
  • -t: Weist ein Pseudo-Terminal oder Terminal zu und erstellt eine interaktive Shell-Umgebung.
  • /bin/sh: Gibt den Befehl an, der beim Start des Containers ausgeführt werden soll, in diesem Fall das Starten einer Shell-Sitzung innerhalb des Containers.

Prozesse im Container

Somit wird die Ubuntu-Maschine zu einem Host, und innerhalb von ihr läuft ein Container mit /bin/sh. Dieses Beispiel und sein zugrunde liegendes Prinzip sollten erfahrenen Docker-Benutzern vertraut sein. Wenn Sie den Befehl ps innerhalb des Containers ausführen, werden Sie etwas Interessantes bemerken:

/ # ps
PID USER TIME COMMAND
1 root 0:00 /bin/sh
10 root 0:00 ps

Hier ist das anfängliche /bin/sh, das in Docker ausgeführt wird, Prozess Nummer 1 (PID=1) innerhalb des Containers, und es laufen nur zwei Prozesse. Dies bedeutet, dass der Befehl /bin/sh und der gerade ausgeführte Befehl ps in einer separaten Umgebung vom Host isoliert wurden.

Der Namespace-Mechanismus

Wie wird das erreicht? Normalerweise weist das Betriebssystem einem /bin/sh-Programm, das auf dem Host ausgeführt wird, eine Prozess-ID zu, z. B. PID=100, die es eindeutig identifiziert. Wenn dieses Programm in einem Docker-Container ausgeführt wird, wendet Docker eine „Illusion“ an, sodass der Prozess, der tatsächlich PID=100 ist, glaubt, der erste Prozess (PID=1) zu sein. Dieser Mechanismus manipuliert den Prozessraum isolierter Anwendungen, sodass sie neu berechnete Prozess-IDs sehen.

Linux-Namespace-Technologie

Die Verwendung von Namespaces ist recht interessant: Es ist lediglich ein optionaler Parameter zum Erstellen neuer Prozesse in Linux. Der Systemaufruf zum Erstellen von Prozessen in Linux ist clone(), wie folgt:

int pid = clone(main_function, stack_size, SIGCHLD, NULL);

Dieser Aufruf erstellt einen neuen Prozess und gibt seine Prozess-ID, pid, zurück. Bei Verwendung des Systemaufrufs clone() zum Erstellen eines neuen Prozesses kann das Argument CLONE_NEWPID angegeben werden:

int pid = clone(main_function, stack_size, CLONE_NEWPID | SIGCHLD, NULL);

Der neu erstellte Prozess wird dann einen neuen Prozessraum „sehen“, in dem seine PID 1 ist. Diese „Illusion“ ändert nicht die tatsächliche PID im Prozessraum des Hosts, die der reale Wert bleibt, z. B. 100.

Mehrere Namespaces in Aktion

Die wiederholte Ausführung des obigen clone()-Aufrufs würde mehrere PID-Namespaces erstellen. Jede Anwendung in einem Namespace glaubt, der erste Prozess in ihrem jeweiligen Container zu sein, ohne Kenntnis des tatsächlichen Prozessraums des Hosts oder der Details anderer PID-Namespaces. Neben dem PID-Namespace bietet Linux Mount-, UTS-, IPC-, Network- und User-Namespaces, um verschiedene Prozesskontexte zu „verschleiern“. Mount-Namespace

  • Mount-Namespace: Er ermöglicht isolierten Prozessen, nur die für den aktuellen Namespace relevanten Mountpunkte zu sehen, d. h. Prozesse innerhalb des Containers sind sich anderer Mountpunkte auf dem Host nicht bewusst.

Network-Namespace

  • Network-Namespace: Er bietet isolierten Prozessen eine Ansicht der Netzwerkgeräte und -konfigurationen, die für den aktuellen Namespace spezifisch sind. Jeder Network-Namespace hat seine eigenen Netzwerkgeräte, IP-Adressen, Routing-Tabellen und Portnummern, getrennt vom Host und anderen Namespaces.

Andere Namespaces

  • UTS-Namespace: Er isoliert den Knotennamen (Hostname) und den Netzwerk-Hostnamen.
  • IPC-Namespace: Er trennt Ressourcen für die Interprozesskommunikation, z. B. Message Queues und Semaphore.
  • User-Namespace: Er isoliert Benutzer- und Gruppen-IDs und ermöglicht die Zuordnung von containerisierten Benutzer-IDs zu anderen IDs auf dem Host für erhöhte Sicherheit.

Das Implementierungsprinzip von Docker-Containern

Dies ist das grundlegende Implementierungsprinzip von Linux-Containern. Somit beinhaltet das scheinbar komplexe Konzept von Docker-Containern im Wesentlichen die Angabe einer Reihe von Namespace-Parametern beim Erstellen eines Container-Prozesses. Folglich kann der Container nur die Ressourcen, Dateien, Geräte, Zustände oder Konfigurationen „sehen“, die durch den aktuellen Namespace begrenzt sind, und bleibt dem Host und nicht verwandten Programmen völlig unbekannt.

Vergleich von Containern mit virtuellen Maschinen

Container sind daher eine besondere Art von Prozessen. Wenn man die Idee betrachtet, Prozessen einen eigenen Raum zuzuweisen, kommen einem virtuelle Maschinen in den Sinn. Sie simulieren Hardware über eine Hypervisor-Software und führen ein vollständiges Gastbetriebssystem aus, um Anwendungsisolation zu erreichen. Im Gegensatz dazu erreichen Docker-Container die Isolation durch Namespace- und Cgroups-Technologie, während sie den Kernel des Host-Betriebssystems gemeinsam nutzen.

Docks leichte Virtualisierung

Docker wird oft als „leichte“ Virtualisierungstechnologie bezeichnet, da sie direkt Host-Ressourcen nutzt, ohne Hardware zu simulieren oder ein zusätzliches Betriebssystem auszuführen. Dies führt zu erheblichen Vorteilen gegenüber traditionellen virtuellen Maschinen in Bezug auf Startgeschwindigkeit, Ressourcennutzung und Leistung.

Fazit

Die Docker-Container-Technologie bietet eine isolierte, aber dennoch leichte Umgebung für Anwendungsprozesse durch die Namespace- und Cgroups-Technologie. Diese Technologie ermöglicht es Containern, schnell zu starten, effizient zu laufen und die Isolation vom Host und anderen Containern aufrechtzuerhalten, was sie zu einer unverzichtbaren Technologie in modernen Cloud-Computing- und Microservices-Architekturen macht.

Novita AI*, die All-in-One-Plattform für grenzenlose Kreativität, die Ihnen Zugang zu über 100 APIs bietet. Von Bildgenerierung und Sprachverarbeitung bis hin zu Audioverbesserung und Videobearbeitung, günstig nach Pay-as-you-go-Modell, befreit Sie von der Wartung der GPU, während Sie Ihre eigenen Produkte entwickeln. Testen Sie es kostenlos.