main

О билд системах, часть вторая

В продолжение предыдущей части, предлагаю посмотреть как подобная же система организуется на базе bsd.

Здесь есть значительные отличия - во-первых сама система - source-based. Пакеты по дефолту собираются на самой целевой машине. Бинарные пакеты - не более чем опция, до последнего времени прилепленная достаточно сбоку.

Во-вторых, нет 2х одинаковых систем. Прежде чем переходить на обновление бинарниками, требуется привести настройки, версии системы и расположение файлов более-менее к одному виду.

В-третьих - немного другая цель. Под дебиан дефолт тебя как правило устраивает, пересобираешь выборочно и своё. Под бзд ты это делаешь, чтобы ХОТЯ БЫ ЧАСТИЧНО избавиться от гемора с обновлением и от затрат времени на него. Примеры - кольцевая зависимость apr <=> svn, perl <=> exim, icu, lzo <=> bacula-fd. Всё это при сборке руками периодически ломается.

Теория

Примерное движение пакетов и исходников показано на схеме. Обозначения:

  • .txz -- бинарники
  • .tar.gz -- оригинальные исходники

Программы:

  • poudriere -- непосредственно сборка пакетов
  • ts -- очередь заданий на замену atd/batch
  • pkg -- управление пакетами
  • cron -- автоматизация обслуживания

Реализация

Потребуется ~40-80 гб места на всё, прайс-лист ниже:

  • дерево портов -- 3Гб за штуку, (+1 системное)
  • дистфайлы -- если периодически чистить - 2Гб минимум
  • отдельный jail на каждую ветку и архитектуру -- 2,5Гб за штуку
  • кэш для объектных файлов -- 5-15Гб
  • зеркало svn'а портов -- 20Гб (не wc, а именно зеркало, если хотим его раздавать дальше)
  • зеркало svn'а системы -- 8Гб (если не хотите дождаться второго пришествия в процессе обновления jail'ов)

Также потребуется > 2Гб памяти, сборка некоторых пакетов жрёт немеряно памяти. Например что-либо с использованием boost'а.

Развёртывание с нуля всей системы происходит примерно в такой последовательности:

  • ставится хост-система в конфигурации «по минимуму»
  • ставится необходимый софт, (poudriere, ts, cron, mail, <…>)
  • генерятся ключи для подписи пакетов/метаданных, настраивается конфиг poudriere
  • выделяется достаточно места под сборку и хранение пакетов (минимум 50-60 гигов суммарно в /usr/obj, /usr/ports, /usr/local/poudriere, /usr/local/www - лучше вынести на отдельный раздел и понаставить симлинков)
  • скачивается отдельное дерево портов (poudriere ports -c <…>)
  • определяются необходимые наборы софта (точнее количество наборов), и наборы архитектур/версий системы, под которые будет собираться софт
  • для каждого набора софта составляется make.conf с набором OPTIONS_SET/UNSET, делаются симлинки вида $jailname-make.conf с нужного make.conf
  • строятся сборочные jail'ы (${softwareset}-${branch}x${arch}) (это легко займёт 2-3 дня)
  • составляются возможно более полные списки пакетов для каждого набора софта pourdiere.d/lists
  • проводится тестовый билды для каждого из наборов до полного устранения видимых косяков
  • при необходимости дополнительно настраиваются опции портов через poudriere options
  • проводится полномастабные билды (опять же - легко займёт 2-3 дня)
  • публикуются пакеты через вебсервер, раскидываются конфиги/ключи на нужные хосты

Список граблей

Вынесен отдельным пунктом, потому что их много и половина -- show-stopper'ов.

  • одновременное подключение 2х репозиториев, например "официального" и своего вызывает весёлый расколбас в обновлениях. Один день, когда прилетает новая версия из "официальной" репы хочет обновится 66 пакетов, следующий день, когда билдсервер соберёт свою версию - 2 пакета. (ибо "direct dependency changed", и посрать, что там отличие в установке примеров для конфигов, html-доков или ещё какой херни)
  • в силу предыдущего пункта - в репе придётся держать все пакеты, которые используются, и обновлять их своими силами.
  • разрешение зависимостей при сборке - примитивно до тупости. Обновился perl 5.16.3_10 -> 5.16.3_11. Удаляем из репы всё что от него зависит, прямо или косвенно. Хуяк, от репы в 300 пакетов - осталась треть, всё остальное собирается заново. Особенно забавно это в свете 2х предыдущих пунктов.
  • обновление пакетов из сорцов никуда не девается, portmaster радостно скажет "а у тебя есть обновление для перлового модуля с xs, давай-ка я тебе заново СОБЕРУ ещё 15 пакетов, включая autocrap, m4, bison, cmake и прочее", которые ты любовно выкорчёвывал из системы, ибо заебут обновлениями каждый день.
  • обновления системы из сорцов тоже никуда не девается, фактически это единственный способ обновления системы при использовании кастомного ядра. А использовать кастомное приходится, потому что GENERIC нихера не умеет. Обновление системы по времени - это примерно столько же, сколько обновление портов за то же время. От 2х до 5 часов в месяц. На каждую машину.
  • нет никакой возможности узнать, какого художника вот этот пакет тянет половину иксов ДО его установки. Выглядит это так: "обновился пакет X, размер 300кб, устанавливается 64 пакета по зависимостям, размер 300Мб"

Итого

Билд-система получается намного проще и логичнее устроенной, чем в случае с debian'ом, но вышеуказанные грабли сводят это преимущество к нулю. Окей, будешь ты тратить не 5 часов на обновление каждой машины, а только 3. Сильно полегчало?