Wytyczne dotyczące uruchamiania Buildah w kontenerze

Jaki jest urok rozdzielenia środowiska wykonawczego kontenera na osobne komponenty narzędzi? W szczególności narzędzia te można zacząć łączyć, aby wzajemnie się chroniły.

Wytyczne dotyczące uruchamiania Buildah w kontenerze

Wiele osób przyciąga pomysł budowania w nich kontenerowych obrazów OCI Kubernetes lub podobny system. Załóżmy, że mamy CI/CD, który stale gromadzi obrazy, a potem coś w tym stylu Red Hat OpenShift/Kubernetes byłby całkiem przydatny pod względem równoważenia obciążenia podczas kompilacji. Do niedawna większość ludzi po prostu dawała kontenerom dostęp do gniazda Docker i pozwalała im na uruchomienie polecenia budowania dockera. Kilka lat temu pokazaliśmyże jest to bardzo niepewne, w rzeczywistości jest nawet gorsze niż podanie roota bez hasła lub Sudo.

Dlatego ludzie ciągle próbują uruchomić Buildah w kontenerze. Krótko mówiąc, stworzyliśmy przykład jak naszym zdaniem najlepiej uruchomić Buildah w kontenerze i zamieścić odpowiednie obrazy quay.io/buildah. Zacznijmy...

regulacja

Obrazy te są zbudowane z plików Dockerfiles, które można znaleźć w repozytorium Buildah w folderze budujobraz.
Tutaj przyjrzymy się stabilna wersja 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

Zamiast OverlayFS, zaimplementowanego na poziomie jądra Linuksa hosta, używamy programu znajdującego się wewnątrz kontenera nakładka bezpiecznikowa, ponieważ obecnie OverlayFS można zamontować tylko wtedy, gdy nadasz mu uprawnienia SYS_ADMIN przy użyciu możliwości Linuksa. Chcemy także uruchamiać nasze kontenery Buildah bez żadnych uprawnień roota. Nakładka Fuse działa dość szybko i ma lepszą wydajność niż sterownik pamięci masowej VFS. Pamiętaj, że uruchamiając kontener Buildah korzystający z Fuse, musisz podać urządzenie /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

Następnie tworzymy katalog na dodatkową pamięć. Kontener/magazyn obsługuje koncepcję łączenia dodatkowych magazynów obrazów tylko do odczytu. Na przykład możesz skonfigurować obszar przechowywania nakładek na jednym komputerze, a następnie użyć systemu plików NFS do zamontowania tego magazynu na innym komputerze i używać z niego obrazów bez pobierania poprzez ściąganie. Potrzebujemy tej pamięci, aby móc podłączyć część pamięci obrazów z hosta jako wolumin i używać jej w kontenerze.

# 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

Na koniec, używając zmiennej środowiskowej BUILDAH_ISOLATION, nakazujemy kontenerowi Buildah, aby domyślnie działał z izolacją chroot. Dodatkowa izolacja nie jest tutaj wymagana, ponieważ pracujemy już w kontenerze. Aby Buildah mógł tworzyć własne kontenery oddzielone przestrzenią nazw, wymagane jest uprawnienie SYS_ADMIN, co wymagałoby złagodzenia reguł SELinux i SECCOMP kontenera, co jest sprzeczne z naszą preferencją budowania z bezpiecznego kontenera.

Uruchamianie Buildaha w kontenerze

Omówiony powyżej diagram obrazu kontenera Buildah pozwala elastycznie różnicować sposoby uruchamiania takich kontenerów.

Szybkość kontra bezpieczeństwo

Bezpieczeństwo komputera jest zawsze kompromisem pomiędzy szybkością procesu a poziomem ochrony, jaki jest wokół niego owinięty. To stwierdzenie odnosi się również do montażu kontenerów, dlatego poniżej rozważymy opcje takiego kompromisu.

Omówiony powyżej obraz kontenera będzie przechowywany w /var/lib/containers. Dlatego musimy zamontować zawartość w tym folderze, a sposób, w jaki to zrobimy, będzie miał ogromny wpływ na szybkość tworzenia obrazów kontenerów.

Rozważmy trzy opcje.

Opcja 1. Jeśli wymagane jest maksymalne bezpieczeństwo, dla każdego kontenera możesz utworzyć własny folder dla kontenerów/obrazu i podłączyć go do kontenera poprzez montowanie woluminów. Poza tym umieść katalog kontekstowy w samym kontenerze, w folderze /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

Bezpieczeństwa. Buildah działający w takim kontenerze charakteryzuje się maksymalnym bezpieczeństwem: nie ma żadnych uprawnień roota do korzystania z możliwości, a obowiązują go wszystkie ograniczenia SECOMP i SELinux.Taki kontener można nawet uruchomić z izolacją przestrzeni nazw użytkownika, dodając opcję typu —uidmap 0: 100000 10000:XNUMX XNUMX.

Wydajność. Ale wydajność tutaj jest minimalna, ponieważ wszelkie obrazy z rejestrów kontenerów są za każdym razem kopiowane do hosta, a buforowanie w ogóle nie działa. Po zakończeniu swojej pracy kontener Buildah musi wysłać obraz do rejestru i zniszczyć zawartość na hoście. Następnym razem, gdy obraz kontenera zostanie zbudowany, trzeba będzie go ponownie pobrać z rejestru, ponieważ do tego czasu na hoście nie będzie już nic.

Opcja 2. Jeśli potrzebujesz wydajności na poziomie platformy Docker, możesz zamontować kontener/magazyn hosta bezpośrednio w kontenerze.

# 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

Bezpieczeństwa. Jest to najmniej bezpieczny sposób budowania kontenerów, ponieważ pozwala kontenerowi modyfikować pamięć na hoście i może potencjalnie dostarczyć Podmanowi lub CRI-O złośliwy obraz. Ponadto będziesz musiał wyłączyć separację SELinux, aby procesy w kontenerze Buildah mogły wchodzić w interakcję z pamięcią masową na hoście. Należy pamiętać, że ta opcja jest nadal lepsza niż gniazdo Docker, ponieważ kontener jest zablokowany przez pozostałe funkcje zabezpieczeń i nie można po prostu uruchomić kontenera na hoście.

Wydajność. Tutaj jest maksymalna, ponieważ buforowanie jest w pełni wykorzystane. Jeśli Podman lub CRI-O pobrał już wymagany obraz na hosta, to proces Buildah wewnątrz kontenera nie będzie musiał pobierać go ponownie, a kolejne kompilacje oparte na tym obrazie również będą mogły pobrać to, czego potrzebują z pamięci podręcznej .

Opcja 3. Istotą tej metody jest połączenie kilku obrazów w jeden projekt ze wspólnym folderem na obrazy kontenerowe.

# 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

W tym przykładzie nie usuwamy folderu projektu (/var/lib/project3) pomiędzy uruchomieniami, więc wszystkie kolejne kompilacje w ramach projektu korzystają z buforowania.

Bezpieczeństwa. Coś pomiędzy opcjami 1 i 2. Z jednej strony kontenery nie mają dostępu do treści na hoście i w związku z tym nie mogą wrzucić czegoś złego do magazynu obrazów Podman/CRI-O. Z drugiej strony kontener ze względu na swoją konstrukcję może kolidować z montażem innych kontenerów.

Wydajność. Tutaj jest gorzej niż w przypadku korzystania ze współdzielonej pamięci podręcznej na poziomie hosta, ponieważ nie można używać obrazów, które zostały już pobrane za pomocą Podmana/CRI-O. Jednak gdy Buildah pobierze obraz, będzie można go wykorzystać w kolejnych kompilacjach projektu.

Dodatkowe miejsce do przechowywania

У pojemniki/magazyn Jest taka fajna rzecz jak sklepy dodatkowe (dodatkowe sklepy), dzięki którym przy uruchamianiu i budowaniu kontenerów silniki kontenerów mogą korzystać z zewnętrznych magazynów obrazów w trybie nakładki tylko do odczytu. Zasadniczo możesz dodać jeden lub więcej magazynów tylko do odczytu do pliku Storage.conf, tak aby po uruchomieniu kontenera silnik kontenera szukał w nich żądanego obrazu. Co więcej, pobierze obraz z rejestru tylko wtedy, gdy nie znajdzie go w żadnym z tych magazynów. Silnik kontenera będzie mógł zapisywać tylko w zapisywalnej pamięci...

Jeśli przewiniesz w górę i spojrzysz na plik Dockerfile, którego używamy do zbudowania obrazu quay.io/buildah/stable, znajdziesz tam takie linie:

# 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

W pierwszej linii modyfikujemy plik /etc/containers/storage.conf wewnątrz obrazu kontenera, informując sterownik pamięci masowej, aby używał „additionalimagestores” w folderze /var/lib/shared. W następnej linii tworzymy folder współdzielony i dodajemy kilka plików blokujących, aby nie było nadużyć w kontenerach/magazynach. Zasadniczo tworzymy po prostu pusty sklep z obrazami kontenerów.

Jeśli zamontujesz kontenery/magazyn na poziomie wyższym niż ten folder, Buildah będzie mógł wykorzystać obrazy.

Wróćmy teraz do omówionej powyżej Opcji 2, kiedy kontener Buildah może czytać i zapisywać do kontenerów/magazynu na hostach i zgodnie z tym ma maksymalną wydajność dzięki buforowaniu obrazów na poziomie Podman/CRI-O, ale zapewnia minimum bezpieczeństwa ponieważ może zapisywać bezpośrednio do pamięci. Dodajmy teraz tutaj dodatkową pamięć i wykorzystajmy to, co najlepsze z obu światów.

# 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

Należy zauważyć, że plik /var/lib/containers/storage hosta jest podłączony do pliku /var/lib/shared wewnątrz kontenera w trybie tylko do odczytu. Dlatego też, pracując w kontenerze, Buildah może używać dowolnych obrazów, które zostały wcześniej pobrane przy użyciu Podmana/CRI-O (witaj, prędkość), ale może zapisywać tylko do własnej pamięci (witaj, bezpieczeństwo). Należy również pamiętać, że odbywa się to bez wyłączania separacji SELinux dla kontenera.

Ważne niuanse

W żadnym wypadku nie należy usuwać żadnych obrazów z repozytorium bazowego. W przeciwnym razie kontener Buildah może ulec awarii.

A to nie wszystkie zalety

Możliwości dodatkowego przechowywania nie ograniczają się do powyższego scenariusza. Na przykład możesz umieścić wszystkie obrazy kontenerów we współdzielonym magazynie sieciowym i zapewnić dostęp do nich wszystkim kontenerom Buildah. Załóżmy, że mamy setki obrazów, których nasz system CI/CD regularnie używa do tworzenia obrazów kontenerów. Koncentrujemy wszystkie te obrazy na jednym hoście pamięci masowej, a następnie korzystając z preferowanych narzędzi sieciowej pamięci masowej (NFS, Gluster, Ceph, ISCSI, S3...) otwieramy ogólny dostęp do tej pamięci dla wszystkich węzłów Buildah lub Kubernetes.

Teraz wystarczy zamontować tę pamięć sieciową w kontenerze Buildah w katalogu /var/lib/shared i gotowe – kontenery Buildah nie muszą już pobierać obrazów metodą pull. W ten sposób odrzucamy fazę przedpopulacyjną i jesteśmy od razu gotowi do wystawienia kontenerów.

Można to oczywiście wykorzystać w działającym systemie Kubernetes lub infrastrukturze kontenerów do uruchamiania i uruchamiania kontenerów w dowolnym miejscu bez konieczności pobierania obrazów za pomocą funkcji „pull”. Co więcej, rejestr kontenerów, otrzymując żądanie push o przesłanie do niego zaktualizowanego obrazu, może automatycznie wysłać ten obraz do udostępnionego magazynu sieciowego, gdzie natychmiast staje się on dostępny dla wszystkich węzłów.

Obrazy kontenerów mogą czasami osiągać rozmiar wielu gigabajtów. Funkcjonalność dodatkowej pamięci pozwala uniknąć klonowania takich obrazów pomiędzy węzłami i sprawia, że ​​uruchamianie kontenerów jest niemal natychmiastowe.

Ponadto obecnie pracujemy nad nową funkcją zwaną nakładkami na wolumeny, dzięki której budowanie kontenerów będzie jeszcze szybsze.

wniosek

Uruchamianie Buildaha wewnątrz kontenera w Kubernetes/CRI-O, Podman, a nawet Docker jest wykonalne, proste i znacznie bezpieczniejsze niż używanie docker.socket. Znacząco zwiększyliśmy elastyczność pracy z obrazami, dzięki czemu można je uruchamiać na różne sposoby, aby zoptymalizować równowagę między bezpieczeństwem a wydajnością.

Funkcjonalność dodatkowej pamięci pozwala przyspieszyć lub nawet całkowicie wyeliminować pobieranie obrazów do węzłów.

Źródło: www.habr.com

Dodaj komentarz