Quel est l'intérêt de découpler le runtime du conteneur en composants d'outils distincts ? Ces outils peuvent notamment commencer à être combinés pour se protéger mutuellement.
De nombreuses personnes sont attirées par l'idée de créer des images OCI conteneurisées dans
C'est pourquoi les gens essaient constamment d'exécuter Buildah dans un conteneur. Bref, nous avons créé
réglage
Ces images sont construites à partir de Dockerfiles, qui se trouvent dans le référentiel Buildah dans le dossier
Ici, nous allons regarder
# stable/Dockerfile
#
# Build a Buildah container image from the latest
# stable version of Buildah on the Fedoras Updates System.
# https://bodhi.fedoraproject.org/updates/?search=buildah
# This image can be used to create a secured container
# that runs safely with privileges within the container.
#
FROM fedora:latest
# Don't include container-selinux and remove
# directories used by dnf that are just taking
# up space.
RUN yum -y install buildah fuse-overlayfs --exclude container-selinux; rm -rf /var/cache /var/log/dnf* /var/log/yum.*
# Adjust storage.conf to enable Fuse storage.
RUN sed -i -e 's|^#mount_program|mount_program|g' -e '/additionalimage.*/a "/var/lib/shared",' /etc/containers/storage.conf
Au lieu d'OverlayFS, implémenté au niveau du noyau Linux hôte, nous utilisons le programme à l'intérieur du conteneur
podman run --device /dev/fuse quay.io/buildahctr ...
RUN mkdir -p /var/lib/shared/overlay-images /var/lib/shared/overlay-layers; touch /var/lib/shared/overlay-images/images.lock; touch /var/lib/shared/overlay-layers/layers.lock
Ensuite, nous créons un répertoire pour un stockage supplémentaire.
# Set up environment variables to note that this is
# not starting with user namespace and default to
# isolate the filesystem with chroot.
ENV _BUILDAH_STARTED_IN_USERNS="" BUILDAH_ISOLATION=chroot
Enfin, en utilisant la variable d'environnement BUILDAH_ISOLATION, nous demandons au conteneur Buildah de s'exécuter avec l'isolation chroot par défaut. Une isolation supplémentaire n'est pas nécessaire ici, puisque nous travaillons déjà dans un conteneur. Pour que Buildah puisse créer ses propres conteneurs séparés par des espaces de noms, le privilège SYS_ADMIN est requis, ce qui nécessiterait d'assouplir les règles SELinux et SECCOMP du conteneur, ce qui est contraire à notre préférence de construire à partir d'un conteneur sécurisé.
Exécuter Buildah dans un conteneur
Le diagramme d'image du conteneur Buildah discuté ci-dessus vous permet de varier de manière flexible les méthodes de lancement de ces conteneurs.
Vitesse contre sécurité
La sécurité informatique est toujours un compromis entre la vitesse du processus et le niveau de protection qui l'entoure. Cette affirmation est également vraie lors de l'assemblage de conteneurs, nous examinerons donc ci-dessous les options pour un tel compromis.
L'image du conteneur discutée ci-dessus conservera son stockage dans /var/lib/containers. Par conséquent, nous devons monter le contenu dans ce dossier, et la manière dont nous procédons affectera grandement la vitesse de création des images de conteneur.
Considérons trois options.
1 Option. Si une sécurité maximale est requise, pour chaque conteneur, vous pouvez créer votre propre dossier pour les conteneurs/image et le connecter au conteneur via le montage en volume. Et d’ailleurs, placez le répertoire contextuel dans le conteneur lui-même, dans le dossier /build :
# mkdir /var/lib/containers1
# podman run -v ./build:/build:z -v /var/lib/containers1:/var/lib/containers:Z quay.io/buildah/stable
buildah -t image1 bud /build
# podman run -v /var/lib/containers1:/var/lib/containers:Z quay.io/buildah/stable buildah push image1 registry.company.com/myuser
# rm -rf /var/lib/containers1
Sécurité. Buildah exécuté dans un tel conteneur a une sécurité maximale : il ne bénéficie d'aucun privilège root pour utiliser les capacités, et toutes les restrictions SECOMP et SELinux s'y appliquent. Un tel conteneur peut même être exécuté avec l'isolation de l'espace de noms utilisateur en ajoutant une option comme —uidmap 0 : 100000 10000 : XNUMX XNUMX.
Performance. Mais les performances ici sont minimes, car toutes les images des registres de conteneurs sont copiées à chaque fois sur l'hôte et la mise en cache ne fonctionne pas du tout. Une fois son travail terminé, le conteneur Buildah doit envoyer l'image au registre et détruire le contenu sur l'hôte. La prochaine fois que l'image du conteneur sera créée, elle devra être à nouveau téléchargée à partir du registre, car à ce moment-là, il n'y aura plus rien sur l'hôte.
2 Option. Si vous avez besoin de performances au niveau Docker, vous pouvez monter le conteneur/stockage hôte directement dans le conteneur.
# podman run -v ./build:/build:z -v /var/lib/containers:/var/lib/containers --security-opt label:disabled quay.io/buildah/stable buildah -t image2 bud /build
# podman run -v /var/lib/containers:/var/lib/containers --security-opt label:disabled quay.io/buildah/stable buildah push image2 registry.company.com/myuser
Sécurité. Il s'agit du moyen le moins sécurisé de créer des conteneurs, car il permet au conteneur de modifier le stockage de l'hôte et pourrait potentiellement transmettre à Podman ou CRI-O une image malveillante. De plus, vous devrez désactiver la séparation SELinux afin que les processus du conteneur Buildah puissent interagir avec le stockage sur l'hôte. Notez que cette option est toujours meilleure qu'un socket Docker car le conteneur est verrouillé par les fonctionnalités de sécurité restantes et ne peut pas simplement exécuter un conteneur sur l'hôte.
Performance. Ici, c'est maximum, puisque la mise en cache est pleinement utilisée. Si Podman ou CRI-O ont déjà téléchargé l'image requise sur l'hôte, le processus Buildah à l'intérieur du conteneur n'aura pas besoin de la télécharger à nouveau, et les versions ultérieures basées sur cette image pourront également extraire ce dont ils ont besoin du cache. .
3 Option. L'essence de cette méthode est de combiner plusieurs images en un seul projet avec un dossier commun pour les images conteneurs.
# mkdir /var/lib/project3
# podman run --security-opt label_level=s0:C100, C200 -v ./build:/build:z
-v /var/lib/project3:/var/lib/containers:Z quay.io/buildah/stable buildah -t image3 bud /build
# podman run --security-opt label_level=s0:C100, C200
-v /var/lib/project3:/var/lib/containers quay.io/buildah/stable buildah push image3 registry.company.com/myuser
Dans cet exemple, nous ne supprimons pas le dossier du projet (/var/lib/project3) entre les exécutions, de sorte que toutes les versions ultérieures du projet bénéficient de la mise en cache.
Sécurité. Quelque chose entre les options 1 et 2. D'une part, les conteneurs n'ont pas accès au contenu sur l'hôte et, par conséquent, ne peuvent pas glisser quelque chose de mauvais dans le stockage d'images Podman/CRI-O. En revanche, de par sa conception, un conteneur peut gêner l’assemblage d’autres conteneurs.
Performance. Ici, c'est pire que lors de l'utilisation d'un cache partagé au niveau de l'hôte, puisque vous ne pouvez pas utiliser des images déjà téléchargées à l'aide de Podman/CRI-O. Cependant, une fois que Buildah a téléchargé l'image, celle-ci peut être utilisée dans toutes les versions ultérieures du projet.
Stockage supplémentaire
У
Si vous faites défiler vers le haut et regardez le Dockerfile que nous utilisons pour construire l'image quay.io/buildah/stable, il y a des lignes comme celle-ci :
# Adjust storage.conf to enable Fuse storage.
RUN sed -i -e 's|^#mount_program|mount_program|g' -e '/additionalimage.*/a "/var/lib/shared",' /etc/containers/storage.conf
RUN mkdir -p /var/lib/shared/overlay-images /var/lib/shared/overlay-layers; touch /var/lib/shared/overlay-images/images.lock; touch /var/lib/shared/overlay-layers/layers.lock
Dans la première ligne, nous modifions /etc/containers/storage.conf à l'intérieur de l'image du conteneur, indiquant au pilote de stockage d'utiliser « supplémentaires d'images » dans le dossier /var/lib/shared. Et dans la ligne suivante, nous créons un dossier partagé et ajoutons quelques fichiers de verrouillage afin qu'il n'y ait pas d'abus de la part des conteneurs/stockage. Essentiellement, nous créons simplement un magasin d’images de conteneur vide.
Si vous montez des conteneurs/stockage à un niveau supérieur à ce dossier, Buildah pourra utiliser les images.
Revenons maintenant à l'option 2 discutée ci-dessus, lorsque le conteneur Buildah peut lire et écrire dans les conteneurs/stocker sur les hôtes et, par conséquent, a des performances maximales grâce à la mise en cache des images au niveau Podman/CRI-O, mais fournit un minimum de sécurité. puisqu'il peut écrire directement sur le stockage. Ajoutons maintenant du stockage supplémentaire ici et obtenons le meilleur des deux mondes.
# mkdir /var/lib/containers4
# podman run -v ./build:/build:z -v /var/lib/containers/storage:/var/lib/shared:ro -v /var/lib/containers4:/var/lib/containers:Z quay.io/buildah/stable
buildah -t image4 bud /build
# podman run -v /var/lib/containers/storage:/var/lib/shared:ro
-v >/var/lib/containers4:/var/lib/containers:Z quay.io/buildah/stable buildah push image4 registry.company.com/myuser
# rm -rf /var/lib/continers4
Notez que le /var/lib/containers/storage de l'hôte est monté sur /var/lib/shared à l'intérieur du conteneur en mode lecture seule. Par conséquent, en travaillant dans un conteneur, Buildah peut utiliser toutes les images précédemment téléchargées à l'aide de Podman/CRI-O (bonjour, vitesse), mais ne peut écrire que sur son propre stockage (bonjour, sécurité). Notez également que cela se fait sans désactiver la séparation SELinux pour le conteneur.
Nuance importante
Vous ne devez en aucun cas supprimer des images du référentiel sous-jacent. Sinon, le conteneur Buildah risque de planter.
Et ce ne sont pas tous les avantages
Les possibilités de stockage supplémentaire ne se limitent pas au scénario ci-dessus. Par exemple, vous pouvez placer toutes les images de conteneurs sur un stockage réseau partagé et y donner accès à tous les conteneurs Buildah. Disons que nous avons des centaines d'images que notre système CI/CD utilise régulièrement pour créer des images de conteneurs. Nous concentrons toutes ces images sur un seul hôte de stockage puis, à l'aide des outils de stockage réseau privilégiés (NFS, Gluster, Ceph, ISCSI, S3...), nous ouvrons l'accès général à ce stockage à tous les nœuds Buildah ou Kubernetes.
Il suffit maintenant de monter ce stockage réseau dans le conteneur Buildah sur /var/lib/shared et c'est tout - les conteneurs Buildah n'ont plus besoin de télécharger d'images via pull. Ainsi, nous abandonnons la phase de pré-population et sommes immédiatement prêts à déployer les conteneurs.
Et bien sûr, cela peut être utilisé dans un système Kubernetes en direct ou une infrastructure de conteneurs pour lancer et exécuter des conteneurs n'importe où sans aucun téléchargement d'images. De plus, le registre de conteneurs, recevant une demande push pour y télécharger une image mise à jour, peut automatiquement envoyer cette image vers un stockage réseau partagé, où elle devient instantanément disponible pour tous les nœuds.
Les images de conteneurs peuvent parfois atteindre plusieurs gigaoctets. La fonctionnalité de stockage supplémentaire vous permet d'éviter de cloner de telles images sur des nœuds et rend le lancement de conteneurs presque instantané.
De plus, nous travaillons actuellement sur une nouvelle fonctionnalité appelée montages de volumes superposés, qui rendra la construction de conteneurs encore plus rapide.
Conclusion
Exécuter Buildah dans un conteneur dans Kubernetes/CRI-O, Podman ou même Docker est réalisable, simple et beaucoup plus sécurisé que d'utiliser docker.socket. Nous avons considérablement augmenté la flexibilité de travail avec les images, afin que vous puissiez les exécuter de différentes manières pour optimiser l'équilibre entre sécurité et performances.
La fonctionnalité de stockage supplémentaire vous permet d'accélérer, voire d'éliminer complètement le téléchargement d'images vers les nœuds.
Source: habr.com