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.
Viele Menschen fühlen sich von der Idee angezogen, darin containerisierte OCI-Bilder zu erstellen
Aus diesem Grund wird ständig versucht, Buildah in einem Container auszuführen. Kurz gesagt, wir haben geschaffen
Einstellung
Diese Images werden aus Dockerfiles erstellt, die im Buildah-Repository im Ordner zu finden sind
Hier werden wir uns das ansehen
# 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
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.
# 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
У
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