Rekommendationer för att köra Buildah inuti en container

Vad är fördelarna med att dela upp körmiljön för containrar i separata verktygskomponenter? Bland annat att dessa verktyg kan börja kombineras för att skydda varandra.

Rekommendationer för att köra Buildah inuti en container

Många attraheras av idén att bygga OCI-bilder för containrar inom Kubernetes eller ett liknande system. Anta att vi har CI/CD som kontinuerligt bygger bilder, då är något som Red Hat OpenShift/Kubernetes было бы весьма полезно с точки зрения распределения нагрузки при сборке. До недавних пор большинство людей просто давали контейнерам доступ к Docker-сокету и разрешали выполнять команду docker build. Vi visade redan för flera år sedan, att detta är mycket osäkert, faktiskt är det till och med sämre än att ge root- eller sudo-åtkomst utan lösenord.

Därför försöker folk ständigt att köra Buildah i en container. Kort sagt, vi skapade exempel det som vi anser är det bästa sättet att köra Buildah inuti en container och publicerade de relevanta bilderna på quay.io/buildah. Låt oss börja...

Inställning

Dessa bilder är sammanställda från Dockerfiles som kan hittas i Buildah-förvaret i mappen buildahimage.
Här kommer vi att titta på den stabila versionen av 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

Istället för OverlayFS, som implementeras på värdens Linux-kärnnivå, använder vi inuti containern programmet fuse-overlay, eftersom OverlayFS för närvarande endast kan montera om den får SYS_ADMIN-behörighet via Linux-capabilities. Och vi vill köra våra Buildah-containrar utan några root-behörigheter. Fuse-overlay fungerar ganska snabbt och presterar bättre än lagringsdrivrutinen VFS. Observera att när du kör en Buildah-container som använder Fuse, krävs det att du tillhandahåller en enhet \/dev\/fuse.

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

Därefter skapar vi en katalog för ytterligare lagringsutrymmen. Container\/storage stöder konceptet att koppla in ytterligare skrivskyddade lagringsutrymmen för bilder. Till exempel kan du ställa in overlay-lagringsområde på en maskin, och sedan under montera detta lagringsutrymme på en annan maskin via NFS och använda bilder från det utan att ladda ner genom pull. Vi behöver detta lagringsutrymme för att kunna koppla en volym från värden och använda den inuti containern.

# 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

Och slutligen, genom att använda miljövariabeln BUILDAH_ISOLATION säger vi att Buildah-kontainern som standard ska köras med chroot-isolering. Ytterligare isolering behövs inte här eftersom vi redan arbetar i en kontainer. För att Buildah ska kunna skapa sina egna kontainrar med namnrymder krävs SYS_ADMIN-rättigheter, vilket innebär att vi måste lätta på SELinux- och SECCOMP-reglerna för kontainern, vilket strider mot vår installation att bygga från en säker kontainer.

Starta Buildah inuti en kontainer

Den beskrivna modellen för Buildah-kontainern tillåter flexibilitet i hur sådana kontainrar körs.

Hastighet kontra säkerhet

Datasäkerhet är alltid en kompromiss mellan hastigheten på processen och hur mycket skydd som är på plats. Detta påstående gäller även vid byggande av kontainrar, så nedan kommer vi att överväga alternativ för en sådan kompromiss.

Den tidigare nämnda kontainerbilden kommer att hålla sitt lagringsutrymme i /var/lib/containers. Därför måste vi montera innehållet i denna mapp, och hur vi gör det kommer att påverka hastigheten på byggandet av kontainerbilder avsevärt.

Vi överväger tre alternativ.

Alternativ 1. Om maximal säkerhet krävs kan en egen mapp för containers/image skapas för varje kontainer och kopplas till kontainern via volume-mount. Dessutom kan kontextmappen placeras i själva kontainern, i mappen /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äkerhet. Buildah som arbetar i en sådan kontainer har maximal säkerhet: den får inga root-rättigheter genom capabilities, och alla SECOMP- och SELinux-restriktioner tillämpas. Denna kontainer kan till och med köras med User Namespace-isolering, genom att lägga till en option som —uidmap 0:100000:10000.

Prestanda. Prestandan här är dock minimal, eftersom alla bilder från kontainerregister varje gång kopieras till värden, och caching fungerar inte alls. Efter avslutad process måste Buildah-kontainern skicka bilden till registret och förstöra innehållet på värden. När kontainerbilden byggs nästa gång måste den laddas ner igen från registret, eftersom inget kommer att återstå på värden efter det.

Alternativ 2. Om Docker-nivå prestanda behövs kan container/storage från värden monteras direkt in i kontainern.

# 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äkerhet. Det här är det minst säkra sättet att bygga containrar, eftersom containern här tillåts att modifiera lagringen på värden, och potentiellt kan den införa en skadlig bild till Podman eller CRI-O. Dessutom måste du inaktivera SELinux-separation så att processerna i Buildah-containern kan interagera med lagret på värden. Observera att detta alternativ fortfarande är bättre än Docker-socketen, eftersom containern blockeras av de återstående säkerhetsfunktionerna och inte bara kan ta och starta en vilken container som helst på värden.

Prestanda. Här är den maximal, eftersom caching utnyttjas fullt ut. Om Podman eller CRI-O redan har hämtat den nödvändiga bilden på värden, behöver Buildah-processen inuti containern inte ladda ner den igen, och efterföljande byggen baserade på denna bild kan också ta det som finns i cachen.

Alternativ 3. Essensen av detta sätt är att sammanfoga flera bilder till ett projekt med en gemensam mapp för containerbilder.

# 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

I det här exemplet tar vi inte bort projektmappen (/var/lib/project3) mellan körningar, så alla efterföljande byggen inom projektet drar nytta av cachning.

Säkerhet. Något mitt emellan alternativ 1 och 2. Å ena sidan har inte containrarna tillgång till innehållet på värden, och kan därför inte införa något dåligt i Podman/CRI-O:s bildlager. Å andra sidan kan containern inom sitt projekt blanda sig i bygget av andra containrar.

Prestanda. Här är den sämre än att använda en gemensam cache på värdnivå, eftersom bilder som redan har laddats ner tidigare via Podman/CRI-O inte kan användas. Men efter att Buildah har laddat ner bilden kan den användas i alla efterföljande byggen inom projektet.

Ytterligare lagringsutrymmen

Hos containers/storage Det finns en fantastisk funktion som kallas ytterligare lagringsutrymmen (additional stores), vilket gör att containermotorer kan använda externa bildlagringsutrymmen i skrivskyddat läge vid start och byggande av containrar. I praktiken kan du lägga till ett eller flera "endast för läsning"-lagringsutrymmen i filen storage.conf, så att container-motorn letar efter den nödvändiga bilden när containern startas. Den kommer endast att ladda ner bilden från registret om den inte hittar den i något av dessa lagringsutrymmen. Container-motorn kan endast skriva till skrivbara lagringsutrymmen…

Om vi rullar upp och tittar på Dockerfile som vi använder för att bygga bilden quay.io/buildah/stable, så finns det sådana rader:

# 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

I den första raden modifierar vi /etc/containers/storage.conf inuti containerbilden, och säger till lagringsdrivrutinen att använda "additionalimagestores" i mappen /var/lib/shared. I nästa rad skapar vi en gemensam mapp och lägger till några lås-filer för att undvika konflikter med containers/storage. I grund och botten skapar vi bara ett tomt lagringsutrymme för containerbilder.

Om containers/storage monteras ovanför denna mapp, kan Buildah använda bilder.

Låt oss nu återkomma till det tidigare diskuterade Alternativ 2, där Buildah-containern kan läsa och skriva i containers/store på värdarna och därmed ha maximal prestanda genom att cacha bilder på Podman/CRI-O-nivå, men ger minst säkerhet eftersom den kan skriva direkt i lagringsutrymmena. Nu lägger vi till ytterligare lagringsutrymmen och får det bästa av två världar.

# 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

Notera att /var/lib/containers/storage på värden är monterad i /var/lib/shared inuti containern i skrivskyddat läge. Därför kan Buildah, när den arbetar i containern, använda alla bilder som tidigare har laddats ner av Podman/CRI-O (heja hastighet), men kan bara skriva till sitt eget lagringsutrymme (heja säkerhet). Observera också att detta görs utan att stänga av SELinux-separationen för containern.

En viktig detalj

Du får absolut inte ta bort några bilder från det underliggande lagringsutrymmet. Annars kan Buildah-containern krascha.

Och detta är verkligen inte alla fördelar

Möjligheterna med ytterligare lagringsutrymmen begränsas inte bara till det ovan beskrivna scenariot. Till exempel kan alla containerbilder placeras i ett gemensamt nätverkslagringsutrymme och ges åtkomst till alla Buildah-containrar. Anta att vi har hundratals bilder som vårt CI/CD-system regelbundet använder för att bygga containerbilder. Vi koncentrerar alla dessa bilder på någon form av värdlagring och öppnar sedan, med hjälp av de föredragna nätverkslagringsverktygen (NFS, Gluster, Ceph, ISCSI, S3…), gemensam åtkomst till detta lagringsutrymme för alla Buildah- eller Kubernetes-noder.

Nu räcker det med att montera detta nätverkslagringsutrymme i Buildah-containern på /var/lib/shared och allt – Buildah-containrarna behöver överhuvudtaget inte ladda ner bilder via pull längre. På så sätt eliminerar vi förberedelsefasen (pre-population) och är genast redo att rulla ut containrar.

Och självklart kan detta användas inom ett befintligt Kubernetes-system eller containerinfrastruktur för att köra och utföra containrar var som helst utan att ladda ner bilder via pull. Dessutom kan ett containerregister, som får en push-förfrågan om att ladda upp en uppdaterad bild, automatiskt skicka denna bild till det gemensamma nätverkslagringsutrymmet, där den omedelbart blir tillgänglig för alla noder.

Storleken på containerbilder kan ibland nå flera gigabyte. Funktionaliteten hos ytterligare lagringsutrymmen gör det möjligt att undvika kloning av sådana bilder mellan noder och gör utrullning av containrar praktiskt taget omedelbar.

Dessutom arbetar vi för närvarande med en ny funktion för overlay volume mounts, som kommer att göra byggandet av containrar ännu snabbare.

Slutsats

Att köra Buildah inuti en container i en Kubernetes/CRI-O, Podman eller till och med Docker-miljö är fullt möjligt, dessutom är det enkelt och mycket säkrare än att använda docker.socket. Vi har avsevärt ökat flexibiliteten i arbetet med bilder, och nu kan du köra dem på olika sätt för en optimal balans mellan säkerhet och prestanda.

Funktionaliteten hos ytterligare lagringsutrymmen gör det möjligt att påskynda eller till och med helt eliminera nedladdning av bilder till noder.

Källa: habr.com

Köp pålitlig webbhotell med DDoS-skydd, VPS VDS-servrar 🔥 Köp pålitlig webbhotell med DDoS-skydd, VPS VDS-servrar | ProHoster