Ubuntu 24.04: DKMS зламався після оновлення ядра — відновіть драйвери без простоїв

Було корисно?

Ви патчуєте флот. Ядро оновлюється. Через кілька хвилин ваша система моніторингу починає сигналити: зникли GPU, ZFS-пулі скаржаться, зникли NIC offload-и, можливо, фібрика InfiniBand флапає. Сервіси поки що працюють… але ненадовго. І тоді ви бачите істину: DKMS не зібрав модулі для нового ядра, тож наступний перезавантаження — пастка.

Це реальність експлуатації Ubuntu 24.04 у продакшені. Оновлення ядра — рутинна справа; відмови DKMS — плата за використання out-of-tree драйверів. Мета тут не «полагодити після того, як поламалося». Мета: виправити, поки система залишається онлайн, і зробити наступне оновлення ядра нудною рутиною.

Як DKMS насправді ламається після оновлення ядра

DKMS (Dynamic Kernel Module Support) існує тому, що вендори продовжують постачати модулі ядра, які не входять у mainline. NVIDIA, ZFS-on-Linux, деякі NIC і RAID драйвери, VirtualBox, деякі агенти безпеки — будь-що, що компілюється проти заголовків ядра, може опинитися тут.

Коли Ubuntu встановлює нове ядро, скрипти пакетів намагаються перебудувати DKMS-модулі для цього ядра. Якщо ця перебудова провалюється, ви можете не помітити цього відразу, бо поточне запущене ядро все ще має робочі модулі завантажені. Поломка проявляється, коли:

  • Ви перезавантажуєтесь і нове ядро стартує без потрібного модуля.
  • initramfs був згенерований без модуля, що викликає ранні помилки завантаження (сховище, root-on-ZFS, шифрування тощо).
  • Secure Boot блокує неподписаний модуль, і ви отримуєте специфічну помилку «зібрано, але не завантажується».
  • Заголовки для нового ядра не були встановлені, тож DKMS просто нічого не зможе скомпілювати.

Більшість інцидентів «DKMS зламався» — один із цих чотирьох сценаріїв. Виправлення рідко містить якусь містику; частіше воно займає час і лякає операторів. Хитрість — знизити ризик: точно діагностувати, збирати для ядра, у яке ви збираєтесь завантажитися, перевіряти можливість завантаження модуля і лише потім дозволяти перезавантаження.

Сухий факт: DKMS не «динамічний» у тому сенсі, як уявляє менеджмент. Він «динамічний» так само, як динамічна паперова форма: її треба заповнювати щоразу, коли змінюється ядро.

Швидкий план діагностики

Коли ви намагаєтеся уникнути простою, важлива швидкість. Найшвидший шлях: визначте цільове ядро, підтвердіть, чи існує модуль для нього, підтвердіть, чи можна його завантажити, а потім перевірте артефакти завантаження (initramfs). Усе інше — прикраса.

Перше: яке ядро зараз запущене й які ядра встановлені?

  • Якщо ви все ще працюєте на старому ядрі, можете спокійно перебудувати перед перезавантаженням.
  • Якщо ви вже на новому ядрі й модулі відсутні, потрібно відновлювати функціональність на живому ядрі (іноді можливо, іноді ні).

Друге: чи показує DKMS «built» для цільового ядра?

  • Якщо не «built»: ви в режимі «перебудувати і виправити залежності збірки».
  • Якщо «built»: перевірте, чи встановлено в /lib/modules/<kernel> і чи проходить modprobe.

Третє: чи блокує модуль Secure Boot?

  • Secure Boot увімкнений + неподписаний модуль = він може добре збиратись, але впаде при завантаженні з помилкою підпису.
  • Це головна причина циклу «перебудували трохи — нічого не змінилось».

Четверте: чи містить initramfs те, що вам потрібно?

  • Якщо модуль потрібен для раннього завантаження (storage/network root, ZFS root, crypto), то «зібрано» недостатньо.
  • Перегенеруйте initramfs для цільового ядра і перевірте, чи містить він модуль.

П’яте: заблокуйте ризикові зміни, поки виправляєте

  • Утримуйте пакети ядра, якщо unattended-upgrades продовжує тягнути нові ядра під час процесу відновлення.
  • Зафіксуйте відоме робоче ядро як опцію відкату.

Цікаві факти та контекст (чому це повторюється)

  • DKMS походить із екосистеми Dell середини 2000-х, щоб тримати вендорні драйвери здатними збиратись під час оновлень ядра, особливо на корпоративних флотах.
  • Ubuntu довго інтегрує DKMS, але це все одно залежить від скриптів пакування та наявності заголовків — немає заголовків, немає модуля.
  • Застосування Secure Boot перетворило “помилки збірки” на “помилки завантаження”. Модуль може компілюватись ідеально, але все одно бути відхиленим ядром.
  • ZFS on Linux тривалий час жив поза деревом ядра через ліцензійні нюанси; саме тому багато інсталяцій Ubuntu досі покладаються на DKMS для ZFS-модулів.
  • Стабільність ABI ядра не гарантується для out-of-tree модулів. Невеликі оновлення ядра можуть зламати збірки, якщо модуль використовує внутрішні API.
  • Cadence HWE і SRU Ubuntu може вас здивувати: оновлення ядра може прийти через unattended-upgrades, навіть якщо ви «нічого не міняли».
  • initramfs часто — справжня зона відмов. Система завантажує ядро; потім ранній userspace не знаходить потрібний модуль для сховища.
  • Збори DKMS можуть впливатися змінами інструментарію (gcc, make, binutils). «Оновлено ядро» іноді означає «також змінився компілятор».
  • Деякі вендори постачають попередньо зібрані модулі для певних версій ядра, але версії ядра Ubuntu змінюються; DKMS стає запасним планом — доки не перестане працювати.

Одна цитата, що пережила більше постмортемів, ніж заслуговує будь-хто один: «Надія — не стратегія.» — Gene Kranz. Вона застосовна і до перебудов DKMS.

Практичні завдання: команди, виводи та рішення (12+)

Це не «запустіть усе підряд». Це набір інструментів. Кожне завдання включає: команду, приклад виводу, що це означає і яке рішення прийняти.

Завдання 1: Підтвердити запущене ядро

cr0x@server:~$ uname -r
6.8.0-51-generic

Що це означає: Це ядро, яке зараз запущено. Якщо DKMS зламався під час встановлення новішого ядра, ви зазвичай можете виправити це без негайного простою, бо ви ще не використовуєте те нове ядро.

Рішення: Якщо запущене ядро — відоме робоче, перебудуйте DKMS для нового ядра зараз, а потім заплануйте контрольований перезавантаження пізніше.

Завдання 2: Переглянути встановлені ядра і що буде за замовчуванням при наступному перезавантаженні

cr0x@server:~$ dpkg -l 'linux-image-*generic' | awk '/^ii/{print $2,$3}'
linux-image-6.8.0-51-generic 6.8.0-51.52
linux-image-6.8.0-52-generic 6.8.0-52.53

Що це означає: У вас щонайменше два ядра встановлені; зазвичай найвища версія обирається при завантаженні.

Рішення: Визначте «цільове» ядро, для якого потрібно мати DKMS-модулі (тут: 6.8.0-52-generic).

Завдання 3: Перевірити статус DKMS по ядрах

cr0x@server:~$ dkms status
zfs/2.2.2, 6.8.0-51-generic, x86_64: installed
zfs/2.2.2, 6.8.0-52-generic, x86_64: built
nvidia/550.90.07, 6.8.0-51-generic, x86_64: installed
nvidia/550.90.07, 6.8.0-52-generic, x86_64: added

Що це означає: «installed» означає, що модуль зібраний і скопійований у /lib/modules/<kernel>. «built» — скомпільований, але може не бути встановленим. «added» — DKMS знає про модуль, але ще не будував його для цього ядра.

Рішення: Для цільового ядра все, що не «installed», — ризик. Збирайте й інсталюйте зараз.

Завдання 4: Перевірити, чи існують заголовки ядра для цільового ядра

cr0x@server:~$ dpkg -l | awk '/linux-headers-6.8.0-52-generic/{print $1,$2,$3}'
ii linux-headers-6.8.0-52-generic 6.8.0-52.53

Що це означає: DKMS потребує заголовків. Якщо їх бракує, DKMS провалиться з помилками на кшталт «Kernel headers for target not found».

Рішення: Якщо заголовки відсутні — встановіть їх перед перебудовою DKMS-модулів.

Завдання 5: Встановити відсутні заголовки (якщо потрібно)

cr0x@server:~$ sudo apt-get update
Hit:1 http://archive.ubuntu.com/ubuntu noble InRelease
Reading package lists... Done
cr0x@server:~$ sudo apt-get install -y linux-headers-6.8.0-52-generic
Reading package lists... Done
Building dependency tree... Done
The following NEW packages will be installed:
  linux-headers-6.8.0-52-generic
Setting up linux-headers-6.8.0-52-generic (6.8.0-52.53) ...

Що це означає: Заголовки тепер присутні; у DKMS з’явився реальний шанс.

Рішення: Перебудуйте DKMS-модулі для цільового ядра.

Завдання 6: Запустити DKMS autoinstall для цільового ядра

cr0x@server:~$ sudo dkms autoinstall -k 6.8.0-52-generic
Sign command: /lib/modules/6.8.0-52-generic/build/scripts/sign-file
Signing key: /var/lib/shim-signed/mok/MOK.priv
Public certificate (MOK): /var/lib/shim-signed/mok/MOK.der
Building module:
Cleaning build area... done.
Building module(s).... done.
Installing /lib/modules/6.8.0-52-generic/updates/dkms/zfs.ko
Installing /lib/modules/6.8.0-52-generic/updates/dkms/nvidia.ko
depmod... done.

Що це означає: DKMS зібрав і встановив модулі для цього конкретного ядра, а depmod оновив карти залежностей модулів.

Рішення: Якщо це пройшло успішно, переходьте до валідації: чи можна завантажити модуль (або принаймні чи він присутній і підписаний)?

Завдання 7: Якщо збірка впала — читайте лог DKMS уважно

cr0x@server:~$ sudo tail -n 40 /var/lib/dkms/nvidia/550.90.07/build/make.log
CONFTEST: drm_prime_pages_to_sg_has_drm_device_arg
CONFTEST: drm_gem_object_put_unlocked
error: implicit declaration of function ‘drm_gem_object_put_unlocked’
make[2]: *** [scripts/Makefile.build:243: /var/lib/dkms/nvidia/550.90.07/build/nvidia-drm/nvidia-drm-gem.o] Error 1
make[1]: *** [Makefile:1926: /var/lib/dkms/nvidia/550.90.07/build] Error 2
make: *** [Makefile:234: __sub-make] Error 2

Що це означає: Це помилка часу компіляції через невідповідність API. Це не відсутній пакет; це означає, що джерело модуля не підтримує це ядро.

Рішення: Перестаньте пробувати випадкові перебудови. Потрібна версія драйвера/модуля, сумісна з цим ядром (наприклад, оновити пакет NVIDIA), або завантажитись у старе ядро поки не буде сумісного драйвера.

Завдання 8: Перевірити наявність модуля для цільового ядра без перезавантаження

cr0x@server:~$ ls -l /lib/modules/6.8.0-52-generic/updates/dkms/ | egrep 'zfs|nvidia' | head
-rw-r--r-- 1 root root  8532480 Dec 29 10:12 nvidia.ko
-rw-r--r-- 1 root root 17362944 Dec 29 10:12 zfs.ko

Що це означає: Файли існують у місці, куди DKMS їх поміщає для цього ядра.

Рішення: Далі перевірте можливість завантаження та стан підпису (особливо при Secure Boot).

Завдання 9: Перевірити стан Secure Boot (детектор «зібрано, але заблоковано»)

cr0x@server:~$ mokutil --sb-state
SecureBoot enabled

Що це означає: Ядро застосовуватиме перевірку підпису модулів. Непідписані DKMS-модулі не будуть завантажені.

Рішення: Якщо Secure Boot увімкнено — забезпечте підпис модулів DKMS ключем, що занесено в довірені, або заплануйте процес MOK-реєстрації.

Завдання 10: Спробувати завантажити модуль на запущеному ядрі (тільки якщо безпечно)

cr0x@server:~$ sudo modprobe -v zfs
insmod /lib/modules/6.8.0-51-generic/updates/dkms/spl.ko
insmod /lib/modules/6.8.0-51-generic/updates/dkms/zfs.ko

Що це означає: На запущеному ядрі модуль завантажується. Це перевірка, що установка DKMS не зіпсована глобально.

Рішення: Якщо modprobe впадає з «Required key not available», у вас проблема з підписом Secure Boot. Якщо «Unknown symbol» — невідповідність ядро/модуль.

Завдання 11: Переглянути логи ядра на предмет помилок підпису або символів

cr0x@server:~$ sudo dmesg -T | tail -n 20
[Mon Dec 29 10:19:02 2025] Lockdown: modprobe: unsigned module loading is restricted; see man kernel_lockdown.7
[Mon Dec 29 10:19:02 2025] nvidia: module verification failed: signature and/or required key missing - tainting kernel

Що це означає: Secure Boot або політика lockdown блокує або позначає ядро. Деякі середовища толерують taint; деякі вважають це невідповідністю.

Рішення: Якщо ваша політика вимагає підписані модулі — виправте підпис і реєстрацію ключа зараз, до того як ви перезавантажитесь у ядро, яке відмовиться завантажити модуль зовсім.

Завдання 12: Перевірити, що initramfs перегенеровано для цільового ядра

cr0x@server:~$ ls -lh /boot/initrd.img-6.8.0-52-generic
-rw-r--r-- 1 root root 98M Dec 29 10:14 /boot/initrd.img-6.8.0-52-generic

Що це означає: Initramfs існує і було нещодавно оновлено, але це не гарантує, що він містить ваш модуль.

Рішення: Якщо модуль потрібен при завантаженні (ZFS root, HBA для сховища, особливий NIC) — обов’язково перевірте його присутність всередині initramfs.

Завдання 13: Підтвердити, що модуль є всередині initramfs (крок «довіряй, але перевіряй»)

cr0x@server:~$ lsinitramfs /boot/initrd.img-6.8.0-52-generic | egrep '/zfs\.ko|/nvidia\.ko' | head
usr/lib/modules/6.8.0-52-generic/updates/dkms/zfs.ko

Що це означає: ZFS включено в ранній userspace для цього ядра. Для GPU зазвичай не потрібно включати в initramfs; для сховища/мережі при завантаженні це може бути критично.

Рішення: Якщо відсутній — перегенеруйте initramfs після виправлення інсталяції DKMS.

Завдання 14: Перегенерувати initramfs для конкретного ядра (цільовий, не «розстрільний»)

cr0x@server:~$ sudo update-initramfs -u -k 6.8.0-52-generic
update-initramfs: Generating /boot/initrd.img-6.8.0-52-generic

Що це означає: Ви примусово згенерували initramfs для ядра, яке вас турбує.

Рішення: Знову прогляньте lsinitramfs; лише потім розглядайте перезавантаження.

Завдання 15: Переконатися, що карта залежностей модулів правильна для цільового ядра

cr0x@server:~$ sudo depmod -a 6.8.0-52-generic

Що це означає: modules.dep та інші файли оновлені. Деякі postinst скрипти виконують це; деякі відмови його пропускають. Запустити вручну — недорого і корисно.

Рішення: Якщо modprobe згодом скаржиться, що не може знайти залежності — швидше за все пропущено depmod або модулі опинилися в нестандартному шляху.

Завдання 16: Утримати оновлення ядра, поки стабілізуєтесь (опціонально, але часто розумно)

cr0x@server:~$ sudo apt-mark hold linux-image-generic linux-headers-generic
linux-image-generic set on hold.
linux-headers-generic set on hold.

Що це означає: Ви зупиняєте мета-пакети від витягування нових ядер автоматично.

Рішення: Використовуйте це під час інциденту. Знімайте холди, коли у вас буде відтворювана pipeline з DKMS та контроль перезавантажень.

Завдання 17: Підтвердити, яка буде стандартна запись завантаження (щоб не перезавантажитись у пастку)

cr0x@server:~$ grep -E 'GRUB_DEFAULT|GRUB_TIMEOUT|GRUB_SAVEDEFAULT' /etc/default/grub
GRUB_DEFAULT=0
GRUB_TIMEOUT=5

Що це означає: За замовчуванням обирається перший пункт меню, зазвичай найновіше ядро.

Рішення: Якщо найновіше ядро не має робочих модулів — або виправте DKMS для нього, або тимчасово налаштуйте GRUB на завантаження відомого робочого ядра.

Завдання 18: Знайти «напівналаштовані» пакети після некоректного оновлення

cr0x@server:~$ sudo dpkg --audit
The following packages are in a mess due to serious problems during installation. They must be reinstalled for them to work properly:
 linux-image-6.8.0-52-generic

Що це означає: Встановлення пакета ядра не завершилося коректно, що могло пропустити тригер DKMS і генерацію initramfs.

Рішення: Виправте стан пакування перш ніж нескінченно дебажити DKMS.

Завдання 19: Відновити стан пакетного менеджера і заново виконати postinst тригери

cr0x@server:~$ sudo apt-get -f install
Reading package lists... Done
Building dependency tree... Done
Correcting dependencies... Done
Setting up linux-image-6.8.0-52-generic (6.8.0-52.53) ...
update-initramfs: Generating /boot/initrd.img-6.8.0-52-generic

Що це означає: Пост-інсталяційні хуки для ядра виконалися. Це часто включає тригер DKMS на перебудову.

Рішення: Заново перевірте dkms status для цільового ядра; знову перевірте наявність модулів і вміст initramfs.

Жарт 1: DKMS — як абонемент у спортзал: ви помічаєте, що він не працює, лише коли намагаєтесь скористатися ним.

Відновлення драйверів без простоїв: стратегія, що працює

«Без простою» не означає магію. Це означає уникнути завантаження в ядро, що не може завантажити критичні модулі, і уникнути скидання обладнання під навантаженням. Для більшості інцидентів DKMS система досі працює на попередньому ядрі і все гаразд — до перезавантаження. Це ваше вікно.

Крок 1: Визначте, що означає «критичний драйвер» на цьому хості

Не всі DKMS-модулі однаково важливі. Відсутність VirtualBox-модуля на сервері дратує; відсутність модуля сховища на node з root-on-ZFS — катастрофа. Класифікуйте хост:

  • Критичний для сховища: ZFS root, ZFS data pools, HBA-драйвери, залежності dm-crypt.
  • Критичний для мережі: out-of-tree NIC-драйвери (рідко на Ubuntu, але трапляється), DPDK-модулі, SR-IOV стеки, вендорні offload-и.
  • Критичний для обчислень: NVIDIA GPU-ноди, ML-кластери, відеотранскодери.
  • «Непотрібно терміново»: робочі станції розробників та неважливі модулі.

Критичний означає: ніякого перезавантаження, поки цільове ядро не має верифікованого, завантажуваного модуля й адекватного initramfs.

Крок 2: Збирайте для ядра, в яке будете завантажуватись, а не для того, яке запущене

Конфігурації DKMS можуть вводити в оману. Якщо ви просто запустите dkms autoinstall без -k, воно часто орієнтується на запущене ядро. Це не те, що вам потрібно під час відновлення. Вам потрібне ядро наступного перезавантаження.

Завжди збирайте явного для цільової версії ядра.

Крок 3: Надавайте перевагу вендорським пакетам, що відстежують вашу лінію ядра

Коли DKMS-модуль не компілюється через несумісність API, у вас є дві реалістичні опції:

  • Оновити пакет драйвера/модуля до версії, сумісної з новим ядром.
  • Відтермінувати перезавантаження і зафіксувати версію ядра, поки не з’явиться сумісний драйвер.

Пробувати патчити джерела модуля прямо на продакшн-боксі о 2:00 — хобі, а не SRE-практика.

Крок 4: Валідируйте «чи можна завантажити» і «чи в initramfs»

Наявність на диску — недостатньо. Потрібне принаймні одне з:

  • Тест завантаження модуля на цільовому ядрі (важко без перезавантаження).
  • Перевірка підпису (якщо увімкнено Secure Boot).
  • Перевірка включення в initramfs для ранньо-завантажувальних модулів.

Практичний компроміс: ви перевіряєте шлях артефакта DKMS, запускаєте modinfo перевірки, перевіряєте стан підпису модулів і вміст initramfs. Потім перезавантажуєтесь у контрольованому вікні з відкатним ядром наготові.

Крок 5: Не ламайте свою мережу під час виправлення драйвера

Більшість відновлень DKMS навантажують CPU й диск, але не порушують трафік. Зона ризику — коли ви unload/reload модулі на живій системі. Якщо у вас немає резерву (bonding, multipath, кластеринг), уникайте перезавантаження мережевих/сховищних модулів на однонодовому критичному хості під час робочого часу.

Перебудова і інсталяція — безпечно. Вивантаження/завантаження — зміна.

Крок 6: Створіть «ворота перезавантаження»

У продакшені найпростіший контроль без простою — політика: не дозволяти перезавантажуватись, якщо DKMS-модулі не встановлені для найновішого встановленого ядра. Ви можете реалізувати це локальним скриптом, що перевіряє:

  • dkms status для цільового ядра показує «installed» для критичних модулів
  • lsinitramfs містить ранньо-завантажувальні модулі
  • mokutil --sb-state і стан підписів узгоджені

Підключіть це в процес змін. Нудно. Працює.

Secure Boot і підпис модулів (MOK): тихий зламник

Якщо ви запускаєте Ubuntu 24.04 на обладнанні з увімкненим Secure Boot — а багато організацій так роблять через політику комплаєнсу — DKMS може «успішно зібрати» і ви все одно втратите функціональність. Ось чому:

  • DKMS компілює модуль.
  • Ядро відмовляється його завантажити, якщо модуль неподписаний (або підписаний ключем, що не занесений у довірені).
  • Ви дізнаєтесь про це лише тоді, коли драйвер стане потрібним, зазвичай після перезавантаження.

Як швидко розпізнати помилки підпису Secure Boot

Типові симптоми:

  • modprobe: ERROR: could not insert '...': Required key not available
  • dmesg показує «module verification failed» або обмеження lockdown
  • dkms status каже «installed», але функціональність відсутня

Що робити (практичні опції)

  1. Підписуйте DKMS-модулі і реєструйте ключ (MOK). Це чисте рішення, якщо Secure Boot має залишатися увімкненим.
  2. Вимкнути Secure Boot у прошивці. Операційно найпростіше, але може порушити політику.
  3. Використовувати підписані in-tree драйвери, коли це можливо. Довгостроково найкраще, але не завжди доступно.

Перевірити, чи DKMS підписує модулі

cr0x@server:~$ sudo grep -R "sign-file" -n /etc/dkms /etc/modprobe.d 2>/dev/null | head

Що це означає: Може не бути явної конфігурації. В Ubuntu підпис модулів DKMS часто пов’язаний із shim/MOK інструментарієм і скриптами пакування.

Рішення: Якщо Secure Boot увімкнено і ви бачите помилки підпису — не гадати. Перевірте підпис модулів за допомогою modinfo.

Переглянути метадані підпису модуля

cr0x@server:~$ modinfo -F signer /lib/modules/6.8.0-52-generic/updates/dkms/zfs.ko
Canonical Ltd. Secure Boot Signing

Що це означає: Модуль має поле signer. Якщо порожнє, модуль може бути неподписаним (або метадані були видалені).

Рішення: Якщо signer відсутній і Secure Boot увімкнено — потрібно підписати і зареєструвати ключ, або прийняти, що модуль не завантажиться.

Перевірити зареєстровані ключі MOK

cr0x@server:~$ sudo mokutil --list-enrolled | head
[key 1]
SHA1 Fingerprint: 12:34:56:78:90:...
Subject: CN=Canonical Ltd. Secure Boot Signing

Що це означає: Система довіряє набору ключів. Якщо ваш підпис DKMS використовує інший ключ, ядро відхилить модуль.

Рішення: Узгодьте ключ підпису з зареєстрованими, або зареєструйте потрібний ключ через MOK (зазвичай це потребує перезавантаження в MOK manager).

Жарт 2: Secure Boot — це швейцар біля дверей ядра: ваш модуль може бути чудово одягнений і все одно не бути у списку дозволених.

initramfs, ранній завантажувальний етап і чому «зібрано» недостатньо

initramfs — це стиснений ранній userspace-образ, який ядро завантажує, щоб пройти шлях від «ядро запущено» до «маунт реального root-файлової системи». Якщо ваш критичний модуль не в initramfs, то наявність модуля на диску стає неважливою, бо диск може бути ще недоступний.

Це важливо для:

  • Систем з root-on-ZFS
  • Зашифрованого root, який потребує специфічних модулів на ранньому етапі
  • Деяких екзотичних потоків завантаження зі сховищ або по мережі

Режим відмови: DKMS встановив модулі, але initramfs згенеровано раніше

Це трапляється під час перерваних оновлень, паралельних операцій пакетного менеджера або коли DKMS запускається пізно, а initramfs — раніше. Ви перезавантажуєтесь і виявляєте, що ранній userspace не знаходить ZFS/SPL або драйвер сховища не присутній.

Виправлення: перегенеруйте initramfs після інсталяції DKMS для цільового ядра і перевірте вміст за допомогою lsinitramfs.

Режим відмови: кілька ядер, застарілий initramfs

Може бути так, що у вас є коректний initramfs для запущеного ядра, але немає для найновішого встановленого ядра. Так виникає пастка при перезавантаженні. Завжди перевіряйте initramfs, що відповідає ядрі, у яке ви плануєте завантажитися.

Три корпоративні міні-історії (реалістичні, анонімізовані)

Міні-історія 1: Інцидент через хибні припущення

У них був невеликий GPU-кластер для пакетного inference. Нічого екзотичного: хости на Ubuntu, NVIDIA DKMS-драйвер, планувальник задач і вікно змін по вівторках. Каденс оновлень був «ядро оновлюється автоматично, драйвери оновлюються коли хтось поскаржиться». Це працювало, поки не перестало.

Оновлення ядра прилетіло в п’ятницю ввечері через unattended-upgrades. Ніхто не помітив, бо ноди ще працювали на старому ядрі і GPU були доступні. Вранці в понеділок вони дренували одну ноду для планового обслуговування і перезавантажили її. Вона повернулась без завантажених модулів NVIDIA.

Хибне припущення було тонким: «якщо драйвер встановлено, то він встановлено». Вони ніколи не перевіряли, чи драйвер зібрався для щойно встановленого ядра. Нода перезавантажилась у найновіше ядро (як і повинна), а DKMS тихо провалився ще кілька днів тому.

Класичне виправлення — перевстановити пакет драйвера. Це не допомогло. Зрештою хтось подивився dmesg і знайшов повідомлення про примусову перевірку підпису Secure Boot. Secure Boot був увімкнений у прошивці після оновлення обладнання, але ніхто не оновив інструкцію.

Вирішення було простим — підпис і реєстрація ключа — але потребувало перезавантажень у MOK manager. Вони витратили день на координацію перезавантажень по нодах, чого можна було уникнути, якби мався pre-reboot gate і перевірка «DKMS встановлено для найновішого ядра».

Міні-історія 2: Оптимізація, що обернулась проти

Фінансова організація втомилась від повільних патчів. Вони вирішили «оптимізувати» і видалили інструменти збірки з продакшн-серверів: ні gcc, ні make, ні заголовків, мінімальний набір пакетів. Безпека це схвалила: образ став легшим, скани чистішими, і сервери виглядали як appliances.

Потім прийшло оновлення ядра. DKMS намагався перебудувати out-of-tree NIC-модуль, від якого вони залежали для специфічних функцій карти. Ні компілятора, ні заголовків, ні збірки. DKMS впав, але поточне ядро продовжувало працювати. Помилка залишалась непомітною.

Наступна хвиля перезавантажень відбулась під час планового обслуговування дата-центру. Декілька хостів запустились із новим ядром без NIC-модуля. Вбудований драйвер працював настільки, щоб пройти завантаження, але не мав offload-функцій, які вони підлаштували під свою латентність. Симптом не був «немає мережі». Він був гірший: періодичний колапс продуктивності і таймаути під навантаженням.

Вони скасували рішення про «мінімальний образ» для цього флоту і перенесли збірки DKMS у контрольований pipeline: передзбирати модулі для цільового ядра в підготовчому середовищі, доставити артефакти і верифікувати перед перезавантаженням. Оптимізація в принципі була слушною. Проте помилковою без заміни implicit вимоги DKMS на явний ланцюжок постачання модулів.

Урок: якщо ви видаляєте компілятори з хостів, ви берете на себе відповідальність за процес збірки модулів до кінця. Інакше ви просто відкладаєте відмову до часу перезавантаження.

Міні-історія 3: Скучно правильна практика, що врятувала ситуацію

Медіакомпанія керувала безліччю серверів зі сховищем, деякі з яких мали ZFS-пулі. Їхня практика була болісно нудною: після кожного оновлення ядра запускали автоматичну перевірку готовності до перезавантаження. Вона перевіряла статус DKMS для ZFS щодо найновішого встановленого ядра, перевіряла initramfs на наявність ZFS і переконувалась, що відоме робоче ядро залишається встановленим як опція відкату.

Одного ранку перевірка виявила помилку на підмножині хостів. DKMS показував ZFS «built», але не «installed» для найновішого ядра. Хости все ще працювали нормально, тож паніки не було. Вони заблокували перезавантаження через оркестратор і відкрили тікет.

Корінь проблеми — гонитва при пакуванні під час попереднього unattended-upgrade: генерація initramfs стала раніше, потім DKMS інсталяція впала і була повторно запущена, що лишило непослідовний стан. Скуча перевірка зловила це до перезавантаження. Вони виконали dkms autoinstall -k, перегенерували initramfs для цільового ядра і зняли блокування.

Ніякого простою, жодної драми, жодних вихідних. Ось як виглядає операційна досконалість, коли прибрати PowerPoint.

Поширені помилки: симптом → корінна причина → виправлення

1) Симптом: dkms status показує «added» для нового ядра

Корінна причина: DKMS зареєстрував модуль, але не зібрав його для цього ядра; відсутні заголовки або збірка раніше провалилась.

Виправлення: Встановіть заголовки для цільового ядра, потім запустіть sudo dkms autoinstall -k <kernel>. Перевірте файли під /lib/modules/<kernel>/updates/dkms.

2) Симптом: збірка DKMS впадає з «Kernel headers not found»

Корінна причина: Відсутній пакет linux-headers-<kernel>, або симлінк /lib/modules/<kernel>/build пошкоджено.

Виправлення: Встановіть відповідні заголовки; перевірте ls -l /lib/modules/<kernel>/build щоб переконатися, що він вказує на заголовки.

3) Симптом: Модуль збирається, але modprobe впадає з «Required key not available»

Корінна причина: Secure Boot увімкнено; модуль неподписаний або підписаний ключем, що не занесений у довірені.

Виправлення: Переконайтеся, що DKMS-модулі підписано довіреним ключем і зареєструйте його через MOK, або вимкніть Secure Boot, якщо політика дозволяє.

4) Симптом: Після завантаження в нове ядро втрачається ZFS/кореневе сховище

Корінна причина: initramfs для нового ядра не містить потрібних модулів, часто через часові розбіжності DKMS або збої postinst тригерів.

Виправлення: Після інсталяції DKMS запустіть update-initramfs -u -k <kernel>, потім підтвердьте вміст за допомогою lsinitramfs.

5) Симптом: Помилки компіляції DKMS про відсутні символи / неявні декларації

Корінна причина: Зміни в API ядра; версія драйвера несумісна з новим ядром.

Виправлення: Оновіть пакет драйвера/модуля (наприклад, нові версії NVIDIA/ZFS), або зафіксуйте ядро і завантажтесь у старе ядро, доки сумісні пакети не стануть доступні.

6) Симптом: Все виглядає встановленим, але апарат не працює після перезавантаження

Корінна причина: Ви зібрали для неправильної версії ядра (запущене ядро, а не найновіше встановлене), або завантажилось інше ядро, ніж очікувалося.

Виправлення: Підтвердіть встановлені ядра, перевірте вибір завантаження, перебудуйте явно для ядра, в яке будете завантажуватись, за допомогою dkms autoinstall -k.

7) Симптом: Оновлення пакетів зависають або лишають «напівналаштований» стан

Корінна причина: Перерване оновлення, блокування dpkg, заповнений FS, або збої postinst скриптів (часто DKMS).

Виправлення: Виправте стан dpkg: apt-get -f install, перевірте місце на диску і перезапустіть збірки DKMS після відновлення стану пакувального шару.

Чеклісти / покроковий план

Чекліст A: Відновлення без простою на хості, що ще працює на старому ядрі

  1. Визначте цільове ядро (найновіше встановлене): використайте dpkg -l для встановлених образів.
  2. Перевірте статус DKMS для критичних модулів щодо цього ядра: dkms status.
  3. Встановіть заголовки для цільового ядра, якщо їх бракує: apt-get install linux-headers-<kernel>.
  4. Перебудуйте модулі для цільового ядра: dkms autoinstall -k <kernel>.
  5. Перевірте наявні артефакти в /lib/modules/<kernel>/updates/dkms.
  6. Перевірка Secure Boot: mokutil --sb-state і підтвердіть signer модуля через modinfo.
  7. Перегенеруйте initramfs для цільового ядра (на хостах, критичних для сховища): update-initramfs -u -k <kernel>.
  8. Перевірте вміст initramfs: lsinitramfs містить потрібні модулі.
  9. Тримайте опцію відкату: переконайтесь, що старіше відоме робоче ядро встановлене.
  10. Заплануйте перезавантаження з планом відкату (доступ до консолі, вибір GRUB, віддалений персонал на місці при потребі).

Чекліст B: Якщо ви вже перезавантажились у зламане ядро

  1. Підтвердіть, що відсутнє: lsmod, modprobe і dmesg.
  2. Негайно перевірте Secure Boot; не марнуйте час на перебудову неподписаних модулів, якщо Secure Boot їх відкине.
  3. Встановіть необхідні засоби збірки тимчасово: заголовки, компілятор, інструменти, якщо DKMS їх потребує.
  4. Перебудуйте DKMS для запущеного ядра: dkms autoinstall -k $(uname -r).
  5. Якщо збірка впала через несумісність API: зупиніться і підберіть сумісну версію драйвера або відкатуйтесь до попереднього ядра через GRUB.
  6. Виправте initramfs, якщо задіяні ранні модулі, потім протестуйте перезавантаження.

Чекліст C: Запобігти цьому наступного разу (гігієна продакшена)

  1. Створіть «ворота перезавантаження», які перевіряють DKMS встановленим для найновішого ядра і верифікують initramfs там, де потрібно.
  2. Стейджіть оновлення ядра на канарних хостах з репрезентативним апаратним забезпеченням.
  3. Розглядайте політику Secure Boot як головний критерій, а не як нотатку BIOS.
  4. Тримайте принаймні одне відкатне ядро встановленим і завантажуваним завжди.
  5. Контролюйте unattended-upgrades, щоб ядра не мінялися без валідації.

FAQ

1) Чому DKMS «зламався» лише після оновлення ядра?

Тому що DKMS-модулі компілюються проти конкретних заголовків ядра. Коли ядро змінюється, модуль потрібно перебудувати. Якщо ця перебудова провалюється, ви не помітите цього, доки не завантажитесь у нове ядро або не спробуєте завантажити модуль для нього.

2) Чи можна виправити DKMS без перезавантаження?

Ви можете перебудувати і встановити модулі для наступного ядра без перезавантаження, так. Зазвичай ви не можете протестувати їх завантаження в тому наступному ядрі без фактичного перезавантаження. Саме тому важливо верифікувати артефакти, підписи і вміст initramfs перед перезавантаженням.

3) Що означає «added» vs «built» vs «installed» у dkms status?

added: DKMS знає про джерело модуля, але ще не будував його для цього ядра. built: скомпільовано, але не обов’язково встановлено в дерево модулів ядра. installed: поміщено в /lib/modules/<kernel> і, ймовірно, виконано depmod.

4) Чи дійсно потрібні точні заголовки ядра?

Так. DKMS збирається проти заголовків точної версії ядра, яку ви таргетуєте. «Достатньо близько» тут не працює; встановіть linux-headers-<exact-version>.

5) Чому Secure Boot ускладнює все так сильно?

Тому що він перетворює проблему на часі компіляції у проблему часу виконання. Ви можете успішно зібрати модуль і все одно не змогти його завантажити. Ядро відкине модулі, які не підписані довіреним ключем, коли Secure Boot та політики lockdown це вимагають.

6) Якщо Secure Boot увімкнено, чи варто вимикати його?

Лише якщо ваша політика це дозволяє. Вимкнення Secure Boot може бути найпростішим операційним шляхом, але правильне рішення в регульованому середовищі — підписувати DKMS-модулі ключем, який ви контролюєте, і зареєструвати його через MOK.

7) Чому система завантажилась, але потім сховище або мережа зламались?

Часто тому, що драйвер завантажується пізніше, ніж ви думаєте, або існує запасний in-tree драйвер, який працює частково, але без функціональності. Інша поширена причина: initramfs відсутній потрібний модуль для раннього завантаження, тому завантаження проходить частково, а потім пристрої з’являються пізніше або неправильно.

8) Який найнадійніший відкат, якщо не вдається зібрати DKMS для нового ядра?

Завантажте попереднє відоме робоче ядро і тимчасово зафіксуйте мета-пакети ядра. Потім оновіть пакет драйвера/модуля до версії, що підтримує нове ядро, перед наступною спробою перезавантаження.

9) Чи варто тримати компілятори поза продакшн-серверами?

Залежить від підходу. Якщо ви покладаєтесь на on-host збірки DKMS, вам потрібен інструментарій збірки і заголовки. Якщо ви їх видаляєте — ви маєте замінити on-host збірку DKMS на pipeline, який виробляє і доставляє сумісні модулі для кожного ядра, яке ви розгортаєте.

10) Як запобігти накопиченню «пасток перезавантаження» в майбутньому?

Додайте крок валідації після встановлення ядра, який перевіряє статус DKMS для критичних модулів на найновішому встановленому ядрі. Якщо перевірка провалюється — блокуйте автоматичні перезавантаження і підніміть алерт. Це дешевше, ніж реагувати на інцидент.

Наступні кроки, які ви можете виконати сьогодні

Якщо ви запускаєте Ubuntu 24.04 з драйверами, якими керує DKMS, припиніть ставитись до оновлень ядра як до «звичайних security-патчів». Це також події перебудови драйверів. Практичний шлях до відсутності простоїв короткий:

  1. Визначте критичні DKMS-модулі для ролі кожного хоста (сховище, мережа, GPU).
  2. Після кожної інсталяції ядра перебудовуйте модулі для найновішого встановленого ядра (dkms autoinstall -k).
  3. Перевіряйте підписи, якщо увімкнено Secure Boot; не припускайте, що успіх збірки означає успіх завантаження.
  4. Перегенеруйте і перевірте initramfs для модулів, які критичні на ранньому етапі завантаження.
  5. Лише після цього перезавантажуйтеся. Тримайте відкатне ядро встановленим і завантажуваним.

Зробіть це, і «DKMS зламався після оновлення ядра» перестане бути інцидентом. Це стане пунктом чеклісту, який виконується до того, як хтось щось помітить.

← Попередня
Ubuntu 24.04: Диск «повний», але df показує вільне — вичерпання inode пояснено (і виправлено)
Наступна →
Безпека VPN: 12 помилок, що перетворюють «приватний тунель» на інцидент

Залишити коментар