Als Fortsetzung der Namespaces-Serie behandelt dieser Artikel die PID Namensraum. Wenn Sie einen allgemeinen Überblick über alle Namespaces wünschen, lesen Sie den ersten Artikel. Zuvor haben Sie ein neues mnt erstellt Namensraum. Interessanterweise, wie Sie festgestellt haben, sogar nach dem Erstellen eines neuen mnt Namespace hatten Sie immer noch Zugriff auf die Prozess-IDs (PIDs) des ursprünglichen Hosts. Als Sie versucht haben, die Datei /proc bereitzustellen Namespace erhalten Sie die ziemlich verwirrende Berechtigung verweigert Fehler, wie unten zu sehen:
root@new-mnt$ mount -t proc proc /proc
mount: permission denied (are you root?)
root@new-mnt$ whoami
root
Während Sie alle Arten von Mounts im neuen Mount-Namespace erstellen konnten, konnten Sie /proc nicht interagieren oder ändern . In diesem Artikel gehe ich Schritt für Schritt durch die PID Namespace und demonstrieren Sie, wie Sie ihn zusammen mit dem mnt verwenden können Namespace, um Ihren noch jungen Container weiter zu sichern.
[ Den Lesern gefiel auch:Wie Linux-PID-Namespaces mit Containern funktionieren ]
Was sind Prozess-IDs?
Bevor Sie direkt in die PID springen Namensraum, ich denke, es ist eine gute Idee, nur ein wenig Hintergrund zu geben, warum dieser Namensraum wichtig ist.
Wenn ein Prozess auf den meisten Unix-ähnlichen Betriebssystemen erstellt wird, erhält er eine bestimmte numerische Kennung, die als Prozess-ID bezeichnet wird (PID). Diese PID hilft dabei, einen Prozess eindeutig zu identifizieren, selbst wenn es zwei Prozesse gibt, die denselben menschenlesbaren Namen haben. Wenn beispielsweise mehrere SSH-Sitzungen auf einem System aktiv sind und Sie eine bestimmte Verbindung schließen müssen, bietet die PID dem Administrator eine Möglichkeit, sicherzustellen, dass die richtige Sitzung geschlossen wird.
Alle diese Prozesse werden in einem speziellen Dateisystem namens procfs
verfolgt . Während dieses Dateisystem technisch gesehen überall gemountet werden kann, erwarten die meisten Tools (und Konventionen) die procfs
unter /proc
einzuhängen . Wenn Sie eine Auflistung von /proc
machen , sehen Sie einen Ordner für jeden Prozess, der derzeit auf Ihrem System ausgeführt wird. In diesem Ordner befinden sich alle Arten von speziellen Dateien, die zum Verfolgen verschiedener Aspekte des Prozesses verwendet werden. Für die Zwecke dieses Artikels sind diese Dateien nicht wichtig. Es genügt zu wissen, dass /proc
Hier speichern die meisten Unix-ähnlichen Systeme Informationen zu Prozessen auf einem laufenden System.
Der PID-Namensraum
Einer der Hauptgründe für die PID Namespace soll eine Prozessisolierung ermöglichen. Genauer gesagt, wie die Manpage sagt:
PID-Namensräume isolieren den Prozess-ID-Nummernraum, was bedeutet, dass Prozesse in verschiedenen PID-Namensräumen dieselbe PID haben können.
Dies ist wichtig, da dadurch garantiert werden kann, dass Prozesse keine widersprüchliche PID mit anderen Prozessen haben. Bei Betrachtung eines einzelnen Systems besteht natürlich keine Möglichkeit, dass PIDs in Konflikt geraten, da das System die Prozess-ID-Nummer kontinuierlich erhöht und niemals dieselbe Nummer zweimal zuweist. Beim Umgang mit Containern auf mehreren Computern wird dieses Problem deutlicher. Wie in der Manpage beschrieben:
PID-Namespaces ermöglichen es Containern, Funktionen wie das Anhalten/Fortsetzen der Reihe von Prozessen im Container und das Migrieren des Containers auf einen neuen Host bereitzustellen, während die Prozesse innerhalb des Containers dieselben PIDs beibehalten.
Abgesehen von der Isolierung funktioniert das PID-System fast identisch mit dem außerhalb des Namensraums. Die Prozess-IDs innerhalb des neuen Namespace beginnen bei 1 , wobei der erste Prozess als init betrachtet wird Prozess. Die init Der Prozess wird ganz anders gehandhabt als alle anderen PIDs auf einem Host. Dies hat besondere Auswirkungen auf das laufende System, die außerhalb des Rahmens dieser Serie liegen. Wenn Sie an weiteren Informationen interessiert sind, lesen Sie den Abschnitt "Signale und der Init-Prozess" des Artikels LWN-Namespaces.
Bemerkenswert ist jedoch, dass jeder Prozess die PID 1 hat ist entscheidend für die Langlebigkeit der Namespaces. Wenn PID 1 aus irgendeinem Grund beendet wird, sendet der Kernel ein SIGKILL
zu allen verbleibenden Prozessen im Namespace, wodurch dieser Namespace effektiv heruntergefahren wird.
Erkunden von PID-Namespaces
Wenn Sie sich wie ich fragen, ob Sie PID verschachteln können Namespaces, lautet die Antwort ja. Tatsächlich macht der Kernel Platz für bis zu 32 verschachtelte PID Namensräume. Dies wird als einseitige Beziehung betrachtet. Das bedeutet, dass der Elternteil die PIDs von Kindern, Enkelkindern usw. sehen kann. Er kann jedoch keine der PIDs seiner Vorfahren sehen. Beachten Sie Folgendes:
[user@localhost ~] sudo unshare -fp /bin/bash
[root@localhost ~] sleep 90000 &
[root@localhost ~] ps -ef
UID PID PPID C STIME TTY TIME CMD
[truncated ]
.....
root 11627 11620 0 09:16 pts/0 00:00:00 sudo unshare -fp /bin/bash
root 11633 11627 0 09:17 pts/0 00:00:00 unshare -fp /bin/bash
root 11634 11633 0 09:17 pts/0 00:00:00 /bin/bash
root 11639 11634 0 09:17 pts/0 00:00:00 sleep 90000
root 11641 11634 0 09:17 pts/0 00:00:00 ps -ef
[root@localhost ~] sudo unshare -fp /bin/bash
[root@localhost ~] sleep 8000 &
[root@localhost ~] ps -ef
[truncated ]
.....
UID PID PPID C STIME TTY TIME CMD
root 11650 11634 0 09:17 pts/0 00:00:00 sudo unshare -fp /bin/bash
root 11654 11650 0 09:17 pts/0 00:00:00 unshare -fp /bin/bash
root 11655 11654 0 09:17 pts/0 00:00:00 /bin/bash
root 11661 11655 0 09:17 pts/0 00:00:00 sleep 8000
root 11671 11655 0 09:17 pts/0 00:00:00 ps -ef
Sie werden feststellen, dass ich die Ausgabe abgeschnitten habe, weil die PID Namespace erscheint vollen Zugriff auf alle PIDs in /proc
zu haben . Beobachten Sie, was passiert, wenn Sie versuchen, einen Prozess zu stoppen, der sich in einem Vorfahren befindet:
[root@localhost ~] kill -9 11361
bash: kill: (11361) - No such process
Warum ist das? Einfach gesagt, herkömmliche Tools wie ps
sind nicht namespace-bewusst und werden tatsächlich aus /proc
gelesen Verzeichnis. Wenn Sie ein ls /proc
gemacht haben , würden Sie immer noch alle Ordner und Dateien von vorher sehen, weil, wie im letzten Artikel besprochen, die PID Namespace erbt alle mnt Namespace-Mounts. Auf diese Situation gehe ich später ein. Kehren Sie zunächst zum vorliegenden Beispiel zurück.
Identifizieren Sie in einer anderen Shell die Schlafprozesse:
[user@localhost ~] ps -ef |grep sleep
root 11639 11634 0 09:17 pts/0 00:00:00 sleep 90000
root 11661 11655 0 09:17 pts/0 00:00:00 sleep 8000
Wenn Sie überprüfen möchten, ob sich diese Prozesse in unterschiedlichen Namespaces befinden, müssen Sie die bash
finden PID verarbeiten. Denken Sie daran, da Sie sudo unshare -fp /bin/bash
ausgeführt haben , die bash
Prozess ist die init Prozess im neuen Namensraum. Daher wird die PID mit der Namensraum-ID verknüpft. Nehmen wir die PIDs:
[root@localhost ~] ps -ef |grep bash
root 11627 11620 0 09:16 pts/0 00:00:00 sudo unshare -fp /bin/bash
root 11633 11627 0 09:17 pts/0 00:00:00 unshare -fp /bin/bash
root 11634 11633 0 09:17 pts/0 00:00:00 /bin/bash
root 11650 11634 0 09:17 pts/0 00:00:00 sudo unshare -fp /bin/bash
root 11654 11650 0 09:17 pts/0 00:00:00 unshare -fp /bin/bash
root 11655 11654 0 09:17 pts/0 00:00:00 /bin/bash
Sie können die PIDs 11634 sehen und 11655 in der Ausgabe. Wenn Sie dies mit der Ausgabe von lsns
vergleichen (Namespaces auflisten), sehen Sie Folgendes:
[root@localhost ~] lsns |grep bash
NS TYPE NPROCS PID USER COMMAND
4026532952 pid 4 11634 root /bin/bash
4026532954 pid 4 11655 root /bin/bash
Wie Sie sehen können, sind die Namespace-IDs unterschiedlich, und daher befinden sich die Prozesse in unterschiedlichen Namespaces.
Nachdem Sie nun festgestellt haben, dass die Namespaces tatsächlich unterschiedlich sind, schauen wir uns die zuvor erwähnte PID-Abstammung an. Sie können dies tun, indem Sie die NSpid identifizieren Attribut einer gegebenen PID in /proc
Verzeichnis, wie unten zu sehen:
sudo cat /proc/11655/status |grep NSpid
NSpid: 11655 6 1
Die Spalten werden von links nach rechts gelesen und geben die PID in ihren jeweiligen Namespaces an. Die PID ganz links ist der primäre oder Root-Namespace. In diesem Fall hat es eine PID von 11655 , eine sekundäre PID von 6 und eine tertiäre PID von 1 . Da die Namespaces jede untergeordnete PID besitzen Namensraum, können Sie sich das so vorstellen:
- Auf dem Host die
bash
Prozess, dersleep 8000
ausführt Befehl hat eine PID von 11655 . - Innerhalb des ersten "Containers", der
bash
Prozess, dersleep 8000
ausführt Befehl hat eine PID von 6 . - Innerhalb des verschachtelten zweiten "Containers" ist die PID 1 . Dies ist der Container, der den Prozess tatsächlich gestartet hat.
Jede dieser bash
Befehle wurde innerhalb seines eigenen Namespace erstellt, ist aber für das übergeordnete Element (in diesem Fall das Root) sichtbar Namensraum).
/proc, PID und nicht privilegierte Benutzer
Dem aufmerksamen Leser wäre aufgefallen, dass ein normaler Benutzer in den letzten beiden Artikeln beide Benutzer erstellen konnte und mnt Namensräume. In diesem Artikel habe ich den sudo
verwendet Befehl. Dies liegt daran, dass Sie keine PID erstellen können Namespace allein mit einem nicht privilegierten Benutzer. Die Antwort darauf besteht darin, mehrere Namespace-Kreationen zu einem Ereignis zusammenzufassen. Es gibt ein paar verschiedene Lösungen zum Mounten von /proc
als nicht privilegierter Benutzer.
Wenn Sie einfach versuchen, einen neuen Nutzer zu erstellen Namespace erhalten Sie ein seltsames Ergebnis:
[ user@localhost ~] unshare -Urp
-bash: fork: Cannot allocate memory
-bash-5.1# ps -ef
-bash: fork: Cannot allocate memory
-bash-5.1# ls
-bash: fork: Cannot allocate memory
Was passiert hier? Denken Sie daran, wie der erste Prozess innerhalb einer neuen PID Namespace wird zum init Prozess? In diesem Fall kann die aktuelle Shell keine Namespaces verschieben. Es existiert im Root Namespace und wann Sie eine neue PID erstellt haben Namespace, das System wusste nicht, wie es damit umgehen sollte. Die Lösung dafür ist die Prozessverzweigung selbst. Dadurch kann die aktuelle Shell ein untergeordneter Prozess von unshare
werden Befehl. Mit dem -f
Flag bewirkt, dass der Namensraum erstellt wird:
[ user@localhost ~] unshare -Urfp
[ root@localhost ~]
Sie sehen jedoch immer noch eine Kontamination von /proc
Einhängepunkt. Dafür gibt es zwei Lösungen. Zuerst könnten Sie ein neues mnt erstellen namespace und mounten Sie dann /proc
neu selbst:
[ user@localhost ~]$ unshare -Urpmf
[ root@localhost ~]# mount -t proc proc /proc
[ root@localhost ~]# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 09:31 pts/0 00:00:00 -bash
root 10 1 0 09:31 pts/0 00:00:00 ps -ef
In der Tat war dies viele Jahre lang die einzige Option, aber ein Flag --mount-proc
wurde vor einiger Zeit erstellt, um dies in einem einzigen Schritt zu tun. Die Manpage lautet:
Mounten Sie kurz vor dem Ausführen des Programms das proc-Dateisystem am Einhängepunkt (Standard ist /proc). Dies ist nützlich, wenn Sie einen neuen PID-Namespace erstellen. Es impliziert auch, einen neuen Mount-Namespace zu erstellen, da der /proc-Mount ansonsten vorhandene Programme auf dem System durcheinander bringen würde. Das neue proc-Dateisystem wird ausdrücklich als privat gemountet (mit MS_PRIVATE|MS_REC).
Daher sehen Sie möglicherweise Verweise auf den folgenden Befehl:
unshare -Urpf --mount-proc
Dadurch wird ein neues mnt erstellt Namespace beim Mounten von /proc
für dich.
Namespace eingeben
Um die Komplexität zu reduzieren, habe ich die zuvor erstellten Namespaces verlassen. Ich habe mit dem folgenden Befehl einen neuen Namensraum erstellt:
unshare -Urfp --mount-proc
Ich habe auch eine andere erstellt sleep
nur um den Namensraum zu identifizieren. Da ich nur einen einzigen neuen Namespace habe, kann ich den lsns
verwenden Befehl, um die richtige PID zu ermitteln:
[ user@localhost ~]$ lsns |grep bash
4026532965 pid 2 13142 user -bash
Führen Sie dann nsenter
aus Befehl:
sudo nsenter -t 13142 -a
Das -a
Flag teilt dem nsenter
mit Befehl, um alle Namespaces dieser PID einzugeben. sudo
wird mit dem -a
benötigt andernfalls können Sie nicht zu allen entsprechenden Namespaces wechseln. Sie sollten jetzt alle PIDS in diesem NS auflisten können:
[ root@localhost ~]$ ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 09:54 pts/0 00:00:00 -bash
root 8 1 0 09:54 pts/0 00:00:00 sleep 99999
root 25 0 0 10:15 pts/1 00:00:00 -bash
root 31 25 0 10:15 pts/1 00:00:00 ps -ef
[ Lernen Sie die Grundlagen der Verwendung von Kubernetes in diesem kostenlosen Spickzettel. ]
Abschluss
Die PID Namespace ist ein wichtiger Name, wenn es darum geht, isolierte Umgebungen zu erstellen. Es ermöglicht Prozessen, unabhängig vom Hostsystem ihre eigenen PIDs zu haben. In einer Welt, in der mehrere Hosts an der Orchestrierung isolierter Umgebungen (Container) beteiligt sein können, wird es entscheidend, über eine Einrichtung zu verfügen, die eindeutige PIDs beim Einfrieren und Migrieren von Prozessen garantiert. Darüber hinaus wird aus Sicherheitsgründen, wenn Sie Namespaces zur Anwendungsisolierung ausführen, die PID Namespace ist wichtig, um Informationslecks zu verhindern, durch die Prozesse auf einem Host ausgeführt werden können.
In Kombination mit dem Benutzer und mnt Namespaces, die PID Namespace bietet ein hohes Maß an Schutz, ohne dass Root-Rechte erforderlich sind. Moderne Browser wie Firefox und Vivaldi verwenden Namespaces, um Browser-Sandboxing bereitzustellen. Im nächsten Artikel werde ich das Netz demonstrieren Namespace und sehen Sie, wie Sie Ihren Container weiterhin manuell erstellen können, indem Sie diskrete Netzwerkkomponenten hinzufügen.