Instrucțiuni pentru rularea Buildah în interiorul unui container

Care este frumusețea decuplării duratei de rulare a containerului în componente separate de scule? În special, aceste instrumente pot începe să fie combinate astfel încât să se protejeze reciproc.

Instrucțiuni pentru rularea Buildah în interiorul unui container

Mulți oameni sunt atrași de ideea de a construi imagini OCI containerizate în interior Kubernetes sau sistem similar. Să presupunem că avem un CI/CD care colectează în mod constant imagini, apoi ceva de genul Red Hat OpenShift/Kubernetes ar fi destul de util în ceea ce privește echilibrarea sarcinii în timpul build-urilor. Până de curând, majoritatea oamenilor le-au permis pur și simplu containerelor acces la un socket Docker și le-au permis să ruleze comanda docker build. Acum câțiva ani am arătatcă acest lucru este foarte nesigur, de fapt, este chiar mai rău decât a da root fără parolă sau sudo.

De aceea oamenii încearcă în mod constant să ruleze Buildah într-un container. Pe scurt, noi am creat exemplu cum, în opinia noastră, este cel mai bine să rulați Buildah într-un container și să postați imaginile corespunzătoare pe chei.io/buildah. Să începem...

ajustare

Aceste imagini sunt construite din Dockerfiles, care pot fi găsite în depozitul Buildah din folder buildahimage.
Aici vom lua în considerare versiune stabilă a 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

În loc de OverlayFS, implementat la nivel de kernel Linux gazdă, folosim programul din interiorul containerului suprapunere fuzibilă, deoarece în prezent OverlayFS se poate monta numai dacă îi acordați permisiuni SYS_ADMIN folosind capabilitățile Linux. Și vrem să rulăm containerele noastre Buildah fără privilegii de root. Fuse-overlay funcționează destul de repede și are performanțe mai bune decât driverul de stocare VFS. Vă rugăm să rețineți că atunci când rulați un container Buildah care utilizează Fuse, trebuie să furnizați dispozitivul /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

Apoi creăm un director pentru stocare suplimentară. Container/depozitare acceptă conceptul de conectare a unor magazine suplimentare de imagini numai pentru citire. De exemplu, puteți configura o zonă de stocare suprapusă pe o mașină și apoi să utilizați NFS pentru a monta acest spațiu de stocare pe o altă mașină și să utilizați imagini de pe acesta fără a descărca prin pull. Avem nevoie de acest spațiu de stocare pentru a putea conecta un spațiu de stocare de imagini de la gazdă ca volum și să îl folosim în interiorul containerului.

# 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

În cele din urmă, folosind variabila de mediu BUILDAH_ISOLATION, îi spunem containerului Buildah să ruleze implicit cu izolarea chroot. Izolarea suplimentară nu este necesară aici, deoarece lucrăm deja într-un container. Pentru ca Buildah să-și creeze propriile containere separate de spații de nume, este necesar privilegiul SYS_ADMIN, ceea ce ar necesita relaxarea regulilor SELinux și SECCOMP ale containerului, ceea ce este contrar preferinței noastre de a construi dintr-un container securizat.

Rularea Buildah într-un container

Diagrama imaginii containerului Buildah discutată mai sus vă permite să variați în mod flexibil metodele de lansare a unor astfel de containere.

Viteză versus siguranță

Securitatea computerului este întotdeauna un compromis între viteza procesului și cât de multă protecție este cuprinsă în jurul acestuia. Această afirmație este valabilă și la asamblarea containerelor, așa că mai jos vom lua în considerare opțiunile pentru un astfel de compromis.

Imaginea containerului discutată mai sus își va păstra stocarea în /var/lib/containers. Prin urmare, trebuie să instalăm conținutul în acest folder și modul în care facem acest lucru va afecta foarte mult viteza de construire a imaginilor containerului.

Să luăm în considerare trei opțiuni.

Opțiunea 1. Dacă este necesară securitatea maximă, atunci pentru fiecare container puteți crea propriul folder pentru containere/imagine și îl puteți conecta la container prin volum-mount. Și în plus, plasați directorul de context în containerul propriu-zis, în folderul /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

Securitate. Buildah care rulează într-un astfel de container are securitate maximă: nu i se acordă niciun privilegiu de rădăcină folosind capabilități și i se aplică toate restricțiile SECOMP și SELinux. Un astfel de container poate fi rulat chiar și cu izolarea spațiului de nume de utilizator prin adăugarea unei opțiuni precum —uidmap 0: 100000:10000.

Performanță. Dar performanța aici este minimă, deoarece orice imagini din registrele de containere sunt copiate pe gazdă de fiecare dată, iar stocarea în cache nu funcționează deloc. Când își finalizează activitatea, containerul Buildah trebuie să trimită imaginea la registru și să distrugă conținutul de pe gazdă. Data viitoare când imaginea containerului este construită, va trebui să fie descărcată din nou din registru, deoarece până atunci nu va mai rămâne nimic pe gazdă.

Opțiunea 2. Dacă aveți nevoie de performanță la nivel Docker, puteți monta containerul/stocarea gazdă direct în container.

# 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

Securitate. Acesta este cel mai puțin sigur mod de a construi containere, deoarece permite containerului să modifice spațiul de stocare de pe gazdă și ar putea alimenta Podman sau CRI-O cu o imagine rău intenționată. În plus, va trebui să dezactivați separarea SELinux, astfel încât procesele din containerul Buildah să poată interacționa cu stocarea de pe gazdă. Rețineți că această opțiune este încă mai bună decât un socket Docker, deoarece containerul este blocat de caracteristicile de securitate rămase și nu poate rula pur și simplu un container pe gazdă.

Performanță. Aici este maxim, deoarece stocarea în cache este utilizată pe deplin. Dacă Podman sau CRI-O au descărcat deja imaginea necesară pe gazdă, atunci procesul Buildah din interiorul containerului nu va trebui să o descarce din nou, iar versiunile ulterioare bazate pe această imagine vor putea, de asemenea, să ia ceea ce au nevoie din cache. .

Opțiunea 3. Esența acestei metode este de a combina mai multe imagini într-un singur proiect cu un folder comun pentru imaginile containerului.

# 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

În acest exemplu, nu ștergem folderul proiectului (/var/lib/project3) între rulări, astfel încât toate versiunile ulterioare din cadrul proiectului beneficiază de cache.

Securitate. Ceva între opțiunile 1 și 2. Pe de o parte, containerele nu au acces la conținut de pe gazdă și, în consecință, nu pot strecura ceva rău în stocarea de imagini Podman/CRI-O. Pe de altă parte, ca parte a designului său, un container poate interfera cu asamblarea altor containere.

Performanță. Aici este mai rău decât atunci când utilizați un cache partajat la nivel de gazdă, deoarece nu puteți utiliza imagini care au fost deja descărcate folosind Podman/CRI-O. Cu toate acestea, odată ce Buildah descarcă imaginea, aceasta poate fi folosită în orice versiuni ulterioare din cadrul proiectului.

Depozitare suplimentară

У containere/depozitare Există un lucru atât de grozav ca magazinele suplimentare (magazine suplimentare), datorită cărora atunci când lansează și construiesc containere, motoarele de containere pot folosi magazine de imagini externe în modul de suprapunere doar pentru citire. În esență, puteți adăuga una sau mai multe stocări numai pentru citire în fișierul storage.conf, astfel încât atunci când porniți containerul, motorul containerului să caute imaginea dorită în ele. Mai mult, va descărca imaginea din registru doar dacă nu o găsește în niciuna dintre aceste stocări. Motorul containerului va putea scrie doar în spațiul de stocare care poate fi scris...

Dacă derulați în sus și vă uitați la Dockerfile pe care îl folosim pentru a construi imaginea quay.io/buildah/stable, există rânduri ca aceasta:

# 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

În prima linie, modificăm /etc/containers/storage.conf în interiorul imaginii containerului, spunând driverului de stocare să folosească „additionalimagestores” în folderul /var/lib/shared. Și în următoarea linie creăm un folder partajat și adăugăm câteva fișiere de blocare, astfel încât să nu existe abuz din containere/stocare. În esență, pur și simplu creăm un magazin de imagini de container gol.

Dacă montați containere/depozitare la un nivel mai mare decât acest folder, Buildah va putea folosi imaginile.

Acum să revenim la Opțiunea 2 discutată mai sus, când containerul Buildah poate citi și scrie în containere/magazin de pe gazde și, în consecință, are performanță maximă datorită stocării în cache a imaginilor la nivel Podman/CRI-O, dar oferă un minim de securitate deoarece poate scrie direct în stocare. Acum să adăugăm spațiu de stocare suplimentar aici și să obținem tot ce este mai bun din ambele lumi.

# 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

Rețineți că /var/lib/containers/storage al gazdei este montat în /var/lib/shared în interiorul containerului în modul doar citire. Prin urmare, lucrând într-un container, Buildah poate folosi orice imagini care au fost descărcate anterior folosind Podman/CRI-O (bună ziua, viteză), dar poate scrie doar în propria sa stocare (bună ziua, securitate). De asemenea, rețineți că acest lucru se face fără a dezactiva separarea SELinux pentru container.

Nuanțe importante

În niciun caz nu trebuie să ștergeți nicio imagine din depozitul de bază. În caz contrar, containerul Buildah se poate prăbuși.

Și acestea nu sunt toate avantajele

Posibilitățile de stocare suplimentară nu se limitează la scenariul de mai sus. De exemplu, puteți plasa toate imaginile containerelor într-o rețea de stocare partajată și puteți oferi acces la aceasta tuturor containerelor Buildah. Să presupunem că avem sute de imagini pe care sistemul nostru CI/CD le folosește în mod regulat pentru a construi imagini container. Concentrăm toate aceste imagini pe o singură gazdă de stocare și apoi, folosind instrumentele preferate de stocare în rețea (NFS, Gluster, Ceph, ISCSI, S3...), deschidem accesul general la această stocare pentru toate nodurile Buildah sau Kubernetes.

Acum este suficient să montați acest spațiu de stocare în rețea în containerul Buildah pe /var/lib/shared și gata - containerele Buildah nu mai trebuie să descarce imagini prin pull. Astfel, aruncăm faza de prepopulare și suntem imediat gata să lansăm containerele.

Și, desigur, aceasta poate fi folosită într-un sistem Kubernetes live sau într-o infrastructură de containere pentru a lansa și rula containere oriunde, fără nicio descărcare prin pull de imagini. Mai mult, registrul containerului, primind o solicitare push pentru a încărca o imagine actualizată în el, poate trimite automat această imagine către o stocare partajată în rețea, unde devine instantaneu disponibilă pentru toate nodurile.

Imaginile containerului pot ajunge uneori la mulți gigaocteți. Funcționalitatea stocării suplimentare vă permite să evitați clonarea unor astfel de imagini peste noduri și face ca lansarea containerelor să fie aproape instantanee.

În plus, lucrăm în prezent la o nouă caracteristică numită suporturi de volum suprapuse, care va face construirea containerelor și mai rapidă.

Concluzie

Rularea Buildah în interiorul unui container în Kubernetes/CRI-O, Podman sau chiar Docker este fezabilă, simplă și mult mai sigură decât utilizarea docker.socket. Am crescut foarte mult flexibilitatea lucrului cu imagini, astfel încât să le puteți rula într-o varietate de moduri pentru a optimiza echilibrul dintre securitate și performanță.

Funcționalitatea stocării suplimentare vă permite să accelerați sau chiar să eliminați complet descărcarea imaginilor în noduri.

Sursa: www.habr.com

Adauga un comentariu