Почему Fedora CoreOS — это container optimized дистрибутив
Fedora CoreOS на официальном сайте представлена как container optimized, container-focused, container based и так далее OS. Но что это вообще значит? Там предустановлен какой-то container runtime? А еще что? В этой статье попытаемся разобраться.
Ссылка на статью на хабре – https://habr.com/ru/companies/selectel/articles/817299/
Что такое optimized
Optimized в нашем случае стоит переводить не как «оптимизированная», а скорее как «оптимальная». Так и поступили неизвестные переводчики сайта Fedora Project. Потому что слово «оптимизированный» намекает на производительность, но никакого ее прироста при запуске контейнеров на FCOS (Fedora CoreOS) в сравнении с другими дистрибутивами мы не получим.
Почему вообще OS может называться оптимальной для контейнеров? Надо понимать, что для их запуска потребуется всего две вещи:
- Linux, потому что, будем честны, запускать контейнеризованные приложения на Windows — это не то, чем вы хотите заниматься;
- Платформа для запуска контейнеров, например, docker или podman.
Помимо этого сама система должна быть достаточно защищена и протестирована, чтобы во время нагрузки не всплыли неожиданные сюрпризы.
Fedora CoreOS зачастую используется для запуска Kubernetes кластеров. Собственно, для этого и была разработана. FCOS редко когда используют для того, чтобы запускать единичные контейнеры. Это основная система для OKD, а также апстрим для RHEL CoreOS, которая является дефолтной для OpenShift.
Теперь рассмотрим, какие основные фичи имеет FCOS, и подумаем, как они смогут облегчить нам жизнь в работе с контейнеризованными приложениями.
Иммутабельная система и транзакционные обновления
Начну с самой интересной, на мой взгляд, особенности. FCOS использует систему rpm-ostree. Это своего рода git для вашей операционки. Разберемся подробнее, что это такое.
В основе лежит ostree — система контроля обновлений операционной системы, очень похожая на git. Вот как она работает. У вас есть базовый образ ОС, к примеру, последняя стабильная версия. Вам нужно установить на нее нужное программное обеспечение и сконфигурировать его. Вы это выполняете, тестируете и коммитите изменения. Тем самым вы делаете их резистентными к перезагрузкам системы, так как установленное, но незакомиченное ПО будет слетать после каждого ребута.
Если вас что-то не устроит в изменениях, вы сможете в любой момент откатиться до предыдущих. Более того, вы сможете использовать этот же репозиторий и на других машинах, которые будут стягивать коммиты по мере их появления. Разумеется, с возможностью откатиться до предыдущей версии, если что-то пошло не так. Тем самым можно централизовать управление обновлениями на большом количестве машин.
Обновления в ostree происходят транзакционно: последние два-три образа системы хранятся на диске. Именно за счет этого и можно быстро откатиться на них.
А почему просто не использовать git? Зачем эта git-подобная система? Дело в том, что git отслеживает далеко не все. К примеру, без его внимания остаются метаданные файлов: права, владелец, дата создания и т. д. Для git все это — user specific data, которая ему не нужна.
А теперь вернемся к rpm-ostree. Она дополняет ostree, встраивая пакетный менеджер dnf. По ит огу мы получаем image-based систему с гибкостью package-based системы. Rpm-ostree позволяет наслаивать установленные юзером пакеты на базовый образ. То есть их установка через rpm-ostree создает новый коммит в ostree-дерево. Таким образом, поддерживается так называемый client-side layering. Соответственно, когда у вас появится новая версия базового образа и вы хотите до нее обновиться, вы, можно сказать, делаете git rebase
. :)
Изначально rpm-ostree проектировалась именно для поддержки удобного client-side layering, но сейчас все стало сложнее. Теперь система реализует ряд других полезных функций. Например, во время установки пакетов она изолирует запускаемые скрипты в контейнерах, используя утилиту bubblewrap, чтобы они не влияли на работающую систему. Также поддерживается функционал native containers, который позволяет собирать базовый образ системы через Docker-файлы (подробнее об этом — чуть ниже).
Если ostree считается иммутабельной системой больше из-за ее принципа обновления, то rpm-ostree к этому добавила почти полностью read-only файловую систему. Вносить изменения вы можете только в /etc
или /run
, в которых хранятся конфигурационные файлы, а также в /var
, в котором находятся все остальные данные приложений.
Вот что происходит с файлами внутри этих директорий при обновлении системы:
/run
приводится в первоначальное состояние, не сохраняя пользовательских изменений или добавленных юзером файлов с прошлого запуска. Оно и понятно, эта директория предназначена для добавления конфигурационных файлов, относящихся только к текущему запуску системы;/etc
будет принимать новые изменения от обновлений (если они есть), но в то же время не будет трогать пользовательские изменения;/var
никак не меняется.
Привычные директории типа
/home
— это симлинки на/var/home
.
Автоматические background-обновления
Система rpm-ostree позволяет организовать транзакционные обновления в фоновом режиме. То есть когда появляетс я обновление, система об этом узнает и устанавливает его. После перезапуска будет использован новый образ.
По дефолту FCOS поставляется с запущенным приложением-демоном Zincati. Оно отвечает за автоматические обновления и перезапуски системы. Zincati узнает о доступных апдейтах с помощью удаленного сервера Cincinnati, периодически запрашивая у него информацию. Cincinnati, можно сказать, подписывается на нужный образ системы и по запросу предоставляет граф обновлений. По нему и проходится Zincati (пример: FCOS Updates Graph).
Так как перезапуск системы — действие, которое теоретически может поломать (пусть даже временно) работу всего кластера, Zincati поддерживает несколько стратегий обновления:
- Immediate (default) — перезагружает систему сразу после установки обновления;
- FleetLock — использует стороннее решение, кот орое устанавливает максимальное количество одновременно обновляющихся машин. Машина пошла обновляться — забрала замочек, обновилась — отдала. Если замков нет, она ждет, когда появятся;
- Periodic — позволяет указать конкретные временные окна, в которые система должна перезагружаться. Например, 29 мая в 10 утра.
По информации с форума Fedora Project, команда Fedora планирует упростить этот процесс и убрать из схемы Cincinati. Разработчикам кажется, что сейчас процесс излишне усложнен. Планируется оставить только Zincati, предварительно улучшив его и сделав умнее.
Запуск системы на основе контейнер-образа
Система rpm-ostree наследует часть кода библиотеки ostree-rs-ext, которая реализует функционал ostree native containers. Он позволяет создавать базовый образ системы на основе Docker-файлов.
Примеры:
# Перемещение библиотек, установленных в /opt (симлинк на /var/opt), в /usr
FROM quay.io/fedora/fedora-coreos:testing-devel
RUN mkdir /var/opt && \
rpm -Uvh https://downloads.linux.hpe.com/repo/stk/rhel/7/x86_64/current/hp-scripting-tools-11.60-20.rhel7.x86_64.rpm && \
mv /var/opt/hp/ /usr/lib/hp && \
echo 'L /opt/hp - - - - ../../usr/lib/hp' > /usr/lib/tmpfiles.d/hp.conf && \
ostree container commit
# Установка пакетов
FROM quay.io/fedora/fedora-coreos:stable
RUN rpm-ostree install kubernetes-client && ostree container commit
# Изменение boolean значения SELinux
FROM quay.io/fedora/fedora-coreos:stable
RUN setsebool -P -N container_manage_cgroup 1
Чтобы использовать в системе «сбилженный» и опубликованный базовый образ, достаточно выполнить rebase системы (rpm-ostree rebase ostree-unverified-registry:REGISTRY/IMAGE:VERSION
) и перезапуститься.
Дополнительную информацию по этой теме вы можете найти в документации, а больше примеров — на GitHub.
Безопасность
В целом из статьи понятны некоторые security-фичи, которые вытекают из факта использования rpm-ostree системы. Вот они:
- Иммутабельная файловая система;
- Изоляция скриптов, запускаемых при установке пакетов, в контейнеры;
- Ограниченный и контролируемый список установленных пакетов в базовом образе;
- Автообновления.
Отмечу, что один из фокусов команды Fedora заключается в том, чтобы сделать FCOS сконфигурированной по дефолту со всеми нужными политиками безопасности. Это необходимо для исключения ситуации, когда пользователь на старте может выбрать путь небезопасно настроенной системы.
Именно поэтому FCOS идет с предварительно установленным и настроенным SELinux. Правда, в базовом образе операционки не установлены некоторые дополнительные программы для него типа semanage, так как они зависят от python, которого в FCOS нет (по поводу зависимостей от python есть отдельная дискуссия на GitHub). Из-за этого управлять политиками SELinux может быть затруднительно, но вы все равно можете скомпилировать свои модули и установить их в систему.
Если вам все же нужен semanage, установите его вместе с питоном, используя пакет policycoreutils-python-utils
:
sudo rpm-ostree install policycoreutils-python-utils
...
Added:
checkpolicy-3.5-3.fc39.x86_64
libb2-0.98.1-9.fc39.x86_64
libgomp-13.2.1-7.fc39.x86_64
mpdecimal-2.5.1-7.fc39.x86_64
policycoreutils-python-utils-3.5-8.fc39.noarch
python-pip-wheel-23.2.1-2.fc39.noarch
python-unversioned-command-3.12.3-2.fc39.noarch
python3-3.12.3-2.fc39.x86_64
python3-audit-3.1.2-8.fc39.x86_64
python3-distro-1.8.0-6.fc39.noarch
python3-libs-3.12.3-2.fc39.x86_64
python3-libselinux-3.5-5.fc39.x86_64
python3-libsemanage-3.5-4.fc39.x86_64
python3-policycoreutils-3.5-8.fc39.noarch
python3-setools-4.4.3-1.fc39.x86_64
python3-setuptools-67.7.2-7.fc39.noarch
Так как мы все-таки говорим о container optimized системе, отмечу следующее. Благодаря политикам SELinux в FCOS есть дополнительная изоляция контейнеров от хоста. Ниже приведены примеры на данный момент уже закрытых с помощью SELinux дыр в безопасности runc:
- https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-5736
- https://cve.mitre.org/cgi-bin/cvename.cgi?name=2021-30465
Сама система в целом рассчитана на то, что большая часть юзер-софта будет запускаться в контейнерах. В сочетании с политиками SELinux это дает плюсик к безопасности.
Кстати, часто дыры в этой самой безопасности связаны с неправильным использованием памяти. Это так называемые «memory safety issues». Чтобы уменьшить количество связанных с ними багов, команда Fedora старается все чаще использовать в кодовой базе своих приложений языки Rust и Go.