Введение
Вопрос о том, как ставить софт на сервер, выглядит решенным примерно до момента, пока в команде не находится два человека с разными привычками. Один ставит `apt install nginx` и не понимает, зачем усложнять. Второй тянет тот же nginx контейнером, потому что через полгода придется откатываться, и делать это через apt он не хочет. Да и типичный это спор между олдскулами и сторонниками контейнеров везде и всюду.
Мы решили посмотреть, что получится, если в качестве аргумента взять секундомер. Метод не универсальный, но вполне имеет право на существование. Результаты вышли не совсем такими, как ожидалось. Разница во времени между методами оказалась в четыре раза. Самым быстрым оказался Nix, который обычно считают сложным и медленным. Однако различие в отклике под нагрузкой было вызвано не разными методами установки, а другими версиями библиотек, которые использовались этими методами. Отдельно выяснилось, что обрыв установки на середине pip не переживает вовсе, и систему после него пришлось чинить руками.
Дальше по порядку. Сначала карта способов, поскольку их больше пяти. Потом критерии сравнения и методика вместе со всеми ее слабыми местами. Потом числа. В конце сводная таблица с плюсами, минусами и сценариями, где каждый способ уместен.
Готовые серверы + предустановленное программное обеспечение, а также индивидуальные конфигурации серверов.
Карта способов установки
Императивные способы установки
Поставить одно и то же приложение на сервер можно добрым десятком способов, и напрямую их сравнить или сопоставить нельзя. apt и сборка из исходников отвечают только за то, откуда приедет пакет и куда он ляжет. Ansible и Nix описывают сервер целиком, так что установка приложения оказывается там частным следствием общего описания. Контейнер меняет само окружение, в котором приложение действует, из-за чего вопрос «какая у вас версия Python» после перехода на него теряет смысл. Но каждый из перечисленных способов позволит достичь нужного результата и запустить ПО на сервере. Поэтому во второй части статьи мы попробуем провести сравнение по результату, а именно по времени до первого успешного ответа, по накладным расходам и по тому, что происходит при откате.
Пакетные менеджеры дистрибутива
Штатный менеджер, apt, dnf, apk или pacman, дает подписанные пакеты, автоматическое разрешение зависимостей и обновления безопасности вместе с остальной системой. Версия при этом привязана к релизу дистрибутива. Например, в Ubuntu 24.04 из-за этого едет PostgreSQL 16, шестнадцатым он и останется до конца поддержки релиза, а за свежей мажорной версией придется идти в сторонний репозиторий.
Сторонние репозитории
Свежие версии ПО берут из репозиториев самих разработчиков, где лежат сборки Docker, PostgreSQL и Nginx, либо из PPA, COPR и backports. Механика та же, что у apt, и команды аналогичны. Ключевой недостаток этого метода заключается в необходимости довериться владельцу репозитория и риском, что при обновлении дистрибутива репозиторий либо не успеет собрать пакеты под новый релиз, либо конфликнет с системными.
Отдельная история начинается тогда, когда репозиторий заводите вы сами, ведь тогда к вопросу доверия к репозиторию добавляется вопрос его организации. О своем опыте мы рассказывали в этой статье.
Сборка из исходников
Если иного варианта нет ни в дистрибутиве, ни у разработчика в репозитории, то помогает сборка из исходников, например, когда nginx понадобился с модулем, которого нет в готовом пакете, или когда на библиотеку надо наложить патч, еще не доехавший до релиза. Порядок при этом остается неизменным: скачать архив, сверить контрольную сумму или подпись, поставить компилятор с заголовочными пакетами, а дальше ./configure, make -j$(nproc) и make install.
Больше всего времени уходит на подбор зависимостей, поскольку ./configure падает на первом же отсутствующем пакете с суффиксом -dev, вы его ставите, запускаете заново и падаете на следующем. С библиотеками из нашего стенда так и получилось: psycopg2 требует libpq-dev, cryptography тянет заголовки OpenSSL и компилятор Rust, а Pillow просит заголовки zlib и libjpeg.
Результат по умолчанию будет расположен в /usr/local, systemd-юнит необходимо написать вручную, и при каждом обновлении придется повторять весь процесс заново. Откат работает, только если заранее поставить версионированный префикс вроде /opt/nginx-1.26 и переключить ссылку, в остальных случаях предыдущей версии после make install просто не остается.
Бинарники и скрипты установки
Программа приходит архивом в /opt, systemd-юнит пишется руками, иногда попадается AppImage, а всё чаще предлагается строчка curl | bash. Она работает, только вы запускаете от root скрипт, который, скорее всего, видите впервые и который может переписать ваши конфигурационные файлы, а читать его целиком перед запуском мало кто станет.
Snap и Flatpak
Пока пакетные менеджеры остаются частью конкретного дистрибутива, Snap и Flatpak пробуют жить поверх него, приложение приезжает уже со своими зависимостями и в изолированном окружении, которое обновляется само по себе, отдельно от системы. У снапа пакет представляет собой образ squashfs, который монтируется отдельным loop-устройством, а strict confinement опирается на AppArmor, seccomp и пространства имен, из-за чего доступ наружу выдается через интерфейсы и часть из них приходится соединять руками. Flatpak устроен иначе, приложение собирается под общий рантайм, который переиспользуют несколько программ, а к ресурсам хоста песочница ходит через порталы, о чем написано в базовых понятиях формата. Порталы рассчитаны на пользовательскую сессию, которой на сервере обычно нет.
На серверах оба формата встречаются довольно редко. snapd по умолчанию проверяет обновления четыре раза в сутки, расписание правится через refresh.timer, паузу ставит snap refresh --hold, в том числе бессрочную, однако системная настройка refresh.hold держит ее не дольше 90 дней, после чего обновление приедет независимо от вашего мнения. Вдобавок система хранит несколько ревизий каждого снапа для отката, на обычной Ubuntu их две, на Ubuntu Core три, а меньше двух refresh.retain не принимает. Для сервера, где версии планируют и выкатывают вместе с остальным, это неудобно, хотя LXD и certbot распространяются именно снапом, так что совсем мимо серверов формат не прошел.
Языковые пакетные менеджеры
Если системный пакетный менеджер не справляется с задачей, то на помощь приходят языковые менеджеры. pip, npm, gem, cargo, go install, composer, каждый со своим индексом пакетов и правилами разрешения версий. А также, к сожалению, своим представлением о том, куда класть файлы. По нашему опыту именно они дают больше всего инцидентов на сервере. Например, sudo pip install поверх системного Python, после которого перестает работать значительная часть утилит дистрибутива, написанных на том же Python и рассчитанных на другие версии библиотек. С PEP 668 стало лучше, ведь в Debian 12 и в Ubuntu системный Python помечен как externally managed (с 23.04), и pip в него не пишет.
Вторая проблема в цепочке поставок: пакет тянет зависимость, та тянет свою, и затем на третьем уровне оказывается библиотека, о существовании которой можно и не знать. Последствия могут быть плачевными, например в истории с event-stream вредоносный flatmap-stream приехал прямой зависимостью в версии 3.3.6 в сентябре 2018 года и продержался в реестре два с половиной месяца. У ua-parser-js в октябре 2021 года угнали аккаунт разработчика, вредоносные версии 0.7.29, 0.8.0 и 1.0.0 висели в реестре около четырех часов, и этого времени хватило на заражение множества машин. Все, кто в это окно собирал проект, подтянули и вредоносное ПО. Подстраховаться от таких проблем можно по-разному в зависимости от языка, поскольку npm, cargo и composer пишут lock-файл сами, Go проверяет контрольные суммы через go.sum, а pip до недавнего времени обходился requirements.txt, и с версии 25.1 у него появилась экспериментальная команда pip lock по стандарту PEP 751.
Контейнерные
Контейнеры (Docker и Podman), как и декларативные системы, решают задачу воспроизводимости, но со своей спецификой. Описывается образ приложения со своим корневым каталогом и всеми библиотеками, а ядро остается хозяйское, и изоляция задается пространствами имен и cgroups. Версия фиксируется тегом образа, откат сводится к запуску контейнера со старым тегом. Казалось бы, всё просто, но, как обычно, есть нюанс. Тег указывает на конкретную сборку, и если через какое-то время будет выполнено какое-нибудь минорное обновление ПО, то тот же тег может вести не на ту версию сборки. Неизменную ссылку дает только digest вида postgres@sha256:..., поскольку он представляет собой контрольную сумму содержимого. Docker и Podman различаются тем, что у первого есть демон, работающий от root, а второй запускает контейнеры напрямую и умеет обходиться правами обычного пользователя, хотя режим rootless есть и у Docker.
Данные приходится явно выносить в тома, в ином случае они исчезнут вместе с контейнером, а логи по умолчанию уезжают в json-драйвер и растут, пока не кончится место на диске. Вдобавок сам движок требует обслуживания. Необходимо следить за его версией, за хранилищем образов, за отсутствием конфликтов между сетью контейнеров и сетью хоста.
Помимо обслуживания самого движка, полноценная работа с контейнерами предполагает вокруг себя оркестрацию, мониторинг, централизованное логирование и обнаружение сервисов, а без этой обвязки Docker может принести больше проблем, чем решить. Как учесть эти нюансы до внедрения, мы показывали на своем примере
Декларативные способы установки и автоматизация
Оркестраторы
Kubernetes редко используют ради одного сервиса, так как он предполагает наличие управляющего слоя из etcd, сервера API, планировщика и менеджера контроллеров, плюс kubelet на каждом узле. Helm добавляет сверху шаблонизатор с values-файлами, а операторы приносят собственные ресурсы и контроллеры, которые тоже надо где-то запускать. Существует вариант полегче, тот же k3s собирает управляющий слой в один процесс и обходится существенно меньшим объемом памяти, но и он остается отдельной системой со своими особенностями работы.
Автоматизация конфигурации
Ansible, Puppet, Salt и Chef описывают сервер кодом. Ansible ходит на машины по SSH и ничего на них не оставляет, а Puppet и Chef держат на узле агента, который сам приходит за конфигурацией. Общее у них в идемпотентности, то есть повторный прогон не ломает сделанное ранее, поскольку модуль сначала смотрит текущее состояние и меняет только то, что разошлось с нужным состоянием, записанным в конфигурации.
Идемпотентность и воспроизводимость при этом разные. Плейбук с apt install nginx отработает одинаково два раза подряд, а через год может поставить другую версию, ведь состояние `present` означает всего лишь, что пакет установлен, а latest при каждом прогоне подтягивает самую свежую версию из подключенных репозиториев. Воспроизводимость появляется только с явной версией вида nginx=1.24.0-2ubuntu7, и точно так же придется зафиксировать версии коллекций Ansible в requirements.yml.
Декларативные системы
Nix, NixOS и Guix существуют ради воспроизводимости, которую не могут дать средства императивной автоматизации. При применении этих способов установки ПО окружение описывается целиком, вместе с версиями всех зависимостей, а само описание привязано к конкретной ревизии пакетного дерева, которая в случае flake-конфигурации записана в flake.lock. В результате получается стабильная конфигурация, которая и через год, и через два соберет те же пакеты, поскольку каждый из них лежит в /nix/store под именем, включающим хеш от всех входных данных сборки.
Платой за стабильность является высокий порог входа, нужно иметь довольно тяжелый багаж знаний и опыта для работы с этими методами установки ПО. Привычной иерархии в файловой системе нет, вместо нее ссылки в /nix/store, из-за чего скачанный со стороны бинарник, скорее всего, просто не запустится, ведь по пути /lib64/ld-linux-x86-64.so.2 в NixOS ничего нет, и такой бинарник приходится либо собирать через Nix, либо запускать в совместимом окружении. И таких нюансов много. Чужие рецепты из интернета к вашему случаю также подходят реже, чем хотелось бы.
Готовые решения. Панели и маркетплейсы
Панели управления и маркетплейсы стоят особняком, поскольку администратор тут не выбирает способ установки, а нажимает кнопку, за которой стоит заранее подготовленная процедура развертывания ПО. Ключевым преимуществом данного способа является низкий порог входа, так как процедуру развертывания разрабатывают и внедряют инженеры хостеров, они же допинывают установку, если случается сбой.
Рядом с зарубежными aaPanel и CyberPanel работают ispmanager и FASTPANEL, готовые образы у хостинг-компаний разворачивают WordPress, GitLab или Nextcloud в одно нажатие, а платформу как услугу (PaaS) можно поднять и на своем сервере, например через Dokku или CapRover. Со стороны клиента весь процесс сводится к выбору конфигурации, ПО и скриптов, выполняемых после установки (последнее по желанию). Само развертывание все равно использует один из уже описанных способов, чаще всего пакеты дистрибутива или контейнер, но это уже не проблемы клиента.
Дальше всего эта логика заходит в управляемых приложениях, где вопрос о том, чем именно установлено приложение и кто будет администрировать его инфраструктуру, уезжает к поставщику услуг вместе с ответственностью.
По каким критериям сравнивать способы установки ПО
Двенадцать перечисленных способов различаются кардинально, от места установки до способа отката. Просто их описать — дело несложное, но малоинформативное. Разговор становится предметным тогда, когда появляются оси, по которым способы получают сопоставимые числа. Мы взяли шесть, причем первые четыре измеряются напрямую, пятая проверяется наблюдением, шестая считается инструментом. Если кратко:
- Время до рабочего сервиса. Секундомер останавливается, когда приложение начинает отвечать на запросы, поскольку возврат управления из установочной команды сам по себе ничего не значит. Внутри время разбито на фазы скачивания, распаковки, сборки и запуска;
- Накладные расходы. Занятое место на диске, прирост потребления памяти по всей системе и задержка ответа под нагрузкой;
- Воспроизводимость. Даст ли та же конфигурация те же версии зависимостей спустя время и на другой машине;
- Откат. Сколько занимает возврат на предыдущую рабочую версию и что при этом теряется. В пакетных системах это устроено хитрее, чем кажется, ведь установить более раннюю версию обычным обновлением нельзя, и приходится, например, пользоваться полем Epoch, при котором пакет с меньшей версией считается более новым;
- Устойчивость к сбою. Что остается в системе, если установку прервать на середине, и можно ли после этого просто повторить команду?
- Известные уязвимости после установки. Сколько известных CVE тянет за собой каждый способ доставки пакетов?
Тесты ориентировочные, и что важно, так это отсутствие возможности перегнать в тест порог входа для каждого способа установки ПО, стоимость эксплуатации и прочие неизмеримые и не универсальные аспекты.
Какие способы установки будем тестировать и почему
Все двенадцать способов гонять смысла нет, так как количественно они друг с другом не сходятся, а часть даст результат, известный и без замеров. Мы взяли по представителю от каждого семейства и добавили тот способ, который чаще прочих оказывается источником проблем.
Apt является точкой отсчета, поскольку он ставит готовые бинарные пакеты без сборки, ничего не добавляет к системе сверх самих пакетов. Pip в связке с venv интересен количеством инцидентов. Docker — самый спорный из пяти, поскольку его противники и сторонники разделены примерно на равные по количеству группы, сторонники считают его стандартом, а противники видят в нем только лишнюю сущность на сервере. Ansible любопытен тем, что снаружи выглядит декларативным, а внутри вызывает все тот же apt. Nix стоит на декларативном полюсе, и с ним удобно сравнивать остальное.
Методология
Измерения мы проводили на том, что стоит у обычного человека, то есть на пяти арендованных виртуальных машинах в одном дата-центре, по машине на способ, с пятью прогонами и одинаковым приложением для всех методов установки. Следует отметить, что такая постановка отвечает на вопрос «сколько это займет времени», а не предоставляет идеальный эталон для выбора метода установки ПО, все же это не лабораторное исследование в идеальных условиях на выделенном железе.
Приложение требовалось с нативными зависимостями, иначе половина интересных проблем не проявится, поэтому мы собрали сервис на FastAPI, которому нужны psycopg2, Pillow и cryptography, а рядом поставили PostgreSQL и Nginx. Пакет psycopg2-binary не используется сознательно, чтобы нативный код собирался из исходников. Маршрутов у сервиса два: /health отвечает успехом, когда приложение поднялось, именно по нему засекалась готовность, а /api/test на каждый запрос читает фиксированную строку из базы, меняет размер одной и той же картинки и подписывает результат. PostgreSQL ставится тем же способом, что и приложение. Единственным исключением стал pip, поскольку серверные пакеты он ставить не умеет, и база в итоге приезжала из apt.
|
Сервер |
Процессор, 1 поток |
Процессор, 4 потока |
Операций записи |
Задержка записи, 99-й процентиль, мс |
|
apt |
901,3 |
3677,6 |
12 856 |
3,88 |
|
pip |
930,4 |
3758,8 |
12 178 |
3,88 |
|
Ansible |
919,1 |
3653,9 |
11 974 |
3,92 |
|
Nix |
933,7 |
3741,8 |
26 652 |
1,22 |
|
Docker |
977,6 |
3820 |
32 038 |
1,16 |
По данным процессора серверы сошлись неплохо, крайние значения расходятся на 8,5 процента в один поток и всего на 4,6 процента в четыре. А вот диски разъехались в 2,7 раза, поскольку docker и nix попали на заметно более быстрое хранилище, где и задержка записи втрое ниже. Что во многом определяет подход к изучению всех таблиц, которые будут представлены ниже. Разница в единицы процентов ничего не значит, а насколько влияют на результат быстрые диски, показывает контрольная серия из следующего раздела.
Результаты
Порог отбраковки по отобранному гипервизором процессорному времени стоял на 5 процентах, и ни один прогон под него не попал, поскольку пиковое значение держалось около 0,26 процента и только у одного прогона Ansible подскочило до 1,49.
Время до рабочего сервиса
|
Способ |
Прогон 1 |
Прогон 2 |
Прогон 3 |
Прогон 4 |
Прогон 5 |
Медиана |
|
apt |
33.15 |
32.58 |
32.45 |
32.15 |
31.70 |
32.45 |
|
pip |
76.83 |
57.72 |
57.33 |
57.17 |
58.41 |
57.72 |
|
Ansible |
111.88 |
110.32 |
111.46 |
111.27 |
110.57 |
111.27 |
|
Nix |
32.48 |
31.86 |
27.12 |
26.49 |
26.27 |
27.12 |
|
Docker |
110.48 |
108.02 |
109.14 |
110.79 |
110.52 |
110.48 |
Медиана считалась по пяти прогонам серии. Пробный прогон, который делался перед серией на свежей машине, чтобы убедиться в работоспособности скрипта, в расчет не идет, поскольку на свежей машине ещё не отработали фоновые таймеры обновления пакетов и условия там отличаются от остальных повторов.
Разброс между повторами у всех способов маленький, за исключением первого прогона pip, где 76,83 секунды против примерно 57,5 у остальных четырех. Разницу объясняет разбивка по фазам. Установка инструментов сборки в первый раз заняла 21,44 секунды против 5,22 в последующих, а установка PostgreSQL — 20,28 против 16,09. Кеш apt между прогонами не очищался, поэтому со второго раза build-essential с заголовочными пакетами брались с диска, а не из сети. На сборку нативных расширений это не спишешь, ведь кеш pip чистился перед каждым прогоном и psycopg2 с Pillow компилировались заново, фаза «pip install» держится на 25,92 секунды во всех пяти прогонах.
Медиана у Nix в 27.12 секунды выглядит как победа декларативного подхода, однако достигнута она на машине, где хранилище /nix уже наполнено, ведь между повторами мы удаляли профили и собирали мусор, а сам пакетный менеджер оставляли. Фаза установки Nix в таблице занимает 0.10 секунды именно поэтому. На чистой машине первая установка вместе с загрузкой хранилища заняла 86.44 секунды и завершилась ошибкой на этапе запуска сервиса, так что метрику готовности с нее снять не удалось.
Контрольная серия
Машины разошлись по калибровке сильнее, чем и ожидалось, и хотелось бы, ведь по процессору в один поток расхождение между крайними значениями составило 8,5 процента, а по числу дисковых операций записи разница достигла 2,7 раза, поскольку серверы под Docker и Nix получили заметно более быстрые диски. Чтобы понять, не в дисках ли дело, мы прогнали apt пять раз на машине, зарезервированной под Nix.
|
apt, 12 856 операций |
nix, 26 652 операции |
Разница |
|
|
Время до сервиса |
32.45 сек. |
34.22 сек. |
+5,3 процента |
|
Запросов в секунду |
63.51 |
60.55 |
−4,7 процента |
Машина с вдвое более быстрым диском дала чуть худший результат, и это, скорее всего, означает, что дисковая подсистема не была узким местом. Зато сравнение Nix и apt на одной и той же машине стало чистым, и там Nix выигрывает 21,4 процента по времени до сервиса и 49,7 процента по числу запросов в секунду.
Отклик под нагрузкой
|
Способ |
Медиана задержки, сек. |
99-й процентиль, сек. |
Запросов в секунду |
|
apt |
0.323 |
0.401 |
63.51 |
|
pip |
0.332 |
0.425 |
61.15 |
|
Ansible |
0.339 |
0.430 |
60.19 |
|
Nix |
0.221 |
0.317 |
90.62 |
|
Docker |
0.292 |
0.377 |
69.90 |
Полуторакратная разница между Nix и Ansible на одинаковом коде приложения выглядит подозрительно, и проверка версий показывает, в чём тут дело:
|
Способ |
Python |
Pillow |
psycopg2 |
|
apt |
3.12.3 |
10.2.0 |
2.9.9 |
|
Nix |
3.12.8 |
11.0.0 |
2.9.9 |
|
Docker |
3.12.14 |
11.1.0 |
2.9.10 |
Обработчик /api/test большую часть времени занят изменением размера картинки, то есть работает внутри Pillow, а версии Pillow у тестируемых способов разные. Получается, что по этой оси мы сравнили не способы установки, а сборки библиотек, которые эти способы притащили.
Место и память
|
Способ |
Артефакты, мегабайты |
Прирост корневого раздела, мегабайты |
Пакетов dpkg |
|
apt |
46 |
266 |
+58 |
|
pip |
98.3 |
387 |
+34 |
|
Ansible |
46 |
888 |
+80 |
|
Nix |
1357.6 |
53 |
0 |
|
Docker |
632.9 |
2 078 |
+14 |
Две первые колонки требуют небольшого пояснения, поскольку du считает только каталоги конкретного способа, а df весь сервер вместе с пакетами в /usr, кешами и журналами, отсюда и разный масштаб чисел. Дороже всех обходится Docker, который приносит два гигабайта против 266 мегабайт у apt, а Nix в этой таблице стоит обособленно, ведь его хранилище на 1357,6 мегабайта наполнено до начала прогона и в прирост уже не попало.
По памяти разброс небольшой и предсказуемый:
|
Способ |
Мегабайты |
|
apt |
543.5 |
|
pip |
538.2 |
|
Ansible |
609.7 |
|
Nix |
641.9 |
|
Docker |
673.2 |
Docker требует больше памяти по сравнению с apt примерно на 130 мегабайт, а заодно он приносит 15 новых юнитов systemd против пяти у apt и двух у Nix.
Воспроизводимость
Хеш полного списка версий совпал у всех способов на всех пяти прогонах, кроме apt, где первый прогон дал один хеш, а четыре последующих — другой. Контрольная серия на второй машине дала тот же хеш, что и поздние прогоны, так что причина не в машине, и разбираться с ней придется отдельно. Тут же мы натыкаемся на еще одно ограничение нашей методологии, по-хорошему воспроизводимость нужно проверять на отрезке в год, а не нескольких дней.
Уязвимости
|
Что сканировали |
Критические |
Высокие |
Средние |
Низкие |
|
apt |
114 |
2327 |
26 634 |
2655 |
|
pip |
119 |
2493 |
28 689 |
2846 |
Обе строки сняты командой trivy fs --scanners vuln / на одинаковой системе, так что лишние пять критических и 166 высоких у pip высоких приходится на дополнительные пакеты, которые ставит скрипт с pip, то есть на python3-dev, build-essential и заголовочные файлы библиотек для сборки psycopg2 и Pillow. Для Docker, Ansible и Nix нужен другой способ сканирования, так что их результаты в эту таблицу не попали.
Что пошло не так
Самое интересное обнаружилось в отказах.
Ansible на Ubuntu 22.04 не ставит коллекции Galaxy, поскольку ansible-core версии 2.12 несовместим с текущим механизмом разрешения зависимостей, и пилотные прогоны на этой системе пришлось забросить.
Обрыв установки способом pip на сороковой секунде оставил систему в состоянии, из которого повторный запуск скрипта не восстановил систему, и кластер базы пришлось создавать руками через pg_createcluster. Это та ось устойчивости к сбою, которую мы заявили в критериях, и pip ее провалил.
Установщик Nix при повторном запуске падает на собственных резервных копиях системных файлов, а nix-collect-garbage -d удаляет профиль суперпользователя вместе с бинарником nix. Оба случая могут произойти и при обычной эксплуатации.
Какой способ установки и под какую задачу выбрать
|
Способ установки |
Плюсы |
Минусы |
Для чего подходит |
|
Пакетные менеджеры дистрибутива |
Подписанные пакеты, обновления безопасности, способ хорошо знаком и привычен для пользователей Linux. |
Мажорную версию не меняют до конца поддержки релиза. |
Nginx, PostgreSQL и прочее ПО, если устраивает версия из дистрибутива. |
|
Сторонние репозитории |
Свежие версии ПО, механика та же, что у apt. |
Необходимо доверять владельцу репозиториев, риски безопасности, риск конфликта при обновлении дистрибутива. |
Docker, PostgreSQL, Nginx и всё ПО, если требуется свежая версия. |
|
Сборка из исходников |
Контроль над флагами компиляции, возможность наложить свой патч, сборка любой нужной версии ПО. |
Необходимо настраивать зависимости вручную, пакетный менеджер и сканер уязвимостей такую программу не видят. |
Если нужен модуль или патч, которого нет в готовых сборках. |
|
Бинарники и `curl \| bash` |
Ставится за минуту, сборка от автора программы, а не от сопровождающего в дистрибутиве. |
Чужой скрипт запускается от root, нет штатного обновления и отката. |
Утилита без данных и зависимостей, которую при сбое проще поставить заново, чем чинить. |
|
Snap и Flatpak |
Изоляция, работа поверх любого дистрибутива. |
Обновления приезжают сами, задержка не длиннее 90 дней, старые ревизии пакетов остаются на диске. |
LXD, certbot и прочее ПО, распространяемое вендором только таким способом. |
|
Языковые менеджеры |
Доступ ко всем пакетам языка, включая те, которых в дистрибутиве нет, причем версии выходят раньше, чем попадают в репозитории. |
Ставит пакеты поверх системного Python и может поломать утилиты дистрибутива, нативные расширения собираются заново при каждой установке, риски вредоносных пакетов. |
Библиотеки под свое приложение, которых нет в репозитории дистрибутива. |
|
Контейнеры |
Окружение едет с приложением, откат сменой тега, изоляция. |
Демон занимает память, в наших замерах 673 мегабайта против 543 у apt, образы и слои сборки съели два гигабайта на диске, а уязвимости внутри образа хостовые сканеры не видят. |
Подходит для ситуаций, когда на машине несколько сервисов с разными версиями библиотек, либо важна возможность быстро вернуться на прошлую версию. |
|
Оркестраторы |
Сервисы переезжают между узлами сами, упавший контейнер перезапускается без участия человека, нагрузка распределяется по кластеру. |
Управляющий слой из etcd, сервера API, планировщика и контроллеров ест ресурсы одинаково при одном приложении и при сорока. |
Есть необходимость поддержки множества сервисов на нескольких узлах, простой недопустим, и есть человек, который занимается кластером. |
|
Автоматизация конфигурации |
Сервер описан кодом, идемпотентность, удобно для большого парка машин. |
Одинаковый плейбук через год поставит другие версии пакетов, если они не прописаны явно, а установка самого Ansible заняла в наших прогонах 68 секунд из 111. |
Парк однотипных серверов, например, узлы приложения с Nginx, PostgreSQL и агентом мониторинга. |
|
Декларативные системы |
Одна и та же конфигурация собирает те же версии пакетов через год, откат возвращает всю систему одной командой, а на наполненном хранилище установка прошла на 21 процент быстрее apt. |
Своя модель сборки и свой язык конфигурации, скачанный со стороны бинарник не запускается, каталог /nix занимает полтора гигабайта и растёт с каждым поколением. |
Долгоживущий сервис, который необходимо воспроизвести через год, наличие человека, готового разобраться с Nix. |
|
Панели и маркетплейсы |
Низкий порог входа, приложение разворачивается выбором из списка, плейбук установки пишут и поддерживают инженеры хостера, они же разбираются при сбое. |
Процедуру и состав установки определяет хостер, то есть ни версию приложения, ни набор зависимостей вы не выбираете, а перенос на другую площадку означает сборку с нуля. |
Типовое приложение вроде WordPress или GitLab, когда заниматься сервером некогда, а настройка нужна стандартная. |
Итоги
Способ установки сам по себе редко ускоряет или замедляет программное обеспечение, но может повлиять на процесс первого развертывания, на обновления ПО в будущем. Выбирать при этом приходится не только по времени, которое займет установка.
Apt дает предсказуемость ценой замороженной версии, а языковой менеджер предоставляет свежие библиотеки ценой конфликтов с системой и тридцати с лишним лишних пакетов на сервере.
Контейнер позволяет выполнить откат сменой тега, но добавляет постоянно работающий демон, уязвимости внутри образа, которых хостовый сканер не видит и занимает два гигабайта на диске. Nix же предоставляет повторяемость ценой высокого порога входа и собственной файловой иерархии.
Стоящие особняком автоматически развертываемые панели и маркетплейсы ПО позволяют установить нужный софт без каких-либо навыков администрирования, но и не позволяют контролировать, что именно установлено.
Причем всё вышесказанное касается одного сервера, а на парке машин к проблемам выбора метода установки добавляются вопросы жизненного цикла, сборки и раздачи пакетов по площадкам, об этом мы рассказывали ранее.
Готовые серверы + предустановленное программное обеспечение, а также индивидуальные конфигурации серверов.