[Перевод] Обзор одноцелевых дистрибутивов Linux
Многие из тех, кто устанавливает дистрибутив Linux для одной-единственной цели, например, для работы с контейнерами, предпочитают развёртывание по принципу «поставил и забыл». На конференции FOSDEM 2023, состоявшейся в Брюсселе, было представлено несколько проектов из разряда таких «минимальных дистрибутивов Linux». Все они — Fedora CoreOS, Ubuntu Core, openSUSE MicroOS и Bottlerocket OS — решают такие задачи по-своему. Из выступлений на FOSDEM можно составить интересную перспективу, демонстрирующую, в чём эти проекты отличаются на уровне применяемых подходов.
❯ Fedora CoreOS
Акашдип Дхар и Сумантро Мукерджи оба входят в совет по разработке Fedora и работают программистами в Red Hat. Они объяснили, как применить Fedora CoreOS в качестве базовой операционной системы, позволяющей гонять в контейнерах серверы для многопользовательских игр. Как сказано в документации по этому дистрибутиву, Fedora CoreOS — это «автоматически обновляемая, минимальная, монолитная операционная система, в которой сделан акцент на работе с контейнерами».
Fedora CoreOS (иногда сокращённо именуемая FCOS) служит операционной хост-системой для этих контейнеров. Она содержит лишь те пакеты, которые нужны для создания минимальной конфигурации с поддержкой сетевых взаимодействий и готовой для работы с контейнерами. На момент написания оригинала этой статьи в новейшем стабильном релизе было 415 пакетов. В нём поддерживаются архитектуры x86_64, aarch64 (в том числе, для Raspberry Pi 4), а также s390x. Дистрибутив работает на голом железе, на виртуальной машине, либо на различных облачных платформах.
Машина для Fedora CoreOS предоставляется при помощи Ignition: это инструмент, при помощи которого можно сегментировать диски, форматировать разделы, включать блоки systemd и конфигурировать пользовательские учётные записи. Сам Ignition выполняется только при первой загрузке системы, стартует с initramfs. Конфигурационный файл Ignition сделан в формате JSON, но для конечных пользователей Fedora CoreOS рекомендуется конфигурация Butane. Это файл в формате YAML, который Butane преобразует в конфигурацию Ignition. В разделе «System Configuration» документации Fedora CoreOS на нескольких примерах объяснено, как сконфигурировать в Butane хранилище данных, сеть, контейнеры, пользователей и группы, часовые пояса, а также многое другое. Дхар и Мукерджи в своей лекции показали конфигурацию Butane, позволяющую настроить сервер Minecraft в контейнере. Эту информацию они также опубликовали в своём репозитории на GitHub.
Устанавливая Fedora CoreOS, вы выбираете один из трёх имеющихся потоков обновлений. Работая с «next», удобно экспериментировать с новыми возможностями, режим «testing» показывает, что будет в следующем стабильном потоке, а «stable» — это поток, в который подтянуты изменения, уже некоторое время пробывшие в режиме «testing». Большинству пользователей подойдёт стабильный поток (stable). Все пользовательские настройки вносите, сверяясь с файлом Ignition, держа в уме выбранный вами тип установки. Например, при установке из PXE к ядру прикрепляется опция coreos.inst.ignition_url=URL
, указывающая, где именно на веб-сервере расположен файл Ignition.
После установки система будет автоматически обновляться всякий раз, когда в выбранный вами поток выкатывается новый релиз. Агент Zincati проверяет, есть ли обновления операционной системы, и применяет их при помощи rpm-ostree. Zincati также можно сконфигурировать; например, указать, насколько «срочно» нужно обновляться (то есть, на насколько раннем этапе в фазированном цикле выкатывания обновлений их получать). Также можно указать, насколько оперативно перезагружаться после того, как обновление будет применено — сразу же или только в рамках заранее сконфигурированных «окон на техобслуживание». Если при обновлении возникают проблемы, то пользователь всегда может вручную откатить систему к предыдущему рабочему состоянию при помощи команды:
$ sudo rpm-ostree rollback -r
В Fedora CoreOS не применяются команды dnf или yum. Набор пакетов расширяется командой rpm-ostree, послойно располагающей пакеты поверх актуального образа операционной системы. Но, поскольку система Fedora CoreOS сосредоточена на работе с контейнерами, дополнительные сервисы обычно устанавливаются именно в виде контейнеров.
❯ Ubuntu Core
Валентин Дэвид из Canonical рассказал об Ubuntu Core. Как сказано на домашней странице данного проекта, это «безопасная операционная система, предназначенная, прежде всего, для работы с IoT, операционная система для встраиваемых устройств». Система Ubuntu Core нацелена на высокотехнологичные встраиваемые устройства, такие, как промышленные компьютеры для IoT-шлюзов, информационных панелей, робототехники и автоматизированных приложений. Дома эту ОС удобно использовать на Raspberry Pi, чтобы эксплуатировать там такие сервисы как Nextcloud или софт для автоматизации умного дома. Софт для этого дистрибутива базируется на основных сборках операционной системы Ubuntu, но без использования отладочных пакетов или команд dpkg и apt. Напротив, дистрибутив использует только «snap-пакеты» для установки софта. В сущности, snap-пакет — это образ squashfs с некоторыми метаданными, описывающими, как устанавливать и выполнять софт.
Любые snap-пакеты изолированы как от других snap-пакетов, так и от операционной системы, в которой они установлены. Если snap-пакет используется в строго ограниченных условиях, он, фактически, работает в песочнице и использует AppArmor, seccomp и группы контроля. По умолчанию snap-пакеты не имеют доступа к ресурсам, расположенным вне песочницы, но могут получать доступ к конкретным ресурсам, используя для этого интерфейсы.
Дэвид объясняет, что в Ubuntu Core есть пять типов snap-пакетов. В snap-пакете «gadget» содержатся компоненты, специфичные для конкретных устройств или архитектур. Такие компоненты — это, например, загрузчик, дерево устройств, пакеты, и конфигурации, специфичные для конкретных плат и конфигураций. В snap-пакете «kernel» поставляется ядро Linux, модули, прошивка и заглушки systemd. Snap-пакет «base» содержит файловую root-систему, рассчитанную на операционную систему Ubuntu Core. В snap-пакете «snapd» лежит демон snapd, устанавливающий и обновляющий все snap-пакеты. И напоследок: каждое приложение упаковано в свой snap-пакет. В нём лежит файловая root-система из базового snap-пакета. Также он может предоставлять базовой операционной системе сервисы и команды.
Также в snap-пакете gadget описана компоновка диска. Обычно диск в Ubuntu Core разделён на четыре раздела. В UEFI-системах для «посева» используется раздел (ESP), в котором содержится конфигурация для загрузчика, работающего на первой стадии, а также как минимум для одной системы, предназначенной для восстановления. В «загрузочном» разделе (boot) содержится загрузчик, работающий на второй стадии, а также ядро и initramfs. Этот раздел дешифрует разделы «save» и «data». Два последних зашифрованы в соответствии со спецификацией LUKS2. Раздел для сохранения («save») содержит резервную копию удостоверений устройств и другие компоненты, упрощающие восстановление системы, тогда как в разделе данных («data») содержится информация о системе и о пользователе.
Большая часть операционной системы Ubuntu Core доступна только для чтения. Например, /etc и /var таковы по умолчанию. Однако конкретные пути монтируются с привязкой (bind-mount), идущей от раздела с данными — таков, например, /etc/systemd, через который системе разрешено монтировать любые файлы systemd unit для сервисов, а также монтировать образ squashfs нужного snap-пакета. Snapd обрабатывает транзакционные обновления: если обновить snap-пакет не удаётся, то система автоматически откатывается к использованию предыдущей версии этого snap-пакета.
❯ openSUSE MicroOS
Игназ Форстер, инженер-исследователь из SUSE, описал, как устроена операционная система openSUSE MicroOS. Это дистрибутив openSUSE Tumbleweed с плавающим выпуском, специально разработанный как одноцелевая система. Как правило, такой дистрибутив предназначается для хостинга контейнеров, но на его основе даже можно создать минимальную сборку для ПК. Подобно Fedora CoreOS и Ubuntu Core, openSUSE Micro автоматически обновляется и содержит минимальную подборку пакетов. В случае с openSUSE MicroOS в эту подборку входят только RPM-пакеты из репозиториев openSUSE. Также этот дистрибутив существует в версии для предприятий, SUSE Linux Enterprise Micro, а на основе последней в сообществе была разработана и ещё одна версия, Leap Micro.
Файловая root-система в OpenSUSE MicroOS предназначена только для чтения, при этом используется Btrfs. Транзакционные обновления обрабатываются при помощи SUSE-специфичного скрипта-обёртки, внутри которого лежит менеджер пакетов zypper, transactional-update. С его помощью создаётся новый мгновенный снимок Btrfs, отражающий состояние файловой root-системы, а затем выполняется обновление системы. Если установка прошла успешно, то этот скрипт помечает новый мгновенный снимок как предназначенный для использования по умолчанию. Если возникнут ошибки, то новый мгновенный снимок отбрасывается, а по умолчанию продолжает использоваться предыдущая версия. Новый мгновенный снимок активируется при перезагрузке. Также Форстер предупредил, что, поскольку все предназначенные только для чтения компоненты openSUSE MicroOS теперь перенесены в /usr, свежий релиз транзакционных обновлений 4.2.0 также позволит применять новые мгновенные снимки без перезагрузки. В MicroOS работает сервис systemd, предназначенный для проверки работоспособности, в частности, штатно ли система загружается после обновления. Если при такой проверке обнаруживается, что система сбоит, то происходит откат к предыдущему мгновенному снимку той файловой root-системы, что использовалась по умолчанию.
Исходный скрипт для транзакционных обновлений развился в универсальную библиотеку — libtukit. Она предназначена для атомарных обновлений системы. В актуальной реализации Btrfs поддерживается только с утилитой Snapper из openSUSE, предназначенной для создания мгновенных снимков — поскольку именно она используется в openSUSE MicroOS. Но, по словам Форстера, сейчас рарабатывается и API для поддержки других бекендов.
В отличие от Ubuntu Core, АМН файлы, содержащиеся в /var и /etc доступны для записи, а /usr — только для чтения. Например, задаваемая по умолчанию системная конфигурация кладётся в /usr. Любые изменения, вносимые администраторами, находятся только в /etc.
Инструмент libeconf из openSUSE обеспечивает слияние конфигурационных файлов из нескольких местоположений. Для работы по такому принципу было изменено большинство пакетов, применяемых по умолчанию в MicroOS. Пока данное соглашение не распространяется только на /etc/fstab. Форстер резюмирует, что в openSUSE избран прагматичный подход к использованию имеющейся инфраструктуры и пакетов, и что это «функциональная операционная система только для чтения и для работы в несовершенном мире».
❯ Bottlerocket
Притом, что каждая из трёх разобранных выше операционных систем произошла от универсального материнского дистрибутива, с Bottlerocket иная история. Этот дистрибутив был создан Amazon и специально приспособлен для хостинга контейнеров в облаке Amazon Web Services (AWS). Программист Шон Мак-Джиннис из компании AWS в своей лекции сразу же подчеркнул, что эта операционная система «поддерживается AWS, но предназначена не только для AWS». В качестве примера в GitHub-репозитории этого проекта даны инструкции, как использовать эту операционную систему на голом серверном железе.
Система Bottlerocket была анонсирована в марте 2020 года, а в общий доступ была выведена в августе 2020. Amazon, добиваясь максимальной компактности этого дистрибутива, публикует его в разных вариантах для конкретных практических случаев. Например, есть вариант aws-k8s с containerd и kubelet для использования в качестве узла Kubernetes на AWS, есть вариант vmware-k8s для той же цели на VMware и работы с Amazon Elastic Kubernetes Service (EKS), есть и вариант metal-k8s, поддерживающий Amazon EKS на голом железе.
В Bottlerocket используется две совершенно разные контейнерные среды выполнения. Одна из этих сред предназначена для использования хост-контейнеров при эксплуатационных задачах. Вторая предназначена для использования контейнеров в оркестраторе, например, в составе подов Kubernetes. Профили безопасности у двух этих сред отличаются.
Каждый контейнер, где бы он ни работал — на хосте или в оркестраторе — использует клиентский API, который через сокет Unix общается с серверным API, работающим на Bottlerocket. Когда Bottlerocket загружается, его загрузочная конфигурация (включая пользовательские данные) попадает на сервер API. Взаимодействие с пользователем также, как правило, осуществляется через этот API, и он позволяет вносить изменения в системную конфигурацию в режиме реального времени.
Один из хост-контейнеров является «управляющим», он запускается при загрузке машины. Он используется для того, чтобы сконфигурировать хост с Bottlerocket. Еще один хост-контейнер — «администраторский». Он по умолчанию не запускается, а должен запускаться лишь в крайнем случае, для устранения неисправностей в операционной системе хоста. В нём есть дополнительные привилегии, и он может использовать пространство имён root-процесса для доступа в другие контейнеры с целью их отладки. В администраторском контейнере работает SSH-сервер, к которому можно обращаться через основной сетевой интерфейс хоста. Наконец, есть ещё один тип хост-контейнера: предзагрузочный. Он выполняет первичную загрузку контейнера ещё до того, как запустятся сервисы вроде Kubernetes или Docker. В нём предусмотрены дополнительные права, например, для предоставления доступа к файловой системе базового хоста.
Один из ключевых аспектов Bottlerocket — безопасность. Файловая root-система предназначена только для чтения, а /etc поддерживается файловой системой tmpfs, которая восстанавливается при каждой загрузке. Для контейнерных образов и томов монтируется специальный пользовательский раздел. Более того, там нет ни менеджера пакетов, ни оболочки, ни интерпретатора Python. «Если злоумышленник выберется за пределы контейнера, у него в распоряжении будет не так много инструментов», — отмечает Мак-Джиннис.
Чтобы удостовериться в целостности блоковых устройств, Bottlerocket использует dm-verity. Ядро загружается в заблокированном режиме (lockdown), поэтому рут-пользователь не может его изменить. По словам Мак-Джинниса, так выше уверенность, что действующее ядро соответствует загруженному. Ещё один аспект обеспечения безопасности заключается в том, что Bottlerocket работает с SELinux в принудительном режиме.
Для обновлений в Bottlerocket применяется модель на основе образов. Ядро, системные пакеты и пакеты контейнерной среды исполнения в полном составе хранятся внутри образа операционной системы. В первом блочном устройстве на хосте есть активный и неактивный раздел. Усовершенствованный образ скачивается в неактивный раздел, и при перезагрузке хост загружается именно с этого раздела, который затем становится активным. Предыдущий образ Bottlerocket продолжает храниться в другом разделе, который теперь стал неактивным, и при необходимости к нему можно откатиться.
❯ Заключение
Рассматривая различные подходы к работе с одноцелевыми дистрибутивами Linux, понятно, что наилучшего варианта здесь не существует. Вы сами выбираете один из вариантов в зависимости от того, как он соотносится с вашими целями, а также с какими инструментами вам удобно работать. Вы хорошо вложились в конфигурацию, основанную на API для AWS или Kubernetes? Тогда вам, наверное, лучше всего подойдёт Bottlerocket. Вы предпочитаете использовать сервисы при помощи snap-пакетов? Думать нечего, выбирайте Ubuntu Core. Если вы хотите эксплуатировать контейнеры на хост-системе, не слишком много внимания уделяя их поддержке, то вам должны подойти Fedora CoreOS или openSUSE MicroOS. Пожалуй, если все рабочие нагрузки у вас выполняются в контейнерах, то не так важно, что вы используете под капотом — rpm-ostree или мгновенные снимки Btrfs.