GNU/Linux >> Tutoriels Linux >  >> Linux

Comment utiliser Podman à l'intérieur d'un conteneur

L'un des sujets les plus demandés aux personnes travaillant sur les technologies de conteneurs en amont est l'exécution de Podman dans un conteneur. La plupart de ces éléments ont toujours été liés à Docker dans Docker (DIND), mais désormais, les utilisateurs souhaitent également exécuter Podman dans Podman (PINP) ou Podman dans Docker (PIND).

Mais Podman peut être exécuté de plusieurs manières, avec et sans racine. Nous nous retrouvons avec des personnes voulant exécuter diverses combinaisons de Podman avec et sans racine :

  • Podman rooté dans Podman rooté
  • Podman sans racine dans Podman racine
  • Podman rooté dans Podman sans racine
  • Podman sans racine dans Podman sans racine

Vous obtenez l'image.

Ce blog tentera de couvrir chaque combinaison, en commençant par une discussion sur les privilèges. Nous allons commencer par le scénario PINP ici dans la première partie. Dans la deuxième partie de la série, nous couvrirons un terrain similaire, mais dans le contexte de Kubernetes. Assurez-vous de lire les deux articles pour une image complète.

Les moteurs de conteneurs nécessitent des privilèges

Pour exécuter un moteur de conteneur comme Podman dans un conteneur, la première chose que vous devez comprendre est que vous avez besoin d'un certain nombre de privilèges.

  • Les conteneurs nécessitent plusieurs UID. La plupart des images de conteneur ont besoin de plusieurs UID pour fonctionner. Par exemple, vous pouvez avoir une image avec la plupart des fichiers appartenant à root, mais certains appartenant à l'utilisateur apache (UID=60).
  • Les moteurs de conteneurs montent des systèmes de fichiers et utilisent le clone d'appel système pour créer des espaces de noms d'utilisateurs.

Remarque :Vous aurez peut-être besoin d'une version plus récente de Podman. Les exemples de ce blog ont été exécutés avec Podman 3.2.

Notre image test

Pour les exemples de ce blog, nous utiliserons le quay.io/podman/stable image, qui a été construite avec l'idée de trouver la meilleure façon d'exécuter Podman dans un conteneur. Vous pouvez examiner comment nous construisons cette image à partir du Dockerfile et de containers.conf image dans le référentiel github.com.

# stable/Dockerfile
#
# Build a Podman container image from the latest
# stable version of Podman on the Fedoras Updates System.
# https://bodhi.fedoraproject.org/updates/?search=podman
# This image can be used to create a secured container
# that runs safely with privileges within the container.
#
FROM registry.fedoraproject.org/fedora:latest

# Don't include container-selinux and remove
# directories used by yum that are just taking
# up space.
RUN dnf -y update; yum -y reinstall shadow-utils; \
yum -y install podman fuse-overlayfs --exclude container-selinux; \
rm -rf /var/cache /var/log/dnf* /var/log/yum.*

RUN useradd podman; \
echo podman:10000:5000 > /etc/subuid; \
echo podman:10000:5000 > /etc/subgid;

VOLUME /var/lib/containers
VOLUME /home/podman/.local/share/containers

ADD https://raw.githubusercontent.com/containers/libpod/master/contrib/podmanimage/stable/containers.conf /etc/containers/containers.conf
ADD https://raw.githubusercontent.com/containers/libpod/master/contrib/podmanimage/stable/podman-containers.conf /home/podman/.config/containers/containers.conf

RUN chown podman:podman -R /home/podman

# chmod containers.conf and adjust storage.conf to enable Fuse storage.
RUN chmod 644 /etc/containers/containers.conf; sed -i -e 's|^#mount_program|mount_program|g' -e '/additionalimage.*/a "/var/lib/shared",' -e 's|^mountopt[[:space:]]*=.*$|mountopt = "nodev,fsync=0"|g' /etc/containers/storage.conf
RUN mkdir -p /var/lib/shared/overlay-images /var/lib/shared/overlay-layers /var/lib/shared/vfs-images /var/lib/shared/vfs-layers; touch /var/lib/shared/overlay-images/images.lock; touch /var/lib/shared/overlay-layers/layers.lock; touch /var/lib/shared/vfs-images/images.lock; touch /var/lib/shared/vfs-layers/layers.lock

ENV _CONTAINERS_USERNS_CONFIGURED=""

Examinons le Dockerfile.

FROM registry.fedoraproject.org/fedora:latest

# Don't include container-selinux and remove
# directories used by yum that are just taking
# up space.
RUN dnf -y update; yum -y reinstall shadow-utils; \
yum -y install podman fuse-overlayfs --exclude container-selinux; \
rm -rf /var/cache /var/log/dnf* /var/log/yum.*

Tirez d'abord Fedora au plus tard, puis mettez à jour les derniers packages. Notez qu'il réinstalle shadow-utils , car il existe un problème connu dans shadow-utils installer sur l'image Fedora où les filecaps sur newsubuid et newsubgid ne sont pas définis. Réinstallation de shadow-utils résout le problème. Ensuite, installez Podman ainsi que le fuse-overlayfs . Nous n'installons pas container-selinux car il n'est pas nécessaire dans le conteneur.

RUN useradd podman; \
echo podman:10000:5000 > /etc/subuid; \
echo podman:10000:5000 > /etc/subgid;

Ensuite, je crée un utilisateur podman et configurez le /etc/subuid et /etc/subgid fichiers pour utiliser 5000 UID. Ceci est utilisé pour configurer l'espace de noms d'utilisateur dans le conteneur. 5000 est un nombre arbitraire et potentiellement trop petit. Nous avons choisi ce nombre car il est inférieur aux 65 000 alloués aux utilisateurs sans racine. Si vous exécutiez uniquement le conteneur en tant que root, 65k aurait été un meilleur nombre.

VOLUME /var/lib/containers
VOLUME /home/podman/.local/share/containers

Puisque nous pouvons exécuter des conteneurs rootfull et rootless avec cette image, nous créons deux volumes. Rootfull Podman utilise /var/lib/containers pour son stockage de conteneurs et ses utilisations sans racine /home/podman/.local/share/containers . La superposition sur superposition est souvent refusée par le noyau, ce qui crée des volumes non superposés à utiliser dans le conteneur.

ADD https://raw.githubusercontent.com/containers/libpod/master/contrib/podmanimage/stable/containers.conf /etc/containers/containers.conf
ADD https://raw.githubusercontent.com/containers/libpod/master/contrib/podmanimage/stable/podman-containers.conf /home/podman/.config/containers/containers.conf

J'ai pré-configuré deux containers.conf fichiers pour s'assurer que les conteneurs s'exécutent plus facilement dans chaque mode.

L'image est configurée pour fonctionner avec fuse-overlayfs par défaut. Dans certains cas, vous pouvez exécuter le système de fichiers superposé du noyau en mode root, et vous pourrez bientôt le faire en mode rootless. Cependant, pour l'instant, nous utilisons des superpositions de fusibles comme stockage de conteneurs dans le conteneur. D'autres personnes ont utilisé le pilote de stockage VFS, mais ce n'est pas si efficace.

L'indicateur --privileged

Le moyen le plus simple d'exécuter Podman à l'intérieur d'un conteneur consiste à utiliser le --privileged drapeau.

Podman rooté dans Podman rooté avec --privileged

# podman run --privileged quay.io/podman/stable podman run ubi8 echo hello
Resolved "ubi8-minimal" as an alias (/etc/containers/registries.conf.d/shortnames.conf)
Trying to pull registry.access.redhat.com/ubi8:latest...
Getting image source signatures
Copying blob sha256:a591faa84ab05242a17131e396a336da172b0e1ec66d921c9f130b7c4c24586d
Copying blob sha256:76b9354adec626b01ffb0faae4a217cebd616661fd90c4b54ba4415f53392fb8
Copying config sha256:dc080723f596f2407300cca2c19a17accad89edcf39f7b8b33e6472dd41e30f1
Writing manifest to image destination
Storing signatures
hello

Pour gagner du temps, puisque je vais faire beaucoup d'expériences, j'ai créé un répertoire sur mon hébergeur ./mycontainers , que je monterai en volume dans le conteneur à utiliser et que je n'aurai pas à extraire l'image à chaque fois.

# podman run --privileged -v ./mycontainers:/var/lib/containers quay.io/podman/stable podman run ubi8 echo hello
hello

Podman sans racine dans Podman racine avec --privileged

Le quay.io/podman/stable l'image est configurée avec un podman utilisateur que vous pouvez utiliser pour exécuter des conteneurs sans racine.

# podman run --user podman --privileged quay.io/podman/stable podman run ubi8 echo hello
Resolved "ubi8" as an alias (/etc/containers/registries.conf.d/shortnames.conf)
...
hello

Notez que dans ce cas, le Podman s'exécutant à l'intérieur du conteneur s'exécute en tant qu'utilisateur podman . En effet, le Podman conteneurisé utilise l'espace de noms d'utilisateur pour créer un conteneur confiné dans le conteneur privilégié.

Exécuter Podman sans racine dans Docker avec --privileged

Semblable à Podman rooté, vous pouvez également exécuter Podman sans racine dans Docker avec le --privileged option.

# docker run --privileged quay.io/podman/stable podman run ubi8 echo hello

Podman sans racine avec Docker

# docker run --user podman --privileged quay.io/podman/stable podman run ubi8 echo hello
Resolved "ubi8" as an alias (/etc/containers/registries.conf.d/shortnames.conf)
...
hello

Pouvons-nous le faire de manière plus sécurisée ?

Notez que même si nous avons exécuté les conteneurs externes --privileged ci-dessus, les conteneurs intérieurs fonctionnent en mode verrouillé. Le Podman sans racine qui s'exécute dans le conteneur est vraiment verrouillé et aurait beaucoup de mal à s'échapper. Compte tenu de cela, je ne suis pas fan de l'utilisation du --privileged drapeau. Je pense que nous pouvons faire mieux du point de vue de la sécurité.

Exécuter sans l'indicateur --privileged

Voyons comment nous pouvons supprimer le --privileged drapeau pour une meilleure sécurité.

Podman rooté dans Podman rooté sans --privileged

# podman run --cap-add=sys_admin,mknod --device=/dev/fuse --security-opt label=disable quay.io/podman/stable podman run ubi8-minimal echo hello
hello

Nous pouvons éliminer le --privileged drapeau du podman rooté, mais il faut encore désactiver certaines fonctionnalités de sécurité pour que le podman rooté fonctionne dans le conteneur.

  1. Capacités :--cap-add=sys_admin,mknod Nous devons ajouter deux fonctionnalités Linux.
    1. CAP_SYS_ADMIN est requis pour que le Podman s'exécute en tant que racine à l'intérieur du conteneur pour monter les systèmes de fichiers requis.
    2. CAP_MKNOD est nécessaire pour que Podman s'exécute en tant que root à l'intérieur du conteneur pour créer les appareils dans /dev . (Notez que Docker le permet par défaut).
  2. Appareils :le --device /dev/fuse flag doit utiliser des superpositions de fusibles à l'intérieur du conteneur. Cette option indique à Podman sur l'hôte d'ajouter /dev/fuse au conteneur afin que Podman conteneurisé puisse l'utiliser.
  3. Désactiver SELinux :le --security-opt label=disable L'option indique au Podman de l'hôte de désactiver la séparation SElinux pour le conteneur. SELinux n'autorise pas les processus conteneurisés à monter tous les systèmes de fichiers nécessaires pour s'exécuter à l'intérieur d'un conteneur.

Podman rooté dans Docker sans --privileged

# docker run --cap-add=sys_admin --cap-add mknod --device=/dev/fuse --security-opt seccomp=unconfined --security-opt label=disable quay.io/podman/stable podman run ubi8-minimal echo hello
hello
  1. Remarque Docker ne prend pas en charge le --cap-add séparé par des virgules commande, j'ai donc dû ajouter sys_admin et mknod séparément
  2. Toujours besoin de --device /dev/fuse , puisque le conteneur est par défaut /dev/fuse
  3. Docker crée toujours des volumes intégrés appartenant à root:root, nous devons donc créer un volume à monter pour Podman dans le conteneur afin de pouvoir l'utiliser pour le stockage.
  4. Comme toujours, je dois désactiver la séparation SELinux
  5. Il faut également désactiver seccomp , puisque Docker a un seccomp légèrement plus strict politique que Podman. Vous pouvez simplement utiliser une politique de sécurité Podman en utilisant --seccomp=/usr/share/containers/seccomp.json
# docker run --cap-add=sys_admin --cap-add mknod --device=/dev/fuse --security-opt seccomp=/usr/share/containers/seccomp.json --security-opt label=disable quay.io/podman/stable podman run ubi8-minimal echo hello
hello

Podman sans racine dans Podman racine sans --privileged

Exécutez non - conteneur privilégié avec Podman à l'intérieur en utilisant un utilisateur non root utilisant l'espace de noms d'utilisateur.

# podman run --user podman --security-opt label=disable --security-opt unmask=ALL --device /dev/fuse -ti quay.io/podman/stable podman run -ti docker.io/busybox echo hello
hello
  1. Notez que contrairement au rooful dans le cas rootful avant, nous n'avons pas besoin d'ajouter les fonctionnalités de sécurité dangereuses sys_admin et mknod
  2. Dans ce cas, j'utilise --user podman , ce qui entraîne automatiquement l'exécution du Podman dans le conteneur dans l'espace de noms de l'utilisateur
  3. Selinux est toujours désactivé puisqu'il bloque le montage
  4. Toujours besoin de --device /dev/fuse utiliser fuse-overlayfs dans le conteneur

Podman-remote dans Podman rooté avec une fuite de socket Podman de l'hôte

# podman run -v /run:/run --security-opt label=disable quay.io/podman/stable podman --remote run busybox echo hi
hi

Dans ce cas, nous divulguons le /run répertoire de l'hôte dans le conteneur. Cela permet à podman --remote pour communiquer avec le socket Podman sur l'hôte et démarrer le conteneur sur le système d'exploitation hôte. C'est souvent ainsi que les gens exécutent Docker dans Docker, en particulier les builds Docker. Vous pouvez également exécuter les versions de Podman de cette manière et tirer parti des images précédemment extraites du système.

Notez, cependant, que cela est extrêmement peu sûr. Les processus au sein du conteneur peuvent totalement prendre le contrôle de la machine hôte.

  1. Vous devez toujours désactiver la séparation SELinux car SELinux empêcherait les processus de conteneur d'utiliser les sockets divulgués dans /run .
  2. Le podman --remote Un indicateur est ajouté pour dire à Podman de travailler en mode distant. Notez que vous pouvez également simplement installer le podman-remote exécutable dans un conteneur et utilisez ceci.

[ Vous débutez avec les conteneurs ? Découvrez ce cours gratuit. Déploiement d'applications conteneurisées :présentation technique. ]

Podman-remote dans Docker avec une fuite de socket Podman de l'hôte

# docker run -v /run:/run --security-opt label=disable quay.io/podman/stable podman --remote run busybox echo hi
hi

Le même exemple fonctionne pour un conteneur Docker.

Cet exemple montre un conteneur entièrement verrouillé - autre que SELinux étant désactivé - avec le socket Podman qui a fui dans le conteneur. SELinux bloquerait cet accès, comme il se doit.

# /bin/podman run --security-opt=label=disable -v /run/podman:/run/podman quay.io/podman/stable podman --remote run alpine echo hi
hi

Podman sans racine avec Podman racine conteneurisé

$ podman run --privileged quay.io/podman/stable podman run ubi8 echo hello
Resolved "ubi8" as an alias (/etc/containers/registries.conf.d/shortnames.conf)
..
hello

Podman sans racine exécutant Podman sans racine

$ podman run --security-opt label=disable --user podman --device /dev/fuse quay.io/podman/stable podman run alpine echo hello

Réflexions finales

Vous avez maintenant un certain contexte pour Podman dans les options de Podman, en utilisant à la fois les modes racine et sans racine. dans diverses combinaisons. Vous avez également une meilleure idée des privilèges nécessaires et des considérations entourant le --privileged drapeau.

La deuxième partie de cette série examine l'utilisation de Podman et Kubernetes. L'article couvre un territoire similaire mais dans le contexte de Kubernetes.

[ Vous voulez tester vos compétences d'administrateur système ? Faites une évaluation des compétences aujourd'hui. ]


Linux
  1. Comment j'utilise cron sous Linux

  2. Comment utiliser Nginx pour rediriger

  3. Comment utiliser la commande Su sous Linux

  4. Aperçu technologique :Exécution d'un conteneur à l'intérieur d'un conteneur

  5. Utiliser perf dans un conteneur docker sans --privileged

Comment utiliser Instagram dans le terminal

Comment exécuter des pods en tant que services systemd avec Podman

Comment utiliser la commande PS

Comment utiliser la commande TOP

Comment installer et utiliser Podman (alternative à Docker)

Comment utiliser Linux Bash Shell dans Windows 10 ?