У чому привабливість поділу середовища виконання контейнерів на окремі інструментальні складові? Зокрема, в тому, що ці інструменти можна почати комбінувати, щоб вони захищали один одного.
Багатьох приваблює ідея виконувати складання контейнерних OCI-образів у рамках
Тому люди постійно намагаються запускати Buildah у контейнері. Коротше, ми створили
Налаштування
Ці образи зібрані з Dockerfiles, які можна знайти в репозиторії Buildah у папці
Тут ми розглянемо
# 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
Замість OverlayFS, реалізованої на рівні Linux-ядра хоста, ми використовуємо всередині контейнера програму
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
Далі ми створюємо каталог додаткових сховищ.
# 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
І, нарешті, використовуючи змінну оточення BUILDAH_ISOLATION, ми говоримо, що за замовчуванням Buildah-контейнер повинен запускатися з ізоляцією chroot. Додаткова ізоляція тут не потрібна, оскільки ми вже працюємо в контейнері. Для того, щоб Buildah створював власні контейнери з поділом просторів імен, потрібен привілей SYS_ADMIN, а для цього доведеться послабити для контейнера правила SELinux і SECCOMP, що суперечить нашій установці виконувати збірку з безпечного контейнера.
Запускаємо Buildah усередині контейнера
Розглянута вище схема Buildah-контейнера дозволяє гнучко варіювати способи запуску таких контейнерів.
Швидкість проти безпеки
Комп'ютерна безпека - це компроміс між швидкістю виконання процесу і тим, скільки захисту навколо цього накручено. Це твердження є справедливим і при складанні контейнерів, тому нижче ми розглянемо варіанти такого компромісу.
Розглянутий вище контейнерний образ триматиме своє сховище в /var/lib/containers. Тому нам потрібно підмонтувати контент у цю папку, і те, як ми це зробимо, сильно впливатиме на швидкість складання контейнерних образів.
Розглянемо три варіанти.
Варіант 1. Якщо потрібна максимальна безпека, для кожного контейнера можна створювати свою папку для containers/image і підключати її до контейнера через volume-mount. Крім того, розміщувати context directory у самому контейнері, в папці /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
Безпека. Buildah, що працює в такому контейнері, має максимальну безпеку: йому не дають ніяких root-привілеїв засобами capabilities, і до нього застосовуються всі обмеження SECOMP і SELinux.
Продуктивність. А ось продуктивність тут мінімальна, оскільки будь-які образи із контейнерних реєстрів щоразу копіюються на хост, і кешування не працює від слова «ніяк». Завершуючи свою роботу, Buildah-контейнер повинен відправляти образ до реєстру та знищувати контент на хості. Коли контейнерний образ буде збиратися наступного разу, його доведеться знову завантажувати з реєстру, оскільки на хості на той момент уже нічого не залишиться.
Варіант 2. Якщо потрібна продуктивність рівня Docker, можна підмонтувати container/storage хоста прямо в контейнер.
# 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
Безпека. Це найменш безпечний спосіб збирання контейнерів, оскільки тут контейнеру дозволено модифікувати сховище на хості, і потенційно він може підсунути Podman'у або CRI-O шкідливий образ. Крім того, потрібно відключити SELinux separation, щоб процеси, що знаходяться в Buildah-контейнері, могли взаємодіяти зі сховищем на хості. Зверніть увагу, що цей варіант все одно краще Docker-сокету, оскільки контейнер блокується функціями безпеки, що залишилися, і не може просто взяти і запустити який-небудь контейнер на хості.
Продуктивність. Тут вона максимальна, оскільки повністю задіюється кешування. Якщо Podman або CRI-O вже встигли завантажити потрібний образ на хост, то Buildah-процесу всередині контейнера не доведеться завантажувати його заново, а наступні зборки на основі цього образу також зможуть взяти потрібне з кешу.
Варіант 3. Суть цього способу полягає в тому, щоб об'єднати кілька образів в один проект із спільною папкою для контейнерних образів.
# 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
У цьому прикладі ми не видаляємо папку проекту (/var/lib/project3) між запусками, тому всі наступні зборки в рамках проекту мають переваги кешування.
Безпека. Щось середнє між варіантами 1 та 2. З одного боку, контейнери не мають доступу до контенту на хості і, відповідно, не можуть підсунути щось погане у сховищі образів Podman/CRI-O. З іншого боку, у межах свого проекту контейнер може втручатися у збирання інших контейнерів.
Продуктивність. Тут вона гірша, ніж при використанні загального кешу на рівні хоста, оскільки не можна використовувати образи, вже раніше завантажені засобами Podman/CRI-O. Однак після того, як Buildah скачає образ, цей образ можна використовувати у будь-яких подальших збірках у рамках проекту.
Додаткові сховища
У
Якщо прокрутити вгору і подивитися Dockerfile, який ми використовуємо для складання образу quay.io/buildah/stable, там є такі рядки:
# 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
У першому рядку ми модифікуємо /etc/containers/storage.conf усередині контейнерного образу, говорячи storage-драйверу використовувати “additionalimagestores” у папці /var/lib/shared. А в наступному рядку створюємо спільну папку і додаємо пару lock-файлів, щоб не було лайки з боку containers/storage. По суті ми просто створюємо порожнє сховище контейнерних образів.
Якщо змонтувати containers/storage рівнем вище цієї папки, Buildah зможе використовувати образи.
Тепер повернемося до розглянутого вище Варіанту 2, коли Buildah-контейнер може читати та писати в containers/store на хостах і, відповідно, має максимальну продуктивність за рахунок кешування образів на рівні Podman/CRI-O, але дає мінімум безпеки, оскільки може писати прямо у сховища. А тепер прикрутимо сюди додаткові сховища та отримаємо найкраще із двох світів.
# 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
Зверніть увагу, що /var/lib/containers/storage хоста змонтована в /var/lib/shared всередині контейнера в режимі read-only. Тому працюючи в контейнері, Buildah може використовувати будь-які образи, які раніше вже були завантажені засобами Podman/CRI-O (привіт, швидкість), але писати при цьому може лише у власне сховище (привіт, безпека). Також зверніть увагу, що це робиться без вимкнення SELinux separation для контейнера.
важливий нюанс
У жодному разі не слід видаляти жодні образи з сховища, що лежить нижче. В іншому випадку Buildah-контейнер може вилетіти.
І це аж ніяк не всі переваги
Можливості додаткових сховищ не обмежуються лише вищеописаним сценарієм. Наприклад, можна розмістити всі контейнерні образи у спільному мережевому сховищі і дати доступ до нього всім Buildah-контейнерам. Допустимо, у нас є сотні образів, які наша система CI/CD регулярно використовує для збирання контейнерних образів. Концентруємо всі ці образи на якомусь одному хосте-сховищі і потім, використовуючи переважні засоби мережевого зберігання (NFS, Gluster, Ceph, ISCSI, S3…), відкриваємо загальний доступ до цього сховища всім нодам Buildah або Kubernetes.
Тепер достатньо підмонтувати це сховище в контейнер Buildah на /var/lib/shared і все - Buildah-контейнерам більше взагалі не доведеться завантажувати образи через pull. Таким чином, ми викидаємо фазу попереднього наповнення (pre-population) і відразу готові викочувати контейнери.
І звичайно ж, це можна використовувати в рамках діючої системи Kubernetes або контейнерної інфраструктури, щоб запускати і виконувати контейнери будь-де без будь-якого завантаження образів через pull. Більше того, реєстр контейнерів, отримуючи push-запит на завантаження в нього оновленого образу, може автоматично відправляти цей образ у загальне мережеве сховище, де він миттєво стає доступним для всіх нодів.
Розміри контейнерних образів іноді можуть досягати багатьох гігабайт. Функціонал додаткових сховищ дозволяє обійтися без клонування таких образів за нодами і робить запуск контейнерів практично миттєвим.
Крім того, зараз ми працюємо над новою функцією overlay volume mounts, яка зробить складання контейнерів ще швидше.
Висновок
Виконувати Buildah усередині контейнера в середовищі Kubernetes/CRI-O, Podman або навіть у Docker цілком реально, до того ж це просто і набагато безпечніше, ніж використовувати docker.socket. Ми значно підвищили гнучкість роботи з образами, і тепер ви можете запускати їх у різний спосіб для оптимального балансу між безпекою та продуктивністю.
Функціонал додаткових сховищ дозволяє прискорити або навіть повністю усунути завантаження образів на ноди.
Джерело: habr.com