GNU/Linux >> Tutoriels Linux >  >> Linux

Construire un conteneur à la main à l'aide d'espaces de noms :l'espace de noms de montage

Cet article examine le montage namespace et est le troisième de la série Linux Namespace. Dans le premier article, j'ai donné une introduction aux sept espaces de noms les plus couramment utilisés, jetant les bases du travail pratique commencé dans l'article sur les espaces de noms d'utilisateurs. Mon objectif est d'acquérir des connaissances fondamentales sur le fonctionnement des fondements des conteneurs Linux. Si vous êtes intéressé par la façon dont Linux contrôle les ressources sur un système, consultez la série CGroup, j'ai écrit plus tôt. J'espère qu'au moment où vous aurez terminé le travail pratique sur les espaces de noms, je pourrai lier les CGroups et les espaces de noms de manière significative, complétant ainsi le tableau pour vous.

Pour l'instant, cependant, cet article examine l'espace de noms de montage et comment il peut vous aider à mieux comprendre l'isolement que les conteneurs Linux apportent aux administrateurs système et, par extension, aux plates-formes comme OpenShift et Kubernetes.

[ Vous pourriez également aimer : Partager des groupes supplémentaires avec des conteneurs Podman ]

L'espace de noms de montage

L'espace de noms de montage ne se comporte pas comme prévu après la création d'un nouvel espace de noms d'utilisateur. Par défaut, si vous deviez créer un nouvel espace de noms de montage avec unshare -m , votre vision du système resterait en grande partie inchangée et non limitée. En effet, chaque fois que vous créez un nouvel espace de noms de montage, une copie des points de montage de l'espace de noms parent est créé dans le nouvel espace de noms de montage. Cela signifie que toute action entreprise sur des fichiers à l'intérieur d'un espace de noms de montage mal configuré sera impact sur l'hôte.

Quelques étapes de configuration pour les espaces de noms de montage

Alors, à quoi sert l'espace de noms de montage ? Pour illustrer cela, j'utilise une archive tar Linux Alpine.

En résumé, téléchargez-le, décompressez-le et déplacez-le dans un nouveau répertoire, en accordant au répertoire de niveau supérieur les autorisations pour un utilisateur non privilégié :

[root@localhost ~] export CONTAINER_ROOT_FOLDER=/container_practice
[root@localhost ~] mkdir -p ${CONTAINER_ROOT_FOLDER}/fakeroot
[root@localhost ~] cd ${CONTAINER_ROOT_FOLDER}
[root@localhost ~] wget https://dl-cdn.alpinelinux.org/alpine/v3.13/releases/x86_64/alpine-minirootfs-3.13.1-x86_64.tar.gz
[root@localhost ~] tar xvf alpine-minirootfs-3.13.1-x86_64.tar.gz -C fakeroot
[root@localhost ~] chown container-user. -R ${CONTAINER_ROOT_FOLDER}/fakeroot

La fakeroot le répertoire doit appartenir à l'utilisateur container-user car une fois que vous avez créé un nouvel espace de noms d'utilisateur, la racine l'utilisateur dans le nouvel espace de noms sera mappé sur le container-user en dehors de l'espace de noms. Cela signifie qu'un processus à l'intérieur du nouvel espace de noms pensera qu'il a les capacités requises pour modifier ses fichiers. Néanmoins, les autorisations du système de fichiers de l'hôte empêcheront l'utilisateur du conteneur compte de modifier les fichiers Alpine à partir de l'archive tar (qui ont racine en tant que propriétaire).

Que se passe-t-il si vous démarrez simplement un nouvel espace de noms de montage ?

PS1='\u@new-mnt$ ' unshare -Umr

Maintenant que vous êtes à l'intérieur du nouvel espace de noms, vous ne vous attendez peut-être pas à voir les points de montage d'origine de l'hôte. Cependant, ce n'est pas le cas :

root@new-mnt$ df -h
Filesystem           Size  Used Avail Use% Mounted on
/dev/mapper/cs-root   36G  5.2G   31G  15% /
tmpfs                737M     0  737M   0% /sys/fs/cgroup
devtmpfs             720M     0  720M   0% /dev
tmpfs                737M     0  737M   0% /dev/shm
tmpfs                737M  8.6M  728M   2% /run
tmpfs                148M     0  148M   0% /run/user/0
/dev/vda1            976M  197M  713M  22% /boot


root@new-mnt$ ls /
bin   container_practice  etc   lib    media  opt   root  sbin  sys  usr
boot  dev                 home  lib64  mnt    proc  run   srv   tmp  var

La raison en est que systemd partage par défaut les points de montage de manière récursive avec tous les nouveaux espaces de noms. Si vous avez monté un tmpfs système de fichiers quelque part, par exemple, /mnt à l'intérieur du nouvel espace de noms de montage, l'hôte peut-il le voir ?

root@new-mnt$ mount -t tmpfs tmpfs /mnt

root@new-mnt$ findmnt |grep mnt
└─/mnt     tmpfs               tmpfs      rw,relatime,seclabel,uid=1000,gid=1000

L'hôte, cependant, ne voit pas ceci :

[root@localhost ~]# findmnt |grep mnt

Donc, à tout le moins, vous savez que l'espace de noms de montage fonctionne correctement. C'est le bon moment pour faire un petit détour pour discuter de la propagation des points de montage. Je résume brièvement, mais si vous êtes intéressé par une meilleure compréhension, consultez l'article LWN de Michael Kerrisk ainsi que la page de manuel de l'espace de noms de montage. Normalement, je ne compte pas autant sur les pages de manuel car je trouve souvent qu'elles ne sont pas faciles à digérer. Cependant, dans ce cas, ils sont pleins d'exemples et en anglais (principalement) simple.

Théorie des points de montage

Les montages se propagent par défaut en raison d'une fonctionnalité du noyau appelée sous-arborescence partagée . Cela permet à chaque point de montage d'avoir son propre type de propagation qui lui est associé. Ces métadonnées déterminent si les nouveaux montages sous un chemin donné sont propagés vers d'autres points de montage. L'exemple donné dans la page de manuel est celui d'un disque optique. Si votre disque optique est automatiquement monté sous /cdrom , le contenu ne serait visible dans d'autres espaces de noms que si le type de propagation approprié est défini.

Groupes d'homologues et états de montage

La documentation du noyau indique qu'un "groupe de pairs est défini comme un groupe de vfsmounts qui propagent des événements les uns aux autres. " Les événements sont des choses telles que le montage d'un partage réseau ou le démontage d'un périphérique optique. Pourquoi est-ce important, demandez-vous ? Eh bien, en ce qui concerne l'espace de noms de montage, les groupes de pairs sont souvent le facteur décisif pour savoir si une monture est visible ou non et peut interagir avec. Un état de montage détermine si un membre d'un groupe de pairs peut recevoir l'événement. Selon la même documentation du noyau, il existe cinq états de montage :

  1. partagé - Une monture qui appartient à un groupe de pairs. Toute modification apportée se propagera à tous les membres du groupe de pairs.
  2. esclave - Propagation unidirectionnelle. Le point de montage maître propagera les événements à un esclave, mais le maître ne verra aucune des actions entreprises par l'esclave.
  3. partagé et esclave - Indique que le point de montage a un maître, mais qu'il a également son propre groupe de pairs. Le maître ne sera pas informé des modifications apportées à un point de montage, mais tous les membres du groupe de pairs en aval le seront.
  4. privé - Ne reçoit ni ne transmet aucun événement de propagation.
  5. non contraignant - Ne reçoit ni ne transmet aucun événement de propagation et ne peut pas être lié monté.

Il est important de noter que l'état du point de montage est par point de montage . Cela signifie que si vous avez / et /boot , par exemple, vous devrez appliquer séparément l'état souhaité à chaque point de montage.

Si vous vous posez des questions sur les conteneurs, la plupart des moteurs de conteneurs utilisent des états de montage privés lors du montage d'un volume à l'intérieur d'un conteneur. Ne vous en faites pas trop pour l'instant. Je veux juste donner un peu de contexte. Si vous souhaitez essayer des scénarios de montage spécifiques, consultez les pages de manuel car les exemples sont assez bons.

Création de notre espace de noms de montage

Si vous utilisez un langage de programmation tel que Go ou C, vous pouvez utiliser les appels bruts du noyau système pour créer l'environnement approprié pour vos nouveaux espaces de noms. Cependant, étant donné que l'intention derrière cela est de vous aider à comprendre comment interagir avec un conteneur qui existe déjà, vous devrez faire quelques trucs bash pour obtenir votre nouvel espace de noms de montage dans l'état souhaité.

Tout d'abord, créez le nouvel espace de noms de montage en tant qu'utilisateur normal :

unshare -Urm

Une fois que vous êtes dans l'espace de noms, regardez le findmnt du périphérique mappeur, qui contient le système de fichiers racine (par souci de brièveté, j'ai supprimé la plupart des options de montage de la sortie) :

findmnt |grep mapper

/       /dev/mapper/cs-root      xfs           rw,relatime,[...]

Il n'y a qu'un seul point de montage qui a le mappeur de périphérique racine. Ceci est important car l'une des choses que vous devez faire est de lier le périphérique de mappage dans le répertoire Alpine :

export CONTAINER_ROOT_FOLDER=/container_practice
mount --bind ${CONTAINER_ROOT_FOLDER}/fakeroot ${CONTAINER_ROOT_FOLDER}/fakeroot
cd ${CONTAINER_ROOT_FOLDER}/fakeroot

C'est parce que vous utilisez un utilitaire appelé pivot_root pour effectuer un chroot -comme une action. pivot_root prend deux arguments :new_root et old_root (parfois appelé put_old ). pivot_root déplace le système de fichiers racine du processus en cours vers le répertoire put_old et fait new_root le nouveau système de fichiers racine.

IMPORTANT :Une note à propos de chroot . chroot est souvent considéré comme ayant des avantages de sécurité supplémentaires. Dans une certaine mesure, c'est vrai, car il faut une expertise plus importante pour s'en libérer. Un chroot soigneusement construit peut être très sécurisé. Cependant, chroot ne modifie ni ne restreint les capacités de Linux que j'ai abordées dans l'article précédent sur l'espace de noms. Il ne limite pas non plus les appels système au noyau. Cela signifie qu'un agresseur suffisamment qualifié pourrait potentiellement échapper à un chroot cela n'a pas été bien pensé. Les espaces de noms de montage et d'utilisateur aident à résoudre ce problème.

Si vous utilisez pivot_root sans le montage lié, la commande répond par :

pivot_root: failed to change root from `.' to `old_root/': Invalid argument

Pour basculer vers le système de fichiers racine Alpine, commencez par créer un répertoire pour old_root puis pivotez dans le système de fichiers racine prévu (Alpine). Étant donné que le système de fichiers racine Alpine Linux n'a pas de liens symboliques pour /bin et /sbin , vous devrez les ajouter à votre chemin et enfin, démonter le old_root :

mkdir old_root
pivot_root . old_root
PATH=/bin:/sbin:$PATH
umount -l /old_root

Vous avez maintenant un bel environnement où l'utilisateur et monter Les espaces de noms fonctionnent ensemble pour fournir une couche d'isolation de l'hôte. Vous n'avez plus accès aux fichiers binaires sur l'hôte. Essayez d'émettre le findmnt commande que vous utilisiez auparavant :

root@new-mnt$ findmnt
-bash: findmnt: command not found

Vous pouvez également consulter le système de fichiers racine ou essayer de voir ce qui est monté :

root@new-mnt$ ls -l /
total 12
drwxr-xr-x    2 root     root          4096 Jan 28 21:51 bin
drwxr-xr-x    2 root     root            18 Feb 17 22:53 dev
drwxr-xr-x   15 root     root          4096 Jan 28 21:51 etc
drwxr-xr-x    2 root     root             6 Jan 28 21:51 home
drwxr-xr-x    7 root     root           247 Jan 28 21:51 lib
drwxr-xr-x    5 root     root            44 Jan 28 21:51 media
drwxr-xr-x    2 root     root             6 Jan 28 21:51 mnt
drwxrwxr-x    2 root     root             6 Feb 17 23:09 old_root
drwxr-xr-x    2 root     root             6 Jan 28 21:51 opt
drwxr-xr-x    2 root     root             6 Jan 28 21:51 proc
drwxr-xr-x    2 root     root             6 Feb 17 22:53 put_old
drwx------    2 root     root            27 Feb 17 22:53 root
drwxr-xr-x    2 root     root             6 Jan 28 21:51 run
drwxr-xr-x    2 root     root          4096 Jan 28 21:51 sbin
drwxr-xr-x    2 root     root             6 Jan 28 21:51 srv
drwxr-xr-x    2 root     root             6 Jan 28 21:51 sys
drwxrwxrwt    2 root     root             6 Feb 19 16:38 tmp
drwxr-xr-x    7 root     root            66 Jan 28 21:51 usr
drwxr-xr-x   12 root     root           137 Jan 28 21:51 var


root@new-mnt$ mount
mount: no /proc/mounts

Fait intéressant, il n'y a pas de proc système de fichiers monté par défaut. Essayez de le monter :

root@new-mnt$ mount -t proc proc /proc
mount: permission denied (are you root?)

root@new-mnt$ whoami
root

Parce que proc est un type spécial de montage lié à l'espace de noms PID, vous ne pouvez pas le monter même si vous êtes dans votre propre espace de noms de montage. Cela revient à l'héritage de capacité dont j'ai parlé plus tôt. Je reprendrai cette discussion dans le prochain article lorsque je couvrirai l'espace de noms PID. Cependant, pour rappel sur l'héritage, regardez le schéma ci-dessous :

Dans le prochain article, je ressasserai ce diagramme, mais si vous avez suivi depuis le début, vous devriez pouvoir faire quelques inférences avant.

[ Manuel du propriétaire de l'API :7 bonnes pratiques pour des programmes d'API efficaces ] 

Conclusion

Dans cet article, j'ai couvert une théorie plus approfondie autour de l'espace de noms de montage. J'ai discuté des groupes de pairs et de leur relation avec les états de montage appliqués à chaque point de montage sur un système. Pour la partie pratique, vous avez téléchargé un système de fichiers Alpine Linux minimal, puis expliqué comment utiliser l'utilisateur et monter les espaces de noms pour créer un environnement qui ressemble beaucoup à chroot sauf potentiellement plus sécurisé.

Pour l'instant, testez le montage des systèmes de fichiers à l'intérieur et à l'extérieur de votre nouvel espace de noms. Essayez de créer de nouveaux points de montage qui utilisent le partagé , privé , et esclave états de montage. Dans le prochain article, j'utiliserai l'espace de noms PID pour continuer à créer le conteneur primitif afin d'accéder au proc isolation du système de fichiers et des processus.


Linux
  1. Dépannage à l'aide du système de fichiers proc sous Linux

  2. Démystifier les espaces de noms et les conteneurs sous Linux

  3. Instaurer la confiance dans la communauté Linux

  4. Docker dans Docker ne peut pas monter le volume

  5. Rendre un montage NFS sur l'hôte visible et en lecture-écriture dans le conteneur Docker

Utilisation de la commande gratuite Linux

Utilisation du fichier de configuration SSH

Construire un conteneur Linux à la main à l'aide d'espaces de noms

Construire des conteneurs à la main :l'espace de noms PID

Une introduction au registre des conteneurs de Quay

Tutoriel sur l'utilisation de la commande Timeout sous Linux