Was ist das Besondere daran, die Ausführungsumgebung von Containern in separate Werkzeugkomponenten zu unterteilen? Besonders, dass man diese Werkzeuge miteinander kombinieren kann, um sich gegenseitig zu schützen.

Viele ziehen die Idee an, OCI-Container-Images im Rahmen von oder einem ähnlichen System zu erstellen. Angenommen, wir haben CI/CD, das kontinuierlich Images erstellt, dann wäre etwas wie /Kubernetes было бы весьма полезно с точки зрения распределения нагрузки при сборке. До недавних пор большинство людей просто давали контейнерам доступ к Docker-сокету и разрешали выполнять команду docker build. , dass dies sehr unsicher ist; tatsächlich ist es sogar schlimmer, als einem root oder sudo ohne Passwort zu geben.
Deshalb versuchen die Leute ständig, Buildah in einem Container auszuführen. Kurz gesagt, wir haben eine Vorgehensweise entworfen, von der wir glauben, dass sie am besten geeignet ist, um Buildah innerhalb eines Containers zu starten, und haben die entsprechenden Images auf . Lassen Sie uns anfangen…
Konfiguration
Diese Images wurden aus Dockerfiles erstellt, die im Buildah-Repository im Ordner .
zu finden sind. .
# 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
die stabile Version des Dockerfiles. fuse-overlay
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ätzliche Speicherorte. unterstützt das Konzept, zusätzliche schreibgeschützte Speicherorte für Images zu verbinden. Zum Beispiel kann man einen Overlay-Speicherbereich auf einem Rechner einrichten und dann dieses Speicherverzeichnis via NFS auf einem anderen Rechner bereitstellen und die Images daraus verwenden, ohne sie über Pull herunterzuladen. Wir benötigen dieses Speicherverzeichnis, um ein Image-Volume vom Host anzuhängen und innerhalb des Containers zu verwenden.
# 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 geben wir mit der Umgebungsvariable BUILDAH_ISOLATION an, dass standardmäßig der Buildah-Container mit chroot-Isolation gestartet werden soll. Zusätzliche Isolation ist hier nicht erforderlich, da wir bereits in einem Container arbeiten. Damit Buildah seine eigenen Container mit Namensraumtrennung erstellt, ist die SYS_ADMIN-Berechtigung erforderlich, was bedeutet, dass die SELinux- und SECCOMP-Regeln für den Container gelockert werden müssen, was im Widerspruch zu unserem Ansatz steht, Builds aus einem sicheren Container durchzuführen.
Wir führen Buildah im Container aus
Das oben dargestellte Schema des Buildah-Container-Images ermöglicht flexible Variationen der Startmethoden solcher Container.
Geschwindigkeit gegen Sicherheit
Computersicherheit ist stets ein Kompromiss zwischen der Ausführungsgeschwindigkeit und dem Schutzniveau, das darübergelegt wird. Diese Aussage gilt auch beim Erstellen von Containern, deshalb betrachten wir im Folgenden die Optionen für diesen Kompromiss.
Das oben besprochene Container-Image speichert seine Daten in /var/lib/containers. Daher müssen wir die Inhalte in diesen Ordner einbinden, und die Methode, wie wir dies tun, hat erheblichen Einfluss auf die Geschwindigkeit des Buildprozesses der Container-Images.
Betrachten wir drei Optionen.
Option 1. Wenn maximale Sicherheit gefordert ist, kann für jeden Container ein eigenes Verzeichnis für containers/image erstellt und über einen Volume-Mount mit dem Container verbunden werden. Zudem kann das Kontextverzeichnis direkt im Container im Ordner /build platziert werden:
# 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. Ein in einem solchen Container arbeitendes Buildah hat die höchste Sicherheit: Es erhält keine Root-Rechte durch Capabilities, und alle SECOMP- und SELinux-Einschränkungen werden angewandt. Ein solcher Container kann sogar mit User Namespace-Isolierung gestartet werden, indem eine Option wie —uidmap 0:100000:10000 hinzugefügt wird.
Leistung. Die Leistung ist hier minimal, da alle Images aus Container-Repositories jedes Mal auf den Host kopiert werden und das Caching überhaupt nicht funktioniert. Nach der Nutzung muss der Buildah-Container das Image ins Repository hochladen und den Inhalt auf dem Host löschen. Wenn das Container-Image beim nächsten Mal wieder aufgebaut wird, muss es erneut aus dem Repository heruntergeladen werden, da zu diesem Zeitpunkt auf dem Host nichts mehr vorhanden sein wird.
Option 2. Wenn Sie Leistung auf Docker-Niveau benötigen, können Sie den container/storage des Hosts direkt im 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 hier berechtigt ist, das Storage auf dem Host zu verändern, und potenziell kann er Podman oder CRI-O ein bösartiges Image unterjubeln. Darüber hinaus muss die SELinux-Trennung deaktiviert werden, damit die Prozesse im Buildah-Container mit dem Storage auf dem Host interagieren können. Beachten Sie, dass diese Option dennoch besser als der Docker-Socket ist, da der Container durch die verbleibenden Sicherheitsfunktionen blockiert wird und nicht einfach einen beliebigen Container auf dem Host starten 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 innerhalb des Containers es nicht erneut herunterladen, und auch spätere Builds, die auf diesem Image basieren, können das Benötigte aus dem Cache abrufen.
Option 3. Die Idee dieser Methode besteht darin, mehrere Images zu einem Projekt mit einem gemeinsamen Ordner für Container-Images 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 Starts nicht, sodass alle nachfolgenden Builds im Rahmen des Projekts von den Vorteilen des Caching profitieren.
Sicherheit. Etwas zwischen Option 1 und 2. Einerseits haben die Container keinen Zugriff auf den Inhalt des Hosts und können daher nichts Schlechtes in das Image-Repository von Podman/CRI-O einschleusen. Andererseits kann der Container im Rahmen seines Projekts in den Build anderer Container eingreifen.
Leistung. Hier ist es schlechter als bei der Verwendung des gemeinsam genutzten Caches auf Hostebene, da bereits zuvor heruntergeladene Images mit Podman/CRI-O nicht verwendet werden können. Nachdem Buildah das Image jedoch heruntergeladen hat, kann es in allen nachfolgenden Builds innerhalb des Projekts verwendet werden.
Zusätzliche Repositories
U Es gibt diese großartige Funktion namens zusätzliche Repositories (additional stores), die es Container-Engines ermöglicht, beim Starten und Erstellen von Containern externe Image-Repositories im schreibgeschützten Overlay-Modus zu verwenden. Im Grunde genommen können in die Datei storage.conf ein oder mehrere "nur zur Lektüre"-Repositories hinzugefügt werden, so dass die Container-Engine beim Start des Containers in diesen Repositories nach dem benötigten Image suchen kann. Das Image wird nur aus dem Registry heruntergeladen, wenn es in keinem dieser Repositories gefunden wird. Die Container-Engine kann nur in für das Schreiben zugängliche Repositories schreiben...
Wenn Sie nach oben scrollen und sich das Dockerfile ansehen, das wir zum Erstellen des Images quay.io/buildah/stable verwenden, finden Sie dort folgende Zeilen:
# 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 modifizieren wir /etc/containers/storage.conf innerhalb des Container-Images und weisen den Storage-Treiber an, die "additionalimagestores" im Verzeichnis /var/lib/shared zu verwenden. In der folgenden Zeile erstellen wir einen gemeinsamen Ordner und fügen einige Lock-Dateien hinzu, um Konflikte mit containers/storage zu vermeiden. Im Grunde genommen schaffen wir einfach einen leeren Speicher für Container-Images.
Wenn man containers/storage über diesem Ordner einbindet, kann Buildah die Images nutzen.
Jetzt kehren wir zu dem oben besprochenen Szenario 2 zurück, in dem der Buildah-Container in containers/store auf Hosts lesen und schreiben kann und somit maximale Leistung durch die Zwischenspeicherung der Images auf Podman/CRI-O-Ebene erzielt, jedoch minimalen Schutz bietet, da er direkt in die Speicher schreiben kann. Lassen Sie uns nun zusätzliche Speicherorte hinzufügen und das Beste aus beiden Welten erhalten.
# 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
Bitte beachten Sie, dass das Verzeichnis /var/lib/containers/storage des Hosts im Container unter /var/lib/shared im Nur-Lese-Modus eingebunden ist. Daher kann Buildah im Container auf alle zuvor heruntergeladenen Images von Podman/CRI-O zugreifen (Hallo, Geschwindigkeit), aber es kann nur in seinen eigenen Speicher schreiben (Hallo, Sicherheit). Auch ist zu beachten, dass dies ohne Deaktivierung der SELinux-Trennung für den Container erfolgt.
Wichtiger Hinweis
Es sollten auf keinen Fall irgendwelche Images aus dem zugrunde liegenden Speicher entfernt werden. Andernfalls kann der Buildah-Container abstürzen.
Und das sind längst nicht alle Vorteile
Die Möglichkeiten zusätzlicher Speicherlösungen beschränken sich nicht nur auf das oben beschriebene Szenario. Beispielsweise können alle Container-Images in einem gemeinsamen Netzwerkspeicher abgelegt werden, auf den alle Buildah-Container zugreifen können. Angenommen, wir haben Hunderte von Images, die unser CI/CD-System regelmäßig zur Erstellung von Container-Images verwendet. Wir konzentrieren all diese Images auf einem bestimmten Host-Speicher und eröffnen dann den Zugriff auf dieses Speicher mit bevorzugten Netzwerkspeichermethoden (NFS, Gluster, Ceph, ISCSI, S3…) für alle Buildah- oder Kubernetes-Knoten.
Jetzt muss dieses Netzwerkspeicher lediglich in den Buildah-Container unter /var/lib/shared eingebunden werden – und das war's. Die Buildah-Container müssen die Images nicht mehr über Pull herunterladen. Damit entfällt die Phase der Vorbefüllung, und wir können sofort mit dem Rollout der Container beginnen.
Natürlich kann dies innerhalb des bestehenden Kubernetes-Systems oder der Container-Infrastruktur verwendet werden, um Container überall auszuführen, ohne Images über Pull herunterzuladen. Darüber hinaus kann das Container-Registry, das einen Push-Anruf zum Hochladen eines aktualisierten Images erhält, dieses Image automatisch in einen gemeinsamen Netzwerkspeicher senden, wo es sofort für alle Nodes verfügbar ist.
Die Größen von Container-Images können manchmal mehrere Gigabyte erreichen. Die Funktion zusätzlicher Speicher ermöglicht es, solche Images nicht auf jeder Node zu klonen, was den Start von Containern nahezu sofort macht.
Darüber hinaus arbeiten wir derzeit an einer neuen Funktion für Overlay-Volume-Mounts, die den Aufbau von Containern noch schneller machen wird.
Fazit
Es ist durchaus möglich, Buildah innerhalb eines Containers in einer Kubernetes/CRI-O-, Podman- oder sogar Docker-Umgebung auszuführen. Darüber hinaus ist es einfach und viel sicherer, als docker.socket zu verwenden. Wir haben die Flexibilität bei der Arbeit mit Images erheblich verbessert, sodass Sie sie nun auf verschiedene Weise ausführen können, um ein optimales Gleichgewicht zwischen Sicherheit und Leistung zu erzielen.
Die Funktionalität zusätzlicher Speicherlösungen ermöglicht es, den Download von Images auf Knoten zu beschleunigen oder sogar vollständig zu eliminieren.
Quelle: habr.com
