Comprendre les Namespaces Linux
Les espaces de noms sont l'une des fonctionnalités du noyau Linux qui rendent les conteneurs possibles. Dans cet article, nous allons découvrir ce que sont les espaces de noms Linux et leur fonctionnement grâce à des explications simples, des illustrations et des exemples.
Que sont les espaces de noms Linux
Espaces de noms Linux Peut être utilisé pour fournir aux processus une vue limitée de certains composants système. C'est un élément important pour isoler les processus les uns des autres. Les outils de conteneurisation comme Docker et Containerd exploitent les espaces de noms Linux pour isoler les conteneurs.

Types d'espaces de noms Linux

Selon le composant système dont nous souhaitons restreindre l'affichage des processus, nous devons utiliser des types d'espaces de noms spécifiques. Les types d'espaces de noms disponibles sur le système sont les suivants :
$ lsns -o TYPE
TYPE
time # Virtualizes the view on some of the system clocks values
ipc # Virtualizes the view on System V IPC and POSIX message queues
cgroup # Virtualizes the view on Cgroups
user # Virtualizes the view on user and group IDs
net # Virtualizes the view on Network devices, stacks, ports, etc
uts # Virtualizes the view on hostname and NIS domain name
mnt # Virtualizes the view on mount points
pid # Virtualizes the view on process IDs
Pour une description détaillée de ce que fait chaque type d'espace de noms, jetez un œil à ceci :
- homme 7 espaces_de_noms_temporels
- homme 7 ipc_namespaces
- homme 7 cgroup_namespaces
- homme 7 espaces_de_noms_utilisateur
- homme 7 espaces_de_noms_réseau
- homme 7 uts_namespaces
- homme 7 mount_namespaces
- homme 7 pid_namespaces
Liste des espaces de noms
La commande « lsns » permet de lister les espaces de noms utilisés par les processus. Son exécution listera par défaut les espaces de noms visibles par l'utilisateur actuel (lisibles depuis le procfs pseudo-système de fichiers)
# Who is the current user?
$ whoami
ubuntu
# Listing namespaces as user ubuntu
$ lsns
NS TYPE NPROCS PID USER COMMAND
4026531834 time 3 74838 ubuntu /lib/systemd/systemd --user
4026531835 cgroup 3 74838 ubuntu /lib/systemd/systemd --user
4026531836 pid 3 74838 ubuntu /lib/systemd/systemd --user
4026531837 user 3 74838 ubuntu /lib/systemd/systemd --user
4026531838 uts 3 74838 ubuntu /lib/systemd/systemd --user
4026531839 ipc 3 74838 ubuntu /lib/systemd/systemd --user
4026531840 net 3 74838 ubuntu /lib/systemd/systemd --user
4026531841 mnt 3 74838 ubuntu /lib/systemd/systemd --user
# Switched to root user
$ whoami
root
# Listing namespaces as user root
$ lsns
NS TYPE NPROCS PID USER COMMAND
4026531835 cgroup 129 1 root /sbin/init
4026531836 pid 126 1 root /sbin/init
4026531837 user 129 1 root /sbin/init
4026531838 uts 123 1 root /sbin/init
4026531839 ipc 126 1 root /sbin/init
4026531840 mnt 118 1 root /sbin/init
4026531860 mnt 1 21 root kdevtmpfs
4026531992 net 126 1 root /sbin/init
4026532144 mnt 1 1770518 root /lib/systemd/systemd-udevd
4026532146 mnt 3 1766779 root nginx: master process nginx -g daemon off;
4026532147 uts 3 1766779 root nginx: master process nginx -g daemon off;
4026532149 ipc 3 1766779 root nginx: master process nginx -g daemon off;
4026532150 pid 3 1766779 root nginx: master process nginx -g daemon off;
4026532152 net 3 1766779 root nginx: master process nginx -g daemon off;
4026532204 mnt 1 697 root /usr/sbin/irqbalance --foreground
4026532206 mnt 1 745 root /usr/sbin/ModemManager
4026532227 mnt 1 1770505 systemd-timesync /lib/systemd/systemd-timesyncd
4026532228 mnt 1 1770508 systemd-network /lib/systemd/systemd-networkd
4026532229 uts 1 1770518 root /lib/systemd/systemd-udevd
4026532231 mnt 1 1770495 systemd-resolve /lib/systemd/systemd-resolved
4026532232 mnt 1 1770551 root /lib/systemd/systemd-logind
4026532233 uts 1 1770505 systemd-timesync /lib/systemd/systemd-timesyncd
4026532234 uts 1 1770551 root /lib/systemd/systemd-logind
Pour chaque espace de noms dans la sortie de la commande 'lsns', nous voyons de gauche à droite :
- NS - l'ID de l'espace de noms
- TYPE - le type d'espace de noms
- NPROCS - le nombre de processus dans l'espace de noms
- PID - l'ID de processus le plus bas dans l'espace de noms
- USER - le nom d'utilisateur du PID
- COMMANDE - la commande du PID
Pour en savoir plus sur les champs disponibles qui peuvent être affichés, utilisez « lsns --help ».
Espaces de noms du système initial
Le système Linux utilise initialement des espaces de noms de chaque type. Pour le prouver, listons les espaces de noms du premier processus du système (PID 1) :
# Listing namespaces of process with PID 1
(root)$ lsns -p 1
NS TYPE NPROCS PID USER COMMAND
4026531834 time 178 1 root /sbin/init
4026531835 cgroup 178 1 root /sbin/init
4026531836 pid 123 1 root /sbin/init
4026531837 user 178 1 root /sbin/init
4026531838 uts 120 1 root /sbin/init
4026531839 ipc 123 1 root /sbin/init
4026531840 mnt 115 1 root /sbin/init
4026531992 net 123 1 root /sbin/init
Lors du processus de démarrage de Linux, une fois le noyau chargé en RAM par le chargeur de démarrage, le premier processus créé pour initialiser le système a le PID 1. Comme le montre le résultat de la commande précédente, le premier processus du système appartient aux espaces de noms de tous les types disponibles.
Liste des espaces de noms d'un processus spécifique
Pour lister les espaces de noms utilisés par un processus spécifique, nous pouvons utiliser la commande suivante :
# Syntax
# lsns -p PID
# Listing namespaces of process with PID 1
$ lsns -p 1
NS TYPE NPROCS PID USER COMMAND
4026531834 time 129 1 root /sbin/init
4026531835 cgroup 129 1 root /sbin/init
4026531836 pid 126 1 root /sbin/init
4026531837 user 129 1 root /sbin/init
4026531838 uts 123 1 root /sbin/init
4026531839 ipc 126 1 root /sbin/init
4026531840 mnt 118 1 root /sbin/init
4026531992 net 126 1 root /sbin/init
# Listing namespaces of process with PID 1766779
$ lsns -p 1766779
NS TYPE NPROCS PID USER COMMAND
4026531834 time 129 1 root /sbin/init
4026531835 cgroup 129 1 root /sbin/init
4026531837 user 129 1 root /sbin/init
4026532146 mnt 3 1766779 root nginx: master process nginx -g daemon off;
4026532147 uts 3 1766779 root nginx: master process nginx -g daemon off;
4026532149 ipc 3 1766779 root nginx: master process nginx -g daemon off;
4026532150 pid 3 1766779 root nginx: master process nginx -g daemon off;
4026532152 net 3 1766779 root nginx: master process nginx -g daemon off;
La dernière commande montre que le processus avec le PID 1766779 appartient aux espaces de noms système par défaut pour « time », « cgroup » et « user » (car les ID de processus associés à ces espaces de noms sont 1) mais fait partie d'espaces de noms supplémentaires pour les autres types d'espaces de noms (mnt, uts, ipc, pid et net).
Lister tous les processus d'un espace de noms
Pour lister tous les processus appartenant à un espace de noms spécifique, nous pouvons utiliser la commande suivante :
# Syntaxt
# lsns NAMESPACE_ID
# Listing processes belonging to namespace with ID 4026531836
$ lsns 4026531836
PID PPID USER COMMAND
1739571 1 ubuntu /lib/systemd/systemd --user
1770724 1770723 ubuntu -bash
1772249 1770724 ubuntu └─lsns 4026531836
Pour chaque processus dans la sortie de la commande de listage, nous voyons de gauche à droite :
- PID - L'ID du processus
- PPID - L'ID du processus parent
- UTILISATEUR - Le nom de l'utilisateur propriétaire du processus
- COMMANDE - La commande du processus
Liste des processus dans les mêmes espaces de noms que PID
Pour lister les processus appartenant au même espace de noms qu'un autre processus, nous pouvons utiliser les commandes suivantes :
# Syntax 1 (consider namespaces of all types)
# pgrep --ns PID -a
# Example 1:
# Listing processes belonging to same namespaces
# as process with ID 1739571 (consider namespaces of all types)
$ pgrep --ns 1739571 -a
1739571 /lib/systemd/systemd --user
1770724 -bash
# Syntax 2 (consider namespaces of types NSTYPE only)
# pgrep --ns PID -a --nslist NSTYPE
# NSTYPE = time, cgroup, user, ...
# Example 2:
# Listing processes belonging to same namespaces
# as process with ID 1739571 (consider namespaces of type user only)
$ pgrep --ns 1739571 -a --nslist user
1739571 /lib/systemd/systemd --user
1770724 -bash
# Example 3:
# Listing processes belonging to same namespaces
# as process with ID 1739571 (consider namespaces
# of types user, ipc and pid only)
$ pgrep --ns 1739571 -a --nslist user,ipc,pid
1739571 /lib/systemd/systemd --user
1770724 -bash
Exécution de programmes dans de nouveaux espaces de noms Linux
Pour exécuter un programme dans de nouveaux espaces de noms, nous pouvons utiliser la commande « unshare ». Les types d'espaces de noms à créer pour l'exécution du programme sont spécifiés par un ou plusieurs indicateurs de la commande « unshare ». Voici quelques exemples.
Exécuter un programme dans un espace de noms nouvellement créé
Pour exécuter mon programme dans un espace de noms réseau nouvellement créé, utilisez :
unshare --net myprogram
Pour exécuter mon programme dans deux espaces de noms réseau et cgroup nouvellement créés, utilisez :
unshare --net --cgroup myprogram
En savoir plus sur la commande unshare
Pour obtenir la liste des indicateurs disponibles pour chaque type d'espace de noms, utilisez :
unshare --help
Lorsqu'un programme n'est pas spécifié pour la commande « unshare », le programme par défaut qui sera exécuté est celui spécifié par la variable d'environnement $SHELL (par défaut /bin/sh).
Exemple : exécuter bash dans un espace de noms réseau nouvellement créé
Pour exécuter le programme bash dans un nouvel espace de noms de type « net » par exemple, nous pouvons utiliser la commande suivante :
(root)$ unshare --net bash
Par défaut, à l'intérieur de ce nouvel espace de noms réseau, nous ne voyons que l'interface réseau de bouclage :
(root)$ ip a
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
À l'intérieur de ce nouvel espace de noms réseau, les vues des tables de routage et d'arp sont également différentes de celles que nous voyons à l'extérieur de l'espace de noms... elles sont vides :
(root)$ route -n
(root)$ arp -a
Si nous exécutons la même commande en dehors de l'espace de noms, nous obtenons ceci :
(root)$ route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 172.18.208.1 0.0.0.0 UG 100 0 0 eth0
172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 docker0
172.18.0.0 0.0.0.0 255.255.0.0 U 0 0 0 br-7642594ed86e
172.18.208.0 0.0.0.0 255.255.240.0 U 0 0 0 eth0
172.18.208.1 0.0.0.0 255.255.255.255 UH 100 0 0 eth0
(root)$ arp -a
? (172.17.0.2) at 02:42:ac:11:00:02 [ether] on docker0
DESKTOP-0HQ48FL.mshome.net (172.18.208.1) at 00:15:5d:73:9d:ba [ether] on eth0
DESKTOP-0HQ48FL.mshome.net (172.18.208.1) at <incomplete> on br-7642594ed86e
test.mshome.net (172.18.208.73) at <incomplete> on br-7642594ed86e
Saisie des espaces de noms Linux existants
Pour exécuter un programme dans un ou plusieurs espaces de noms d'autres processus, nous pouvons utiliser la commande « nsenter » comme suit.
Exécuter des programmes dans d'autres espaces de noms de processus
Entrez tous les espaces de noms du processus avec le PID 8256 et exécutez la commande bash :
nsenter -t 8256 --all bash
Entrez les espaces de noms spécifiques d'autres processus
Entrez l'espace de noms de montage du processus avec le PID 8256 :
nsenter -t 8256 --mount
En savoir plus sur la commande nsenter
Pour obtenir la liste des indicateurs disponibles pour chaque type d'espace de noms, utilisez :
nsenter --help
Lorsqu'un programme n'est pas spécifié pour la commande 'nsenter', le programme par défaut qui sera exécuté est celui spécifié par la variable d'environnement $SHELL (par défaut /bin/sh).
Exploration des espaces de noms d'un conteneur Docker
# No container running yet
$ ps aux | grep nginx | grep -v grep
# Nginx container creation
$ docker run -d nginx
64c34cc1ded89d9f5604eecc861bd4df0c85494649090eb2b3dc171f2a92b644
# Here it is
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
64c34cc1ded8 nginx "/docker-entrypoint.…" 39 seconds ago Up 36 seconds 80/tcp awesome_banzai
# Here are the processes created by the container
$ ps aux | grep nginx | grep -v grep
root 8256 0.0 0.1 11456 7472 ? Ss May19 0:00 nginx: master process nginx -g daemon off;
systemd+ 8316 0.0 0.0 11920 2892 ? S May19 0:00 nginx: worker process
systemd+ 8317 0.0 0.0 11920 2892 ? S May19 0:00 nginx: worker process
Les processus utilisant la commande « nginx » proviennent du conteneur Docker. Listons les espaces de noms de l'un de ces processus :
$ lsns -p 8256
NS TYPE NPROCS PID USER COMMAND
4026531834 time 122 1 root /sbin/init
4026531835 cgroup 122 1 root /sbin/init
4026531837 user 122 1 root /sbin/init
4026532155 mnt 3 8256 root nginx: master process nginx -g daemon off;
4026532156 uts 3 8256 root nginx: master process nginx -g daemon off;
4026532157 ipc 3 8256 root nginx: master process nginx -g daemon off;
4026532158 pid 3 8256 root nginx: master process nginx -g daemon off;
4026532160 net 3 8256 root nginx: master process nginx -g daemon off;
La vue de ce processus sur les composants système est limitée par des espaces de noms de types autres que time, cgroup et user. Comme indiqué dans la commande précédente, les espaces de noms auxquels appartient le processus avec le PID 8256 pour time, cgroup et user sont les espaces de noms système initiaux contenant le PID 1 (commande /sbin/init). Par conséquent, les composants système hôtes associés à ces types d'espaces de noms ne sont pas isolés des processus conteneurs Nginx.
Les processus de conteneur nginx appartiennent aux espaces de noms nouvellement créés de types mnt, uts, ipc, pid et net (le PID le plus bas des espaces de noms correspond au PID nginx), et par conséquent, seuls les composants du système hôte liés à ces types d'espaces de noms sont isolés des processus de conteneur nginx.
Pour l'espace de noms de type 'net' (réseau) par exemple, voici les interfaces réseau que le processus nginx (PID 8256) voit :
$ nsenter -t 8256 --net
$ 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
5: eth0@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
et les interfaces réseau qui sont réellement disponibles sur le système hôte :
$ 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
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 52:54:00:2c:e2:ea brd ff:ff:ff:ff:ff:ff
inet 172.19.22.97/20 brd 172.19.31.255 scope global eth0
valid_lft forever preferred_lft forever
inet 172.18.208.73/20 brd 172.18.223.255 scope global dynamic eth0
valid_lft 84950sec preferred_lft 84950sec
inet6 fe80::5054:ff:fe2c:e2ea/64 scope link
valid_lft forever preferred_lft forever
3: br-7642594ed86e: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:d2:37:fb:2a brd ff:ff:ff:ff:ff:ff
inet 172.18.0.1/16 brd 172.18.255.255 scope global br-7642594ed86e
valid_lft forever preferred_lft forever
4: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:24:2a:a3:ce brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:24ff:fe2a:a3ce/64 scope link
valid_lft forever preferred_lft forever
6: veth5b9d547@if5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether ea:b1:a8:41:e8:b3 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet6 fe80::e8b1:a8ff:fe41:e8b3/64 scope link
valid_lft forever preferred_lft forever
Cela démontre que le conteneur possède sa propre vue du réseau (périphériques, table de routage, etc.), isolée des composants réseau de l'hôte. Le même type d'isolation s'applique également aux systèmes de fichiers montés sur le conteneur.espace de noms mnt), les processus qu'il voit (espace de noms pid), nom d'hôte (espace de noms uts) et IPC (espace de noms ipc).
C'est tout. J'espère que vous comprenez mieux les espaces de noms Linux maintenant.
Vous souhaitez signaler une erreur ou poser une question ? N'hésitez pas à m'envoyer un e-mail à gmkziz@hackerstack.org. Je serai ravi de répondre.
Si vous aimez mes articles, pensez à vous inscrire à ma newsletter afin de recevoir les derniers articles dès qu'ils sont disponibles.
Prenez soin de vous, continuez à apprendre et à bientôt pour le prochain post 🚀