Wat is de charme van het splitsen van de uitvoeringsomgeving van containers in afzonderlijke instrumentele componenten? In wezen is het zo dat deze tools gecombineerd kunnen worden om elkaar te beschermen.

Veel mensen worden aangetrokken door het idee om OCI-containerafbeeldingen te bouwen binnen de of een soortgelijk systeem. Stel dat we een CI/CD hebben die voortdurend afbeeldingen bouwt, dan iets zoals /Kubernetes было бы весьма полезно с точки зрения распределения нагрузки при сборке. До недавних пор большинство людей просто давали контейнерам доступ к Docker-сокету и разрешали выполнять команду docker build. , dat dit zeer onveilig is, in feite zelfs slechter dan het geven van een wachtwoordloze root of sudo.
Daarom proberen mensen voortdurend Buildah in een container te draaien. Kortom, we hebben hoe wij denken dat je Buildah het beste binnen een container kunt draaien, en we hebben de bijbehorende afbeeldingen op . Laten we beginnen...
Instellingen
Deze afbeeldingen zijn opgebouwd uit Dockerfiles die te vinden zijn in de Buildah-repository in de map .
Hier zullen we kijken naar .
# 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
In plaats van OverlayFS, geïmplementeerd op het niveau van de host Linux-kernel, gebruiken we binnen de container het programma , omdat OverlayFS op dit moment alleen kan worden gemonteerd als het SYS_ADMIN-rechten krijgt via Linux-capabilities. En we willen onze Buildah-containers draaien zonder enige root-privileges. Fuse-overlay werkt behoorlijk snel en is qua prestaties beter dan de storage driver VFS. Let op dat bij het draaien van een Buildah-container die Fuse gebruikt, het apparaat /dev/fuse moet worden verstrekt.
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
Vervolgens maken we een map voor extra opslag. ondersteunt het concept van extra read-only opslaggebieden voor afbeeldingen. Zo kan een overlay storage area op één machine worden ingesteld en vervolgens via NFS op een andere machine worden aangekoppeld, zodat afbeeldingen zonder te downloaden via pull kunnen worden gebruikt. We hebben deze opslag nodig om een opslagplaats vanaf de host als volume aan te sluiten en deze binnen de container te gebruiken.
# 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
En tenslotte, door gebruik te maken van de omgevingsvariabele BUILDAH_ISOLATION, geven we aan dat de Buildah-container standaard moet worden uitgevoerd met chroot-isolatie. Extra isolatie is hier niet nodig, aangezien we al in een container werken. Om Buildah zijn eigen containers met naamruimte-isolatie te laten maken, is de SYS_ADMIN-privilege vereist, wat betekent dat we de SELinux- en SECCOMP-regels voor de container moeten versoepelen, wat in strijd is met onze installatie om de bouw uit een veilige container uit te voeren.
Start Buildah binnen de container
Het bovenstaande schema van het Buildah-containerbeeld maakt het mogelijk om flexibel te variëren met de manieren om dergelijke containers te starten.
Snelheid versus veiligheid
Computerveiligheid is altijd een compromis tussen de snelheid van het proces en de hoeveelheid bescherming die eromheen is opgebouwd. Deze stelling is ook waar bij het bouwen van containers, dus hieronder bekijken we de opties voor dit compromis.
Het hierboven besproken containerbeeld zal zijn opslag houden in /var/lib/containers. Daarom moeten we de inhoud in deze map ondermounten, en de manier waarop we dit doen zal aanzienlijk invloed hebben op de snelheid van het bouwen van containerbeelden.
Laten we drie opties bekijken.
Optie 1. Als maximale veiligheid vereist is, kan voor elke container een aparte map voor containers/image worden aangemaakt en deze aan de container worden gekoppeld via volume-mount. Bovendien kan de contextdirectory in de container zelf worden geplaatst, in de map /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
Beveiliging. Buildah die in zo'n container werkt, heeft maximale veiligheid: het krijgt geen root-rechten via capabilities, en alle SECOMP- en SELinux-beperkingen zijn van toepassing. Zo'n container kan zelfs worden uitgevoerd met User Namespace-isolatie, door een optie zoals --uidmap 0:100000:10000 toe te voegen.
Performance. De prestaties zijn hier echter minimaal, aangezien alle afbeeldingen uit containerregisters telkens opnieuw naar de host worden gekopieerd, en caching werkt helemaal niet. Wanneer het Buildah-container zijn werk heeft beëindigd, moet het de afbeelding naar het register sturen en de inhoud op de host vernietigen. Wanneer het containerbeeld de volgende keer wordt gebouwd, moet het opnieuw uit het register worden gedownload, aangezien er op de host tegen die tijd niets meer zal zijn.
Optie 2. Als je prestaties op Docker-niveau nodig hebt, kun je de container/storage van de host direct in de container monteren.
# 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
Beveiliging. Dit is de minst veilige manier om containers te bouwen, omdat de container hier is toegestaan om de opslag op de host te wijzigen, en potentieel kan hij een schadelijk beeld aan Podman of CRI-O doorgeven. Bovendien moet je SELinux-scheiding uitschakelen, zodat processen in de Buildah-container kunnen communiceren met de opslag op de host. Houd er rekening mee dat deze optie nog steeds beter is dan de Docker-socket, omdat de container wordt geblokkeerd door de resterende beveiligingsfuncties en niet zomaar een container op de host kan starten.
Performance. Hier is het maximaal, omdat caching volledig wordt benut. Als Podman of CRI-O het benodigde beeld al op de host heeft gedownload, hoeft het Buildah-proces binnen de container het niet opnieuw te downloaden, en toekomstige builds op basis van dit beeld kunnen ook gebruikmaken van de cache.
Optie 3. De essentie van deze methode is om meerdere beelden in één project te combineren met een gemeenschappelijke map voor containerbeelden.
# 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 dit voorbeeld verwijderen we de projectmap (/var/lib/project3) niet tussen de runs, zodat alle volgende builds binnen het project profiteren van caching.
Beveiliging. Dit is een tussenoplossing tussen opties 1 en 2. Aan de ene kant hebben containers geen toegang tot de inhoud op de host en kunnen ze dus niets kwaads in de opslag van Podman/CRI-O doorgeven. Aan de andere kant kan de container binnen zijn project invloed uitoefenen op de build van andere containers.
Performance. Hier is het slechter dan bij het gebruik van een gedeelde cache op hostniveau, omdat je beelden die eerder met Podman/CRI-O zijn gedownload, niet kunt gebruiken. Maar zodra Buildah een beeld heeft gedownload, kan dat beeld worden gebruikt in alle daaropvolgende builds binnen het project.
Aanvullende opslagplaatsen
Er Er is zoiets geweldigs als aanvullende opslag (additional stores), waarmee tijdens het opstarten en samenstellen van containers, container engines externe opslagplaatsen van afbeeldingen in read-only overlaymodus kunnen gebruiken. In feite kan je in het bestand storage.conf één of meerdere 'alleen-lezen' opslagplaatsen toevoegen, zodat de container engine bij het opstarten van de container in deze opslagplaatsen de benodigde afbeelding zoekt. De engine zal de afbeelding alleen vanuit de registry downloaden als hij deze in geen van deze opslagplaatsen kan vinden. De container engine kan alleen schrijven naar de opslagplaatsen die schrijfbaar zijn...
Als we omhoog scrollen en de Dockerfile bekijken die we gebruiken voor het bouwen van de afbeelding quay.io/buildah/stable, zien we de volgende regels:
# 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 de eerste regel wijzigen we /etc/containers/storage.conf binnen de container afbeelding, en geven we de storage-driver de instructie om 'additionalimagestores' te gebruiken in de map /var/lib/shared. In de volgende regel creëren we een gedeelde map en voegen we een paar lock-bestanden toe om conflicten van containers/storage te voorkomen. In wezen creëren we gewoon een leeg opslagplaats voor containerafbeeldingen.
Als we containers/storage één niveau hoger dan deze map koppelen, kan Buildah beelden gebruiken.
Laten we nu terugkomen op de eerder besproken Optie 2, waarbij de Buildah-container kan lezen en schrijven in containers/store op de hosts en daardoor maximale prestaties verkrijgt door afbeeldingen op Podman/CRI-O-niveau te cachen, maar minimale beveiliging biedt omdat het direct in de opslagplaatsen kan schrijven. En nu voegen we hier aanvullende opslagplaatsen aan toe en krijgen we het beste van twee werelden.
# 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
Let op dat /var/lib/containers/storage van de host is gekoppeld aan /var/lib/shared binnen de container in read-only modus. Daarom kan Buildah, terwijl hij in de container werkt, elke afbeelding gebruiken die eerder is gedownload via Podman/CRI-O (hallo, snelheid), maar kan hij alleen in zijn eigen opslagplaats schrijven (hallo, veiligheid). Let ook op dat dit gebeurt zonder de SELinux-scheiding voor de container uit te schakelen.
Belangrijk punt
Verwijder absoluut geen afbeeldingen uit de onderliggende opslag. Anders kan de Buildah-container crashen.
En dit is zeker niet alles qua voordelen
De mogelijkheden van extra opslag beperken zich niet tot het hierboven beschreven scenario. Je kunt bijvoorbeeld alle containerafbeeldingen in een gedeelde netopslag plaatsen en toegang geven aan alle Buildah-containers. Stel dat we honderden afbeeldingen hebben die ons CI/CD-systeem regelmatig gebruikt voor het bouwen van containerafbeeldingen. We concentreren al deze afbeeldingen op één host-opslag en openen vervolgens, met behulp van de voorkeursmethoden voor netopslag (NFS, Gluster, Ceph, ISCSI, S3…), de gedeelde toegang tot deze opslag voor alle Buildah- of Kubernetes-nodes.
Het is nu voldoende om deze netopslag te koppelen aan de Buildah-container op /var/lib/shared, en dat is het – Buildah-containers hoeven geen afbeeldingen meer via pull te downloaden. Op deze manier elimineren we de fase van voorvervulling (pre-population) en zijn we direct klaar om container uit te rollen.
En natuurlijk kan dit worden gebruikt binnen een bestaand Kubernetes-systeem of containerinfrastructuur om containers overal te starten en uit te voeren zonder afbeeldingen via pull te downloaden. Bovendien kan de containerregistratie, bij het ontvangen van een push-verzoek voor een bijgewerkte afbeelding, deze afbeelding automatisch naar de gedeelde netopslag verzenden, waar deze onmiddellijk toegankelijk is voor alle nodes.
De grootte van containerafbeeldingen kan soms vele gigabytes bedragen. De functionaliteit van extra opslag maakt het mogelijk om dergelijke afbeeldingen niet over de nodes te clonen en maakt het starten van containers vrijwel direct.
Daarnaast werken we momenteel aan een nieuwe functie voor overlay volume mounts, die het bouwen van containers nog sneller zal maken.
Conclusie
Het uitvoeren van Buildah binnen een container in een Kubernetes/CRI-O, Podman of zelfs Docker-omgeving is heel goed mogelijk, bovendien is het eenvoudig en veel veiliger dan het gebruik van docker.socket. We hebben de flexibiliteit in het werken met afbeeldingen aanzienlijk vergroot, en nu kun je ze op verschillende manieren uitvoeren voor een optimale balans tussen veiligheid en prestaties.
De functionaliteit van extra opslag versnelt of elimineert zelfs volledig het downloaden van afbeeldingen naar nodes.
Bron: habr.com
