Jaka jest zaleta podziału środowiska uruchomieniowego kontenerów na oddzielne elementy narzędziowe? Przede wszystkim polega on na tym, że te narzędzia można rozpocząć łączyć, aby mogły się wzajemnie chronić.

Wielu osób przyciąga pomysł kompilacji kontenerowych obrazów OCI w ramach lub podobnego systemu. Załóżmy, że mamy CI/CD, które nieprzerwanie kompiluje obrazy, wówczas coś takiego jak /Kubernetes было бы весьма полезно с точки зрения распределения нагрузки при сборке. До недавних пор большинство людей просто давали контейнерам доступ к Docker-сокету и разрешали выполнять команду docker build. , że jest to bardzo niebezpieczne, w rzeczywistości nawet gorsze niż udostępnienie hasła do roota czy sudo.
Dlatego ludzie ciągle próbują uruchamiać Buildah w kontenerze. Krótko mówiąc, stworzyliśmy naszym zdaniem najlepszy sposób uruchamiania Buildah wewnątrz kontenera i udostępniliśmy odpowiednie obrazy na . Zaczynajmy…
Konfiguracja
Te obrazy są zbudowane na podstawie Dockerfile, które można znaleźć w repozytorium Buildah w folderze .
Tutaj przyjrzymy się .
# 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, który jest wdrażany na poziomie jądra Linuxa gospodarza, używamy wewnątrz kontenera programu , ponieważ aktualnie OverlayFS może montować, tylko jeśli otrzyma uprawnienia SYS_ADMIN za pomocą możliwości Linux. A my chcemy uruchamiać nasze kontenery Buildah bez jakichkolwiek uprawnień roota. Fuse-overlay działa dość szybko i pod względem wydajności jest lepsze niż sterownik storage VFS. Należy pamiętać, że uruchamiając kontener Buildah, który używa Fuse, trzeba udostępnić 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 dla dodatkowych magazynów. wspiera koncepcję podłączania dodatkowych read-only magazynów obrazów. Na przykład można skonfigurować obszar magazynowania overlay na jednej maszynie, a następnie podmontować ten magazyn na innej maszynie za pomocą NFS i używać obrazów z niego bez pobierania przez pull. Potrzebujemy tego magazynu, aby mieć możliwość podłączenia jako wolumenu jakiegoś magazynu obrazów z gospodarza i używania go wewnątrz kontenera.
# 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, mówimy, że domyślnie kontener Buildah powinien być uruchamiany w izolacji chroot. Dodatkowa izolacja nie jest tutaj wymagana, ponieważ pracujemy już w kontenerze. Aby Buildah mógł tworzyć własne kontenery z podziałem przestrzeni nazw, wymagana jest zgoda SYS_ADMIN, co oznacza, że będziemy musieli złagodzić zasady SELinux i SECCOMP dla kontenera, co jest sprzeczne z naszym podejściem do budowy z bezpiecznego kontenera.
Uruchamiamy Buildah wewnątrz kontenera
Rozważony powyżej schemat obrazu kontenera Buildah pozwala elastycznie dostosować sposoby uruchamiania takich kontenerów.
Szybkość kontra bezpieczeństwo
Bezpieczeństwo komputerowe to zawsze kompromis między szybkością realizacji a ilością ochrony wokół. To stwierdzenie jest prawdziwe również podczas budowy kontenerów, dlatego poniżej rozważymy opcje takiego kompromisu.
Rozważony powyżej obraz kontenera będzie przechowywał swoje magazyny w /var/lib/containers. Dlatego musimy zamontować zawartość w tym folderze, a to, jak to zrobimy, ma znaczący wpływ na szybkość budowy obrazów kontenerowych.
Rozważmy trzy opcje.
Opcja 1. Jeśli wymagana jest maksymalna ochrona, dla każdego kontenera można stworzyć osobny folder dla containers/image i podłączyć go do kontenera przez volume-mount. Dodatkowo, umieszczony kontekst katalogu 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ństwo. Buildah działający w takim kontenerze ma maksymalne bezpieczeństwo: nie otrzymuje żadnych przywilejów root za pomocą capabilities, i stosowane są wszystkie ograniczenia SECOMP i SELinux. Taki kontener można nawet uruchomić w izolacji User Namespace, dodając opcję taką jak —uidmap 0:100000:10000.
Wydajność. Wydajność jest jednak minimalna, ponieważ wszelkie obrazy z rejestrów kontenerów są za każdym razem kopiowane na hosta, a pamięć podręczna nie działa w ogóle. Kończąc swoją pracę, kontener Buildah powinien wysłać obraz do rejestru i usunąć zawartość na hoście. Kiedy obraz kontenera będzie budowany następnym razem, będzie musiał być pobierany ponownie z rejestru, ponieważ na hoście w tym czasie nie zostanie nic.
Wariant 2. Jeśli potrzebna jest wydajność na poziomie Dockera, można podłączyć container/storage hosta bezpośrednio do kontenera.
# 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ństwo. To najbezpieczniejszy sposób budowania kontenerów, ponieważ kontener ma możliwość modyfikacji zasobów na hoście i potencjalnie może wprowadzić złośliwy obraz do Podmana lub CRI-O. Ponadto konieczne będzie wyłączenie separacji SELinux, aby procesy w kontenerze Buildah mogły komunikować się z zasobami na hoście. Należy pamiętać, że ta opcja wciąż jest lepsza od gniazda Dockera, ponieważ kontener jest chroniony przez pozostałe funkcje bezpieczeństwa i nie może po prostu wziąć i uruchomić jakiegokolwiek kontenera na hoście.
Wydajność. Tutaj jest to maksymalne, ponieważ całkowicie wykorzystuje pamięć podręczną. Jeśli Podman lub CRI-O zdążyły już pobrać potrzebny obraz na hosta, proces Buildah wewnątrz kontenera nie będzie musiał pobierać go ponownie, a następne budowy na podstawie tego obrazu również będą mogły skorzystać z pamięci podręcznej.
Opcja 3. Istotą tego sposobu jest połączenie kilku obrazów w jeden projekt z wspólnym folderem dla kontenerowych obrazów.
# 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) między uruchomieniami, dlatego wszystkie następne budowy w ramach projektu korzystają z zalet pamięci podręcznej.
Bezpieczeństwo. Coś pomiędzy opcjami 1 i 2. Z jednej strony, kontenery nie mają dostępu do zawartości na hoście i nie mogą w związku z tym wprowadzić nic złego do magazynu obrazów Podmana/CRI-O. Z drugiej strony, w ramach swojego projektu kontener może ingerować w budowę innych kontenerów.
Wydajność. Tutaj jest to gorsze niż w przypadku użycia wspólnej pamięci podręcznej na poziomie hosta, ponieważ nie można korzystać z obrazów, które już wcześniej pobrano za pomocą Podmana/CRI-O. Jednak po tym, jak Buildah pobierze obraz, może on być użyty w dowolnych kolejnych budowach w ramach projektu.
Dodatkowe magazyny
U Istnieje coś takiego jak dodatkowe magazyny (additional stores), dzięki którym przy uruchamianiu i budowaniu kontenerów, silniki kontenerowe mogą używać zewnętrznych magazynów obrazów w trybie read-only overlay. W zasadzie, do pliku storage.conf można dodać jedno lub więcej magazynów „tylko do odczytu”, aby podczas uruchamiania kontenera silnik kontenerowy szukał w nich potrzebnego obrazu. Oczywiście pobierze obraz z rejestru tylko w przypadku, gdy nie znajdzie go w żadnym z tych magazynów. Silnik kontenerowy będzie mógł pisać tylko w dostępnych do zapisu magazynach…
Jeśli przewiniesz w górę i spojrzysz na Dockerfile, który używamy do budowania obrazu quay.io/buildah/stable, to 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 /etc/containers/storage.conf wewnątrz obrazu kontenera, informując sterownik storage, aby używał ‘additionalimagestores’ w folderze /var/lib/shared. A w następnej linii tworzymy wspólny folder i dodajemy parę plików blokad, aby uniknąć konfliktów ze strony containers/storage. W istocie, po prostu tworzymy pusty magazyn obrazów kontenerów.
Jeśli zamontować containers/storage wyżej w hierarchii tego folderu, Buildah będzie mogło używać obrazów.
Teraz wróćmy do rozważanego powyżej wariantu 2, gdy kontener Buildah może czytać i pisać w containers/store na hostach i, w konsekwencji, ma maksymalną wydajność dzięki buforowaniu obrazów na poziomie Podman/CRI-O, ale daje minimalne bezpieczeństwo, ponieważ może pisać bezpośrednio do magazynów. A teraz dodajmy do tego dodatkowe magazyny i uzyskamy to, co najlepsze z dwóch ś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
Zauważ, że /var/lib/containers/storage hosta jest zamontowane w /var/lib/shared wewnątrz kontenera w trybie read-only. Dlatego pracując w kontenerze, Buildah może używać wszelkich obrazów, które wcześniej zostały pobrane za pomocą Podman/CRI-O (cześć, szybkość), ale może pisać tylko w swoim własnym magazynie (cześć, bezpieczeństwo). Zauważ również, że odbywa się to bez wyłączania separacji SELinux dla kontenera.
Ważny szczegół
W żadnym wypadku nie należy usuwać żadnych obrazów z niższego magazynu. W przeciwnym razie kontener Buildah może się wywalić.
I to wcale nie wszystkie zalety
Możliwości dodatkowych magazynów nie ograniczają się tylko do opisanego powyżej scenariusza. Na przykład, można umieścić wszystkie obrazy kontenerów w wspólnym magazynie sieciowym i udostępnić go wszystkim kontenerom Buildah. Załóżmy, że mamy setki obrazów, które nasz system CI/CD regularnie wykorzystuje do budowy obrazów kontenerów. Koncentrujemy wszystkie te obrazy na jednym hoście-magazynie, a następnie, wykorzystując preferowane środki przechowywania w sieci (NFS, Gluster, Ceph, ISCSI, S3…), otwieramy wspólny dostęp do tego magazynu dla wszystkich węzłów Buildah lub Kubernetes.
Teraz wystarczy podmontować to sieciowe magazyn w kontenerze Buildah w /var/lib/shared i wszystko – kontenery Buildah nie będą musiały już w ogóle pobierać obrazów przez pull. W ten sposób eliminujemy etap wstępnego wypełniania (pre-population) i od razu jesteśmy gotowi do wdrożenia kontenerów.
Oczywiście, można to wykorzystać w ramach działającego systemu Kubernetes lub infrastruktury kontenerowej, aby uruchamiać i wykonywać kontenery wszędzie bez żadnego pobierania obrazów przez pull. Co więcej, rejestr kontenerów, otrzymując zapytanie push o załadowanie zaktualizowanego obrazu, może automatycznie wysyłać ten obraz do wspólnego magazynu sieciowego, gdzie natychmiast staje się dostępny dla wszystkich węzłów.
Rozmiary obrazów kontenerów czasami mogą osiągać wiele gigabajtów. Funkcjonalność dodatkowych magazynów pozwala uniknąć klonowania takich obrazów na węzły i praktycznie przyspiesza uruchamianie kontenerów.
Ponadto w tej chwili pracujemy nad nową funkcją montowania wolumenów overlay, która uczyni budowę kontenerów jeszcze szybszą.
Podsumowanie
Wykonywanie Buildah wewnątrz kontenera w środowisku Kubernetes/CRI-O, Podman lub nawet w Dockerze jest całkowicie możliwe, a ponadto jest to proste i znacznie bezpieczniejsze niż użycie docker.socket. Znacznie zwiększyliśmy elastyczność pracy z obrazami, więc teraz można je uruchamiać na różne sposoby dla optymalnej równowagi między bezpieczeństwem a wydajnością.
Funkcjonalność dodatkowych magazynów pozwala przyspieszyć lub nawet całkowicie wyeliminować pobieranie obrazów na węzły.
Źródło: habr.com
