Сборка образа: 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 МБ) решено оставить в образе. Рассматривались и отклонены два пути:
depends: trueпри удалении: ломает сборку, см. выше.- Собственный готовый пакет модуля под конкретное ядро: модули привязаны не к ветке ядра, а к точной сборке (6.18.55 и 6.18.56 уже несовместимы). Пришлось бы пересобирать пакет при каждом обновлении ядра Sisyphus, то есть почти ежедневно.
Не пробовали: многоэтапный Containerfile, где gcc и make есть только в отдельном слое сборки, а в финальный образ копируется готовый .ko. Если вернётесь к теме, начинайте с него.
Локально проверить такое нельзя: нужен настоящий APM, а каждая попытка в CI стоит полного цикла сборки образа.
Нарезка слоёв#
О том, как образ делится на слои для небольших обновлений, см. rechunk и chunkah.