Verstehen Sie, was es bedeutet, einen Linux-Namespace über $ podman pod create --share-Namespace freizugeben.

Letztes Mal Als ich untersuchte, wie Pods für die Integration mehrerer Container in Podman behandelt werden sollen, podman-pod-create / markdown / podman-pod-create.1.md) Es ist einfach, weil ich nicht genau wusste, was der "Namespace" mit der Option "--share" des Befehls geteilt hat. Ich habe versucht, es mit praktischen Übungen intuitiv verständlich zu machen.

Einführung

Ich habe diesen Artikel mit dem Ziel geschrieben, bis zum Ende des Lesens Folgendes zu verstehen.

--Was ist der Linux-Namespace, mit dem die Containertechnologie realisiert wird? ――Was ist die spezifische Situation, wenn der Namespace gemeinsam genutzt / getrennt wird? --Was verwalten die fünf Namespaces ipc, net, pid, user und uts, die beim Erstellen eines Pods durch Podman gemeinsam genutzt / isoliert werden können?

Was ist --share * Namespace *?

Dies ist eine der Optionen, die beim Erstellen eines Pods mit dem Befehl podman pod create verwendet werden können. Die Rolle und das Format entsprechen den Angaben im Repository [libpod](https://github.com/containers/podman/blob/master/docs/source/markdown/podman-pod-create.1.md erstellen).

####--share=namespace A comma delimited list of kernel namespaces to share. If none or "" is specified, no namespaces will be shared. The namespaces to choose from are ipc, net, pid, user, uts.

Ah ich sehe. ** Ich verstehe voll und ganz. ** Es ist nur eine Erklärung, aber es scheint, dass einige vorausgesetzte Kenntnisse erforderlich sind, um es zu verstehen.

Was ist überhaupt ein Namespace?

Oma sagte. Wenn Sie etwas nachschlagen, schauen Sie es sich aus der Primärquelle an. Laut Namespaces-Manpage ist dies wie folgt.

Der Namespace ist ein Mechanismus, der die globalen Systemressourcen mit einer Abstraktionsebene abdeckt, damit die Prozesse im Namespace so aussehen, als hätten sie ihre eigenen separaten globalen Ressourcen. Änderungen an globalen Ressourcen sind für andere Prozesse sichtbar, die Mitglieder des Namespace sind, jedoch nicht für andere Prozesse. Eine Verwendung von Namespaces besteht darin, Container zu implementieren.

Hmmm. Das war der Fall. Ich wusste es. Das ist wahr! Dann werde ich am Beispiel des PID-Namespace erklären! ??

Mit anderen Worten, wenn sich an einer bestimmten Schule zwei Yutas in derselben Klasse befinden, wird nicht eindeutig festgelegt, auf welche Yutas sie bei ihrer Berufung hinweisen sollen. Dies bedeutet, dass keine Kollision ** vorliegt, da sie in Gruppen B unterteilt ist und existiert.

Beispiele für die Verwendung von Namespaces

Wenn Sie diesen Mechanismus verwenden, um einen vom Host getrennten Speicherplatz nicht nur für Prozesse, sondern auch für verschiedene Ressourcen zu sichern ... Er funktioniert auf dem Host, obwohl er keine Hardware emuliert ** Virtual Haben Sie das Gefühl, dass Sie so etwas wie eine Maschine herstellen können **? Da es sich so verhält, als wäre es eine separate Maschine, sollte es nicht seltsam sein, zum Beispiel die folgenden Funktionen zu haben ... oder es ist seltsam, dass dies nicht der Fall ist. Dies sollte durch Trennen der Namespaces möglich sein.

Wie Sie vielleicht bemerkt haben, ist das Ausführen von Prozessen in einem vom Host getrennten Bereich für verschiedene Ressourcen das, was Containertechnologie wirklich ist. "Abgesehen von der Trennung vom Host ist es jedoch unpraktisch, wenn Sie mit mehreren Prozessen zusammenarbeiten möchten, wenn alles eng zwischen Containern getrennt ist", sodass einige Namespaces von mehreren Containern gemeinsam genutzt werden. Der Pod ist eine bequeme Möglichkeit, damit umzugehen.

Im nächsten Kapitel werden wir den Unterschied zwischen der Freigabe eines Namespace und der Nichtfreigabe untersuchen, indem wir in Podman einen Pod erstellen und die Unterschiede im Verhalten der Container im Pod vergleichen.

network namespace

Der Netzwerk-Namespace ist ein Mechanismus zum Trennen von Informationen über das Netzwerk, z. B. NIC, Routing-Tabelle und Firewall-Richtlinieneinstellungen.

Überprüfen Sie zunächst den auf dem Betriebssystem vorhandenen Netzwerk-Namespace mit dem folgenden Befehl. Es wird nichts ausgegeben. Dies bedeutet, dass der Netzwerk-Namespace noch nicht erstellt wurde.

# ip netns

--Netz für Pods teilen

Erstellen Sie ein Pod-Netshared, das den Netzwerk-Namespace mit podman teilt. Konfigurieren Sie die Portweiterleitung auch so, dass sie von 8080 auf der Hostseite auf 80 auf dem Pod weitergeleitet wird. Im Pod wird ein Apache-Container namens net1 ausgeführt.

# podman pod create --name netshared --share net -p 8080:80
# podman run --pod netshared --rm -d -name net1 httpd

Sie können sehen, dass der Infrastrukturcontainer und der httpd-Container erstellt wurden. Der Infrastrukturcontainer ist ein Pod-Verwaltungscontainer zum Speichern des dem Pod zugeordneten Namespace. Es ist immer im Schlaf und tut im Grunde nichts.

# podman container ls -a
CONTAINER ID  IMAGE                           COMMAND           CREATED         STATUS                         PORTS                 NAMES
6d320abc7fa5  docker.io/library/httpd:latest  httpd-foreground  41 seconds ago  Up 40 seconds ago              0.0.0.0:8080->80/tcp  net1
76630b31f5c6  k8s.gcr.io/pause:3.1                              51 seconds ago  Up 41 seconds ago              0.0.0.0:8080->80/tcp  d1d99b6ed720-infra

Lassen Sie uns die IP-Adressen des Infrastrukturcontainers und des net1-Containers herausfinden. Dem Infrastrukturcontainer wird die IP-Adresse `` `10.88.0.83 / 16``` zugewiesen, dem net1-Container jedoch nicht.

# podman inspect d1d99b6ed720-infra | grep -E "^.*\"IPAddress" -A1
            "IPAddress": "10.88.0.83",
            "IPPrefixLen": 16,
            "IPv6Gateway": "",
# podman inspect net1  | grep -E "^.*\"IPAddress" -A1
            "IPAddress": "",
            "IPPrefixLen": 0,

Nachdem wir den Pod erstellt haben, überprüfen wir den Netzwerk-Namespace erneut. Sie können sehen, dass ein neuer Netzwerk-Namespace erstellt wurde.

# ip netns
cni-07de2651-2761-c638-a1fd-2af594ad9503 (id: 0)

Dieser Netzwerk-Namespace wird von dem zuvor erstellten Pod-Netshared verwendet. Wenn Sie den Befehl `` `ip a``` in diesem Netzwerk-Namespace ausführen, werden Informationen zur netshared virtual NIC zurückgegeben.

# ip netns exec cni-07de2651-2761-c638-a1fd-2af594ad9503 ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
3: eth0@if85: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:71:25:ce:de:49 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 10.88.0.83/16 brd 10.88.255.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::71:25ff:fece:de49/64 scope link
       valid_lft forever preferred_lft forever

eth0@if85 ist 10.88.0.83/Sie haben 16 IP-Adressen. Es entspricht der IP des zuvor überprüften Infrastrukturcontainers.



 Mal sehen, ob die Portweiterleitung auch funktioniert.

curl localhost:8080

It works!

```

Die Apache-Testseite ist zurück. Die Antwort wird zurückgegeben, obwohl der Apache-Container keine IP-Adresse hatte, da der Apache-Container die virtuelle Netzwerkkarte des Infrastrukturcontainers gemeinsam nutzt.

--share none Für Pods

Erstellen Sie diesmal auf die gleiche Weise einen Pod, der keinen Namespace gemeinsam hat. Es gibt nichts Besonderes, außer dass die Portweiterleitung jetzt "9090-> 80" und "--share none" ist.

# podman pod create --name none --share none -p 9090:80
# podman run --pod none --rm -d --name none1 -d httpd
# podman start 55db2b908174-infra
# podman container ls -a
CONTAINER ID  IMAGE                           COMMAND           CREATED         STATUS             PORTS                 NAMES
8b91672858a9  docker.io/library/httpd:latest  httpd-foreground  4 minutes ago   Up 4 minutes ago                         none1
f4069bf6aad1  k8s.gcr.io/pause:3.1                              4 minutes ago  Up 3 minutes ago   0.0.0.0:9090->80/tcp  55db2b908174-infra
6d320abc7fa5  docker.io/library/httpd:latest  httpd-foreground  10 minutes ago  Up 40 seconds ago              0.0.0.0:8080->80/tcp  net1
76630b31f5c6  k8s.gcr.io/pause:3.1                              10 minutes ago  Up 41 seconds ago              0.0.0.0:8080->80/tcp  d1d99b6ed720-infra

Wenn Sie sich auf die Spalte PORTS konzentrieren, gibt es im Apache-Container keine Einstellung für die Portweiterleitung wie im Netshared-Pod. Die Portweiterleitungseinstellung mit der Option -p, die beim Erstellen des Pods angegeben wurde, entspricht der Weiterleitungseinstellung für den Infrastrukturcontainer. Außerdem scheint es nicht an den Apache-Container weitergeleitet zu werden, da die virtuellen Netzwerkkarten des Infrastrukturcontainers und des Apache-Containers nicht gemeinsam genutzt werden. Was passiert mit der virtuellen Netzwerkkarte des Apache-Containers, wenn dieser nicht freigegeben ist?

Finden Sie die IP des Containers heraus, der zum none-Pod gehört.

# podman inspect 55db2b908174-infra | grep -E "^.*\"IPAddress" -A1
            "IPAddress": "10.88.0.85",
            "IPPrefixLen": 16,
# podman inspect none1 | grep -E "^.*\"IPAddress" -A1
            "IPAddress": "10.88.0.84",
            "IPPrefixLen": 16,

Im Netshared Pod hatte nur der Infrastrukturcontainer eine IP-Adresse, aber jetzt haben beide Container eine IP-Adresse. Der Apache-Container scheint eine eigene virtuelle Netzwerkkarte zu haben. Wenn der Netzwerk-Namespace nicht im Pod freigegeben ist, wächst der eindeutige Netzwerk-Namespace möglicherweise jedes Mal weiter, wenn ein Container erstellt wird?

ip netnsLassen Sie uns mit überprüfen.

# ip netns 
cni-209074d8-5a08-7f59-bb73-6b258c228cf4 (id: 2)
cni-dc45758c-a9e2-91a2-db2c-a0f3406b9568 (id: 1)
cni-07de2651-2761-c638-a1fd-2af594ad9503 (id: 0)

Zusätzlich zum Netzwerk-Namespace für den Netshared Pod wurden zuvor zwei Netzwerk-Namespaces erstellt.

Sie können die virtuelle Netzwerkkarte mit den letzten 84 Adressen im Netzwerk-Namespace mit der ID: 1 sehen. Dies ist aus dem Infrastrukturcontainer ohne Pod.

id1


# ip netns exec cni-dc45758c-a9e2-91a2-db2c-a0f3406b9568 ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
3: eth0@if86: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 7a:11:aa:8e:52:ef brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 10.88.0.84/16 brd 10.88.255.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::7811:aaff:fe8e:52ef/64 scope link
       valid_lft forever preferred_lft forever

Sie können die virtuelle Netzwerkkarte mit den letzten 85 Adressen im Netzwerk-Namespace mit der ID: 2 sehen. Dies ist aus dem none1-Container, in dem Apache ausgeführt wird.

id2


# ip netns exec cni-209074d8-5a08-7f59-bb73-6b258c228cf4 ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
3: eth0@if87: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether b2:93:94:3c:05:7e brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 10.88.0.85/16 brd 10.88.255.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::b093:94ff:fe3c:57e/64 scope link
       valid_lft forever preferred_lft forever

Überprüfen Sie auch die Funktion der Portweiterleitung. Im Gegensatz zum Netshared Pod reagiert Curl auf localhost: 9090 nicht von Apache. Dies liegt daran, dass sich der schlafende Infrastrukturcontainer kräuselt. In dieser Hinsicht kann die Curl zu localhost: 8080, die im Netshared-Pod durchgeführt wurde, als Curl zu demselben Infrastrukturcontainer bezeichnet werden, aber der Netshared-Pod bezieht sich auf den Apache-Container, da der Infrastrukturcontainer und der Apache-Container die virtuelle Netzwerkkarte gemeinsam nutzen. Die Anfrage ist angekommen. Es ist, als ob mehrere Container verbunden sind und als eine virtuelle Maschine arbeiten.

Beachten Sie, dass Sie eine Antwort erhalten, wenn Sie direkt zu none1 (10.88.0.84) locken, wo Apache ausgeführt wird, sodass Apache selbst zu funktionieren scheint.

# curl localhost:9090
curl: (7) Failed to connect to localhost port 9090:Verbindung abgelehnt
# curl 10.88.0.84
<html><body><h1>It works!</h1></body></html>
# curl 10.88.0.85
curl: (7) Failed to connect to 10.88.0.85 port 80:Verbindung abgelehnt

Ich werde es nur für den Fall überprüfen, aber es scheint nicht von Firewalld gespielt worden zu sein.

# firewall-cmd --list-all --zone=public | grep -E "^\s*ports"
  ports: 8080/tcp 9090/tcp

Wir konnten das Verhalten bestätigen, wenn der Netzwerk-Namespace nicht von Containern gemeinsam genutzt wird.

uts namespace

Ein Namespace, der Hostnamen und NIS-Domänennamen trennt.

UTS steht für Unix Time-Sharing System (ein Mechanismus, der unter UNIX verwendet wird, um einen Computer mit mehreren Benutzern zu verwalten), aber seine Bedeutung scheint jetzt verloren zu sein. Zeit spielt keine Rolle.

NIS ist ein Mechanismus zur zentralen Verwaltung mehrerer Computer, und die NIS-Domäne ist eine Kennung für diesen Mechanismus. Dieses Mal konzentrieren wir uns auf die Trennung von Hostnamen.

--share uts für pods

Erstellen Sie einen Pod utsshared, der den uts-Namespace gemeinsam nutzt, und erstellen Sie einen Apache-Container uts1 und einen CentOS7-Container uts2.

# podman pod create --name utsshared --share uts
# podman run -d --pod utsshared --name uts1 --rm httpd
# podman run -it -d --pod utsshared --name uts2 --rm centos:7

Zeigt die Hostnamen für uts1 und uts2 an. Es wurde utsshared zurückgegeben, was dem Pod-Namen entspricht. Es scheint sicher, dass der uts-Namespace gemeinsam genutzt wird.

# podman exec uts1 hostname
utsshared
# podman exec uts2 hostname
utsshared

--share none Für Pods

Erstellen wir eine ähnliche Umgebung mit dem zuvor erstellten Nicht-Pod und zeigen den Hostnamen an.

# podman exec none1 hostname
8b91672858a9
# podman exec none2 hostname
692b66d45c4a

Die Hostnamen für none1 und none2 hatten denselben Inhalt wie ihre eigene Container-ID. Es kann gesagt werden, dass der uts-Namespace nicht gemeinsam genutzt wird.

ipc namespace

Namespace für die prozessübergreifende Kommunikation. Wenn der IPC-Namespace gemeinsam genutzt wird, ist eine Kommunikation zwischen Prozessen möglich. Container, die nicht zum selben Pod gehören, und Container zu Hosts werden normalerweise getrennt, aber Container, die zum selben Pod gehören, teilen sich einen IPC-Namespace, sodass eine Kommunikation zwischen Prozessen möglich ist.

Ich habe dieses Bild ausgeliehen, um die IPC-Kommunikation im selben Pod zu demonstrieren. https://github.com/allingeek/ch6_ipc/tree/e9fa9a13198903bebcd983bf88bcb75950823d85

allingeek/ch6_ipc


FROM ubuntu:latest
RUN apt-get update && apt-get -y install gcc libc-dev
COPY . /work/ipc
WORKDIR /work/ipc
RUN gcc -o ipc ipc.c -lrt
ENTRYPOINT ["./ipc"]

Dies ist ein Ubuntu-Image mit einer ausführbaren Datei namens "ipc". ipcZum Zeitpunkt der Ausführung-producerSendet eine Zufallszahlennachricht und eine Endnachricht. ipcZum Zeitpunkt der Ausführung-consumerMit-producerEmpfängt die Nachrichtenausgabe von und zeigt sie in der Standardausgabe an.

--share ipc pod

Erstellen Sie wie gewohnt einen Pod-ipcshared, der den ipc-Namespace gemeinsam nutzt, wobei ipc1 `-producer``` und ipc2` -consumer``` darin ist.

# podman pod create --name ipcshared --share ipc
# podman run -d --pod ipcshared --name ipc1 --entrypoint /work/ipc/ipc ch6_ipc -producer
# podman run -d --pod ipcshared --name ipc2 --entrypoint /work/ipc/ipc ch6_ipc -consumer

Überprüfen Sie die Protokolldatei, um festzustellen, ob Sie senden und empfangen können.

# podman logs --tail 5 ipc1 | tac
Produced: 86 
Produced: 86
Produced: 67
Produced: 2b 
Produced: b9 

# podman logs --tail 6 ipc2 | tac
Consumed: 86
Consumed: 86
Consumed: 67
Consumed: 2b
Consumed: b9
Consumed: done

Die von Hersteller und Verbraucher ausgegebenen Zahlen stimmen überein. Ich konnte bestätigen, dass das Senden und Empfangen korrekt durchgeführt wurde.

--share none Für Pods

Machen Sie dasselbe für keine Pods, die den IPC-Namespace nicht gemeinsam nutzen. Hier kann der Verbraucher die Nachricht nicht empfangen.

# podman pod create --name none --share none
# podman run -d --pod ipcshared --name ipc1 --entrypoint /work/ipc/ipc ch6_ipc -producer
# podman run -d --pod ipcshared --name ipc2 --entrypoint /work/ipc/ipc ch6_ipc -consumer
# podman logs --tail 5 ipc_unshare1
Produced: 9c
Produced: 98
Produced: 53
Produced: b9
Produced: 45
# podman logs --tail 6 ipc_unshare2
Either the producer has not been started or maybe I cannot access the same memory...

Die Trennung des IPC-Namespace verhinderte die Kommunikation der Prozesse im Pod.

user namespace Ein Namespace, der UIDs und GIDs trennt. Betrachten des Dokuments Dies schien ebenfalls durcheinander zu sein, aber es scheint, dass es noch nicht implementiert wurde.

# podman pod create --name usershared --share user
Error: unable to create pod: User sharing functionality not supported on pod level
# podman pod create --share help
Error: unable to create pod: Invalid kernel namespace to share: help. Options are: net, pid, ipc, uts or none

pid namespace

Dies ist der Namespace für die am Anfang genannten Prozessnummern.

--share pid Für Pods

Erstellen Sie einen Pod-Pidshared mit einem gemeinsam genutzten PID-Namespace. Der Apache-Container sei pid1, der MySQL-Container sei pid2 und der CentOS7-Container sei pid3 und gehe in pid3.

# podman pod create --share pid --name pidshared
# podman run -d --pod pidshared --name pid1 --rm httpd
# podman run -d --pod pidshared --name pid2 --rm -e MYSQL_ROOT_PASSWORD=password mysql
# podman run -it --pod pidshared --name pid3 --rm centos:7 /bin/bash
[container_id /]#

Überprüfen Sie den Prozess.

[container_id /]# ps -ef
root         1     0  0 01:33 ?        00:00:00 /pause
root       114     0  0 01:44 ?        00:00:00 httpd -DFOREGROUND
bin        120   114  0 01:44 ?        00:00:00 httpd -DFOREGROUND
bin        121   114  0 01:44 ?        00:00:00 httpd -DFOREGROUND
bin        122   114  0 01:44 ?        00:00:00 httpd -DFOREGROUND
999        284     0  1 01:48 ?        00:00:02 mysqld
root       484     0  4 01:51 pts/0    00:00:00 /bin/bash
root       499   484  0 01:51 pts/0    00:00:00 ps -ef

Sie können die Prozesse httpd und mysqld sehen, die in anderen Containern ausgeführt werden.

--share none Für Pods

Machen Sie dasselbe für den Nicht-Pod.

# podman pod create --name none
# podman run -d --pod none --name none1 --rm httpd
# podman run -d --pod none --name none2 --rm -e MYSQL_ROOT_PASSWORD=password mysql
# podman run -it --pod none --name none3 --rm centos:7 /bin/bash
[container_id /]#
[container_id /]# ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0 12 02:02 pts/0    00:00:00 /bin/bash
root        14     1  0 02:02 pts/0    00:00:00 ps -ef

Ich kann nur die Prozesse sehen, die im pid3-Container ausgeführt werden. Dies liegt daran, dass der PID-Namespace nicht freigegeben wird.

schließlich

Podman erstellte Pods mit drei gemeinsam genutzten Standard-Namespaces: net, uts und ipc. Daher weist der Standard-Pod die folgenden Eigenschaften auf.

Mit anderen Worten, die Container im Pod sehen im Gegensatz zu den nicht verbundenen Containern, die nicht zum Pod gehören, wie derselbe Computer ** im Netzwerk ** aus und ** können über Interprozesskommunikation (IPC) ** kommunizieren. Es bedeutet, dass es gibt. Sie haben die Unannehmlichkeiten überwunden, die durch das Prinzip verursacht werden, dass ein Prozess in einem Container ausgeführt werden soll, indem Sie einige Namespaces zwischen den Containern gemeinsam nutzen. In Bezug auf das Prinzip des 1-Container-1-Prozesses gibt es verschiedene Gründe, wie z. B. das Problem und die Bequemlichkeit von PID 1, wenn davon ausgegangen wird, dass der Container wegwerfbar ist, aber der Spielraum zu eng ist, um ihn hier zu schreiben.

Referenz

Ich habe es als Referenz verwendet, um die IPC-Kommunikation zu demonstrieren.

Prozessübergreifende Kommunikation von Containern im selben Pod durch Kubernetes https://qiita.com/mamorita/items/15437a1dbcc00919fa4e

Recommended Posts

Verstehen Sie, was es bedeutet, einen Linux-Namespace über $ podman pod create --share-Namespace freizugeben.
Versuchen Sie, einen neuen Befehl unter Linux zu erstellen
Wenn Sie eine SSD mit Linux verbinden und einen Dateiserver erstellen, ist es besser, NTFS zu verwenden.
So erstellen Sie ein lokales Repository für Linux