Richtlinien zum Ausführen von Buildah in einem Container

Was ist das Schöne daran, die Container-Laufzeit in separate Tooling-Komponenten zu entkoppeln? Insbesondere können diese Werkzeuge so kombiniert werden, dass sie sich gegenseitig schützen.

Richtlinien zum Ausführen von Buildah in einem Container

Viele Menschen fühlen sich von der Idee angezogen, darin containerisierte OCI-Bilder zu erstellen Kubernetes oder ähnliches System. Nehmen wir an, wir haben ein CI/CD, das ständig Bilder sammelt, dann so etwas wie Red Hat OpenShift/Kubernetes wäre im Hinblick auf den Lastausgleich während Builds sehr nützlich. Bis vor kurzem gewährten die meisten Leute Containern einfach Zugriff auf einen Docker-Socket und erlaubten ihnen, den Docker-Build-Befehl auszuführen. Vor einigen Jahren haben wir es gezeigtdass dies sehr unsicher ist, tatsächlich ist es sogar noch schlimmer, als root oder sudo ohne Passwort zu vergeben.

Aus diesem Grund wird ständig versucht, Buildah in einem Container auszuführen. Kurz gesagt, wir haben geschaffen Beispiel Wie unserer Meinung nach Buildah am besten in einem Container ausgeführt werden kann, und haben die entsprechenden Bilder gepostet quay.io/buildah. Lass uns anfangen...

Einstellung

Diese Images werden aus Dockerfiles erstellt, die im Buildah-Repository im Ordner zu finden sind buildahimage.
Hier werden wir uns das ansehen stabile Version von Dockerfile.

# 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

Anstelle von OverlayFS, das auf der Ebene des Host-Linux-Kernels implementiert ist, verwenden wir das Programm im Container Sicherungsüberlagerung, da OverlayFS derzeit nur gemountet werden kann, wenn Sie ihm mithilfe von Linux-Funktionen SYS_ADMIN-Berechtigungen erteilen. Und wir möchten unsere Buildah-Container ohne Root-Rechte ausführen. Fuse-Overlay arbeitet recht schnell und bietet eine bessere Leistung als der VFS-Speichertreiber. Bitte beachten Sie, dass Sie beim Ausführen eines Buildah-Containers, der Fuse verwendet, das Gerät /dev/fuse bereitstellen müssen.

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

Als nächstes erstellen wir ein Verzeichnis für zusätzlichen Speicher. Container/Lagerung unterstützt das Konzept der Anbindung zusätzlicher schreibgeschützter Bildspeicher. Sie können beispielsweise einen Overlay-Speicherbereich auf einer Maschine konfigurieren und dann NFS verwenden, um diesen Speicher auf einer anderen Maschine bereitzustellen und Bilder von dort zu verwenden, ohne sie per Pull herunterzuladen. Wir benötigen diesen Speicher, um einen Teil des Image-Speichers vom Host als Volume anbinden und im Container verwenden zu können.

# 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

Schließlich weisen wir den Buildah-Container mithilfe der Umgebungsvariablen BUILDAH_ISOLATION an, standardmäßig mit Chroot-Isolation ausgeführt zu werden. Eine zusätzliche Isolierung ist hier nicht erforderlich, da wir bereits in einem Container arbeiten. Damit Buildah seine eigenen, durch Namespaces getrennten Container erstellen kann, ist die Berechtigung SYS_ADMIN erforderlich, was eine Lockerung der SELinux- und SECCOMP-Regeln des Containers erfordern würde, was im Widerspruch zu unserer Präferenz steht, aus einem sicheren Container zu erstellen.

Buildah in einem Container ausführen

Mit dem oben besprochenen Buildah-Container-Image-Diagramm können Sie die Methoden zum Starten solcher Container flexibel variieren.

Geschwindigkeit versus Sicherheit

Computersicherheit ist immer ein Kompromiss zwischen der Geschwindigkeit des Prozesses und dem Umfang des Schutzes. Diese Aussage gilt auch für die Montage von Containern, daher werden wir im Folgenden Optionen für einen solchen Kompromiss betrachten.

Das oben besprochene Container-Image behält seinen Speicher in /var/lib/containers. Daher müssen wir den Inhalt in diesem Ordner bereitstellen. Die Art und Weise, wie wir dies tun, hat großen Einfluss auf die Geschwindigkeit der Erstellung von Container-Images.

Betrachten wir drei Optionen.

1 Option. Wenn maximale Sicherheit erforderlich ist, können Sie für jeden Container einen eigenen Ordner für Container/Image erstellen und diesen per Volume-Mount mit dem Container verbinden. Platzieren Sie außerdem das Kontextverzeichnis im Container selbst, im Ordner /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

Sicherheit. Buildah, das in einem solchen Container ausgeführt wird, bietet maximale Sicherheit: Es erhält keine Root-Rechte für die Nutzung von Funktionen und es gelten alle SECOMP- und SELinux-Einschränkungen. Ein solcher Container kann sogar mit Benutzernamespace-Isolation ausgeführt werden, indem eine Option wie „uidmap 0“ hinzugefügt wird: 100000:10000.

Leistung. Allerdings ist die Leistung hier minimal, da alle Bilder aus Container-Registern jedes Mal auf den Host kopiert werden und das Caching überhaupt nicht funktioniert. Nach Abschluss seiner Arbeit muss der Buildah-Container das Image an die Registrierung senden und den Inhalt auf dem Host zerstören. Wenn das Container-Image das nächste Mal erstellt wird, muss es erneut aus der Registrierung heruntergeladen werden, da zu diesem Zeitpunkt nichts mehr auf dem Host vorhanden ist.

2 Option. Wenn Sie Leistung auf Docker-Ebene benötigen, können Sie den Host-Container/Speicher direkt in den Container einbinden.

# 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

Sicherheit. Dies ist die am wenigsten sichere Methode zum Erstellen von Containern, da der Container dadurch den Hostspeicher ändern kann und Podman oder CRI-O möglicherweise ein bösartiges Image liefern könnte. Darüber hinaus müssen Sie die SELinux-Trennung deaktivieren, damit Prozesse im Buildah-Container mit dem Speicher auf dem Host interagieren können. Beachten Sie, dass diese Option immer noch besser ist als ein Docker-Socket, da der Container durch verbleibende Sicherheitsfunktionen gesperrt ist und nicht einfach einen Container auf dem Host ausführen kann.

Leistung. Hier ist es maximal, da das Caching vollständig genutzt wird. Wenn Podman oder CRI-O das erforderliche Image bereits auf den Host heruntergeladen haben, muss der Buildah-Prozess im Container es nicht erneut herunterladen, und nachfolgende Builds, die auf diesem Image basieren, können auch das, was sie benötigen, aus dem Cache übernehmen .

3 Option. Der Kern dieser Methode besteht darin, mehrere Bilder in einem Projekt mit einem gemeinsamen Ordner für Containerbilder zu kombinieren.

# 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

In diesem Beispiel löschen wir den Projektordner (/var/lib/project3) zwischen den Läufen nicht, sodass alle nachfolgenden Builds innerhalb des Projekts vom Caching profitieren.

Sicherheit. Etwas zwischen den Optionen 1 und 2. Einerseits haben Container keinen Zugriff auf Inhalte auf dem Host und können dementsprechend keine schädlichen Inhalte in den Podman/CRI-O-Bildspeicher schleusen. Andererseits kann ein Behälter konstruktionsbedingt die Montage anderer Behälter behindern.

Leistung. Hier ist es schlimmer als bei der Verwendung eines Shared Caches auf Host-Ebene, da Sie keine Bilder verwenden können, die bereits mit Podman/CRI-O heruntergeladen wurden. Sobald Buildah das Image jedoch herunterlädt, kann es in allen nachfolgenden Builds innerhalb des Projekts verwendet werden.

Zusätzlicher Speicher

У Behälter/Lagerung Es gibt so etwas Cooles wie zusätzliche Stores (zusätzliche Stores), dank derer Container-Engines beim Starten und Erstellen von Containern externe Image-Stores im schreibgeschützten Overlay-Modus verwenden können. Im Wesentlichen können Sie der Datei storage.conf einen oder mehrere schreibgeschützte Speicher hinzufügen, sodass die Container-Engine beim Starten des Containers nach dem gewünschten Bild darin sucht. Darüber hinaus wird das Bild nur dann aus der Registrierung heruntergeladen, wenn es in keinem dieser Speicher gefunden wird. Die Container-Engine kann nur in beschreibbaren Speicher schreiben ...

Wenn Sie nach oben scrollen und sich die Docker-Datei ansehen, die wir zum Erstellen des Images quay.io/buildah/stable verwenden, finden Sie Zeilen wie diese:

# 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

In der ersten Zeile ändern wir /etc/containers/storage.conf im Container-Image und weisen den Speichertreiber an, „additionalimagestores“ im Ordner /var/lib/shared zu verwenden. Und in der nächsten Zeile erstellen wir einen freigegebenen Ordner und fügen ein paar Sperrdateien hinzu, damit kein Missbrauch durch Container/Speicher erfolgt. Im Wesentlichen erstellen wir einfach einen leeren Container-Image-Speicher.

Wenn Sie Container/Speicher auf einer höheren Ebene als diesem Ordner bereitstellen, kann Buildah die Bilder verwenden.

Kehren wir nun zur oben besprochenen Option 2 zurück, bei der der Buildah-Container in Containern/Speichern auf Hosts lesen und schreiben kann und dementsprechend aufgrund der Zwischenspeicherung von Bildern auf der Podman/CRI-O-Ebene maximale Leistung bietet, aber seitdem ein Minimum an Sicherheit bietet Es kann direkt in den Speicher schreiben. Jetzt fügen wir hier zusätzlichen Speicher hinzu und holen uns das Beste aus beiden Welten.

# 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

Beachten Sie, dass /var/lib/containers/storage des Hosts im schreibgeschützten Modus in /var/lib/shared im Container gemountet wird. Daher kann Buildah bei der Arbeit in einem Container alle Bilder verwenden, die zuvor mit Podman/CRI-O heruntergeladen wurden (Hallo, Geschwindigkeit), aber nur in seinen eigenen Speicher schreiben (Hallo, Sicherheit). Beachten Sie außerdem, dass dies erfolgt, ohne die SELinux-Trennung für den Container zu deaktivieren.

Wichtige Nuance

Unter keinen Umständen sollten Sie Bilder aus dem zugrunde liegenden Repository löschen. Andernfalls kann der Buildah-Container abstürzen.

Und das sind nicht alle Vorteile

Die Möglichkeiten der zusätzlichen Speicherung sind nicht auf das oben genannte Szenario beschränkt. Sie können beispielsweise alle Container-Images auf einem gemeinsamen Netzwerkspeicher platzieren und allen Buildah-Containern Zugriff darauf gewähren. Nehmen wir an, wir haben Hunderte von Images, die unser CI/CD-System regelmäßig zum Erstellen von Container-Images verwendet. Wir konzentrieren alle diese Bilder auf einem Speicherhost und öffnen dann mithilfe der bevorzugten Netzwerkspeichertools (NFS, Gluster, Ceph, ISCSI, S3...) den allgemeinen Zugriff auf diesen Speicher für alle Buildah- oder Kubernetes-Knoten.

Jetzt reicht es aus, diesen Netzwerkspeicher im Buildah-Container unter /var/lib/shared zu mounten, und das war's – Buildah-Container müssen Bilder nicht mehr per Pull herunterladen. Somit entfällt die Vorbestückungsphase und wir sind sofort bereit, die Container auszurollen.

Und natürlich kann dies innerhalb eines Live-Kubernetes-Systems oder einer Container-Infrastruktur verwendet werden, um Container überall zu starten und auszuführen, ohne dass Bilder per Pull-Download heruntergeladen werden müssen. Darüber hinaus kann die Container-Registrierung, wenn sie eine Push-Anfrage zum Hochladen eines aktualisierten Bildes erhält, dieses Bild automatisch an einen gemeinsam genutzten Netzwerkspeicher senden, wo es sofort allen Knoten zur Verfügung steht.

Container-Images können manchmal eine Größe von mehreren Gigabyte erreichen. Durch die Funktionalität des zusätzlichen Speichers können Sie das Klonen solcher Images über Knoten hinweg vermeiden und das Starten von Containern nahezu augenblicklich durchführen.

Darüber hinaus arbeiten wir derzeit an einer neuen Funktion namens Overlay Volume Mounts, die das Erstellen von Containern noch schneller machen wird.

Abschluss

Das Ausführen von Buildah in einem Container in Kubernetes/CRI-O, Podman oder sogar Docker ist machbar, einfacher und viel sicherer als die Verwendung von docker.socket. Wir haben die Flexibilität bei der Arbeit mit Bildern erheblich erhöht, sodass Sie sie auf vielfältige Weise ausführen können, um das Gleichgewicht zwischen Sicherheit und Leistung zu optimieren.

Die Funktionalität des zusätzlichen Speichers ermöglicht es Ihnen, das Herunterladen von Bildern auf Knoten zu beschleunigen oder sogar ganz zu eliminieren.

Source: habr.com

Kommentar hinzufügen