Git

Сборка образа: DKMS, ядро и APM

Заметки о подводных камнях при сборке образа через APM и CI. Они пригодятся тем, кто правит рецепт образа (image.yml и модули в src/resources/).

DKMS: ядро хоста сборки не совпадает с ядром образа#

Модули ядра, которые собираются через DKMS (например ddcci), нужно собирать под ядро образа, а не под ядро машины, где идёт сборка.

Симптом. Сборка падала с ошибкой «kernel headers for kernel X cannot be found», причём версия X менялась от запуска к запуску и не совпадала с только что установленной.

Причина. dkms без параметра -k собирает под uname -r процесса, который его вызвал. В CI-контейнере это ядро хоста раннера: у контейнера нет своего ядра. Установленное в образ ядро лежит там просто файлами.

Решение. Брать версию из того, что реально лежит в /lib/modules образа, и передавать её в dkms явно, через -k. Модуль APM type: kernel (параметры kernel-info.flavour и include-headers: true) держит пакеты ядра и заголовков в одной версии: обычная установка уже установленного kernel-image для APM ничего не делает.

Ветка ядра (flavour) указана в модуле явно. Если она сменится, её нужно поправить вручную.

Репозиторий подключается модулем type: repos#

В базовом образе нет apt-get: весь пакетный менеджмент идёт через APM. Попытка добавить репозиторий командой в type: shell падала с apt-get: command not found. Просто положить файл в /etc/apt/sources.list.d/ тоже недостаточно: APM не видит его, пока не обновит свою базу пакетов. Нужно использовать модуль type: repos: он же обновляет базу, и следующий type: packages находит новый пакет.

depends: true удаляет больше, чем кажется#

Хотелось убрать gcc и make после сборки модуля DKMS, чтобы образ был меньше:

- type: packages body: remove: [gcc, make] depends: true

Сборка сломалась: Failed to enable unit: Unit ddcci-attach.service does not exist.

Причина. depends: true удаляет не только пакеты, которые тянули за собой gcc и make, но и те, что сами зависят от них. Пакет dkms-ddcci зависит от gcc, как и любой пакет DKMS, поэтому его удалило вместе с юнитом ddcci-attach.service.

Итог. gcc и make (с зависимостями около 360 МБ) решено оставить в образе. Рассматривались и отклонены два пути:

  1. depends: true при удалении: ломает сборку, см. выше.
  2. Собственный готовый пакет модуля под конкретное ядро: модули привязаны не к ветке ядра, а к точной сборке (6.18.55 и 6.18.56 уже несовместимы). Пришлось бы пересобирать пакет при каждом обновлении ядра Sisyphus, то есть почти ежедневно.

Не пробовали: многоэтапный Containerfile, где gcc и make есть только в отдельном слое сборки, а в финальный образ копируется готовый .ko. Если вернётесь к теме, начинайте с него.

Локально проверить такое нельзя: нужен настоящий APM, а каждая попытка в CI стоит полного цикла сборки образа.

Нарезка слоёв#

О том, как образ делится на слои для небольших обновлений, см. rechunk и chunkah.