Linux Mount Namespaces sind ein zentrales Element moderner Container-Technologie und ermöglichen es, unterschiedliche Dateisystemansichten für einzelne Prozesse zu schaffen. Durch die Nutzung von Mount Namespaces kann man dafür sorgen, dass Prozesse isoliert in einem eigenen Dateisystemumfeld arbeiten, was besonders wichtig ist für Container-Anwendungen und Sicherheitskonzepte. Bei der gewöhnlichen Verwendung von Namespaces sind diese jedoch eng an die Lebensdauer von Prozessen gebunden. Sobald der letzte Prozess, der einem Namespace zugeordnet ist, beendet wird, verschwindet auch der Namespace. Diese temporäre Natur stellt eine Herausforderung dar, wenn es darum geht, Namespaces über die Lebensdauer einzelner Prozesse hinaus persistent zu halten.
Genau hier setzt die Bind-Mount-Technik an, die es erlaubt, einen Namespace über die virtuelle Datei im „/proc“-Verzeichnis eines Prozesses in einen dauerhaften Pfad auf dem Dateisystem zu binden. Dieser Ansatz erweitert die Nutzbarkeit von Mount Namespaces deutlich und eröffnet neue Möglichkeiten in der Orchestrierung und Verwaltung von Container-Umgebungen sowie in der Systemadministration Linux-basierter Systeme. Zunächst ist es wichtig zu verstehen, wie Linux Mount Namespaces konzipiert sind. Sie isolieren die Mount-Punkte, also jene Strukturen, mit denen Dateisysteme ins System eingebunden werden. Prozesse innerhalb eines bestimmten Mount Namespace sehen nur die Mount-Points, die in diesem Namespace definiert sind, und sind von den übrigen Mounts des Systems abgeschottet.
Falls man also in einem Namespace ein temporäres Dateisystem mountet, ist dieses nur in diesem Namespace sichtbar, nicht aber in der globalen oder anderen Namespaces. Diese Eigenschaft wird häufig genutzt, um Umgebungen zu schaffen, in denen Anwendungen ihre eigene, abgesicherte Dateisystemansicht haben, ohne dass Änderungen andere Anwendungen oder den Host beeinflussen. Ein Problem entsteht jedoch dadurch, dass Namespaces standardmäßig mit dem Start eines Prozesses entstehen und mit dessen Ende wieder verschwinden. Das bedeutet, dass alle Mountänderungen, die in einem Namespace durchgeführt werden, nur so lange bestehen, wie der Namespace selbst existiert. Für viele Anwendungsfälle ist es jedoch sinnvoll, einen Namespace weiterzuführen, auch wenn der ursprüngliche Prozess beendet wurde.
Ein praktisches Beispiel ist die Entwicklung von selbstgebauten Containern oder die Erstellung von isolierten Umgebungen für Tests, bei denen man eine Dateisystemstruktur dauerhaft erhalten möchte, ohne ständig Prozesse offen zu halten. Um Namespaces persistent zu machen, bietet Linux eine elegante Möglichkeit: Die virtuelle Datei, die den Namespace eines Prozesses im Verzeichnis „/proc/PID/ns/“ darstellt, kann via Bind-Mount an einen anderen Ort im Dateisystem gebunden werden. Die so gebundene Datei bleibt bestehen, selbst wenn der ursprüngliche Prozess beendet wird, solange der Mount bestehen bleibt. Diese Technik erlaubt es, Namespaces quasi 'zu konservieren' und später von anderen Prozessen wieder zu verwenden. Ein weiterer wesentlicher Aspekt bei der Persistenz von Mount Namespaces ist die Propagation der Mounts.
Linux kennt verschiedene Propagationstypen wie „shared“, „private“ oder „slave“, die beeinflussen, wie Mountänderungen zwischen unterschiedlichen Mount-Namespaces weitergegeben werden. Für die Bind-Mounts, die zur Persistenz genutzt werden, ist es erforderlich, dass der Zielordner, an den der Namespace gebunden wird, die Propagationseigenschaft „private“ hat. Ist dieser Punkt nicht beachtet, kann es zu unerwartetem Verhalten kommen, da Mount-Änderungen sonst doch auf andere Mount-Punkte durchschlagen können. Hierfür sorgt man zum Beispiel mit dem Befehl mount --bind --make-private, der eine spezielle Bind-Mount-Konfiguration erzeugt und somit dafür sorgt, dass die Persistenz korrekt funktioniert. Die praktische Arbeit mit persistenten Mount Namespaces lässt sich gut anhand eines Beispiels beschreiben.
Man beginnt mit dem Anlegen eines Verzeichnisses, das als Ziel für die Bind-Mounts dienen soll. Dort wird mittels Bind-Mounts die private Mount-Propagation sichergestellt. Anschließend wird eine leere Datei erzeugt, denn Namespaces müssen an reguläre Dateien gebunden werden, nicht an Verzeichnisse. Danach nutzt man das unshare-Tool, um einen neuen Mount Namespace zu erstellen und ihn dabei direkt als Mount unter der erzeugten Datei persistent zu machen. In dieser neuen Namespace-Umgebung kann man beispielsweise ein tmpfs mounten und Dateien ablegen, die ausschließlich in diesem Namespace sichtbar sind.
Das interessante Verhalten zeigt sich anschließend in einem zweiten Terminal, das außerhalb dieses Namespaces operiert. Dort sind die im neuen Namespace angelegten Mounts völlig unsichtbar, wodurch die Isolation demonstriert wird. Mit dem Befehl nsenter kann man von anderen Prozessen aus jederzeit wieder in den persistenten Namespace eintreten und auf die dort erzeugten Dateien und Mount-Punkte zugreifen. Somit ist eine temporäre Isolation gewährleistet, die bei Bedarf wieder aufgebrochen und modifiziert werden kann. Ein wichtiger Hinweis betrifft die Verwaltung und Identifikation von Namespaces.
Jeder Namespace verfügt über eine einzigartige Identifikationsnummer, die sich über das Dateisystem unter /proc sichtbar machen lässt. Der Befehl readlink auf die Datei /proc/$$/ns/mnt zeigt eine Zeichenkette mit einer solchen ID an. Diese IDs sind hilfreich, wenn man Namespaces überwachen oder gezielt verwalten möchte, gerade wenn mehrere Namespaces parallel existieren. Das Werkzeug lsns listet alle aktuell auf dem System existierenden Namespaces auf und kann durch Filterung auf den Typ „mnt“ spezialisiert werden. Eine Besonderheit ist, dass in manchen Versionen von util-linux das Werkzeug lsns keine Mount Namespaces mit null assoziierten Prozessen anzeigen konnte.
Dieses Verhalten wurde jedoch in neueren Versionen behoben, sodass nun auch die noch nicht genutzten oder soeben persistenzierten Namespaces sichtbar bleiben. So erhält man bessere Kontrolle über die Namespaces, auch wenn sie gerade nicht active Prozessbezug besitzen. Neben der Persistenz über Bind-Mounts besteht zudem die Möglichkeit, Namespace-Dateideskriptoren in Programmen zu halten, wodurch man ebenfalls Namespaces am Leben erhalten kann, die keinen aktiven Prozess direkt referenzieren. Diese Möglichkeit ist beispielsweise in fortgeschrittenen Containermanagement-Tools von Vorteil, wenn es darum geht, Namespaces unabhängig von Prozessen zu verwalten und Ressourcen gezielt freizugeben. Linux Mount Namespaces sind also ein mächtiges Werkzeug, das weit über das Containerisieren von Software hinausgeht.