Что такое initramfs и почему без него система не находит собственный диск
Сервер не грузится, и на экране одна строка: Gave up waiting for root device или ALERT! /dev/mapper/... does not exist. Диск на месте, ядро свежее, конфиг GRUB не трогали — а система упорно не находит собственный корневой раздел. Почти всегда причина в одном и том же месте: initramfs либо отсутствует, либо не знает про реальную конфигурацию диска. Разберёмся, зачем вообще нужен этот промежуточный слой и почему без него ядро оказывается в тупике курицы и яйца.
Содержание
- Курица и яйцо: ядру нужен диск, чтобы найти диск
- Что реально лежит внутри initramfs
- Как initramfs собирается: dracut, initramfs-tools, mkinitcpio
- Путь загрузки: от GRUB до переключения на настоящий корень
- Почему без initramfs или с устаревшим initramfs загрузка ломается
- Диагностика: что смотреть, когда загрузка встала на этом этапе
Курица и яйцо: ядру нужен диск, чтобы найти диск
Когда GRUB передаёт управление ядру Linux, у ядра есть образ самого себя, немного памяти и адрес, где искать корневую файловую систему — обычно в виде параметра root=UUID=... или root=/dev/sda1. Дальше начинается проблема.
Если раздел — простой ext4 на одиночном SATA-диске с давно известным контроллером, ядро может справиться само: базовые драйверы дисковых контроллеров нередко вкомпилированы прямо в ядро. Но на практике конфигурация диска почти никогда не бывает такой плоской:
- корень лежит на программном RAID (mdadm) — нужен модуль
raid1/raid10/md_modи утилита, которая соберёт массив из отдельных дисков в один блочное устройство; - корень — логический том LVM — нужны модули
dm_mod,dm-raidи userspace-утилитыlvm2, которые активируют volume group и найдут в ней нужный logical volume; - диск зашифрован LUKS — нужен модуль
dm-crypt, утилитаcryptsetupи способ спросить у вас пароль (или прочитать ключ с другого носителя) ещё до того, как загрузилась обычная система (подробнее о том, что именно защищает такое шифрование — в статье про шифрование дисков); - контроллер — не банальный AHCI, а аппаратный RAID или NVMe со специфичным драйвером, которого может не быть в минимальном наборе, вкомпилированном в ядро.
Во всех этих случаях ядру, чтобы прочитать корневой раздел, сначала нужен код — драйверы контроллера, модуль dm-crypt, утилиты LVM, — а этот код по-хорошему тоже должен откуда-то загружаться. Причём именно с диска, на который ядро пока попасть не может. Это и есть петля курицы и яйца: чтобы смонтировать диск, нужны инструменты, а инструменты обычно живут на диске.
Разорвать петлю позволяет отдельный, временный, минимальный набор файлов, который грузится в оперативную память вместе с ядром, ещё до того, как речь вообще заходит о «настоящей» файловой системе. Это и есть initramfs.
Что реально лежит внутри initramfs
initramfs (initial RAM filesystem) — это сжатый архив cpio, который загрузчик (GRUB) кладёт в память рядом с ядром и передаёт ядру как второй аргумент, отдельно от самого образа ядра. Ядро распаковывает этот архив прямо в память и монтирует его как временную корневую файловую систему — ещё до обращения к реальному диску.
Внутри — не полноценный дистрибутив, а ровно то, что нужно для одной конкретной задачи: собрать доступ к реальному корню и передать управление дальше. Типичное содержимое:
- минимальный
/init— скрипт или бинарник, который выполняется первым и оркестрирует весь процесс; - модули ядра под конкретное железо и конфигурацию диска этой машины: драйвер контроллера,
raid456.ko,dm-crypt.ko,dm-mod.koи так далее; - статически собранные или использующие свои библиотеки утилиты:
mdadm,lvm,cryptsetup,blkid,udevadm; - busybox или похожий набор базовых команд оболочки — на случай, если что-то пойдёт не так и потребуется аварийный shell;
- udev-правила и небольшой набор конфигов, скопированных с хост-системы:
/etc/mdadm/mdadm.conf,/etc/lvm/lvm.conf,/etc/crypttab.
Важный нюанс: initramfs не универсален и не одинаков для всех машин. Он генерируется индивидуально под конкретный сервер, с учётом того, какие модули ядра и какие конфиги реально нужны именно этой машине с её конкретным набором дисков. Именно поэтому initramfs с одного сервера почти никогда нельзя просто скопировать на другой с иной схемой дисков — набор модулей и конфигов внутри может не совпасть.
Стоит отличать initramfs от более старого термина initrd. Исторически initrd был отдельным блочным образом файловой системы (ext2 в файле), который ядро монтировало как настоящее блочное устройство в памяти. initramfs проще: это архив cpio, распаковываемый прямо в tmpfs средствами самого ядра, без эмуляции блочного устройства. Современные дистрибутивы используют именно initramfs, но по привычке файлы часто всё ещё называют initrd.img-* — это просто имя файла, а не признак старого механизма.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверКак initramfs собирается: dracut, initramfs-tools, mkinitcpio
За генерацию initramfs отвечает не сам initramfs, а отдельная система сборки, которая запускается на уже работающей системе — обычно после установки или обновления ядра.
В экосистеме Debian/Ubuntu это initramfs-tools, команда update-initramfs:
# пересобрать initramfs под текущее ядро
update-initramfs -u -k $(uname -r)
# пересобрать под все установленные ядра
update-initramfs -u -k all
# посмотреть, что реально попало внутрь
lsinitramfs /boot/initrd.img-$(uname -r) | less
lsinitramfs /boot/initrd.img-$(uname -r) | grep -E 'raid|dm-|crypt'
В RHEL/CentOS/Fedora и их производных — dracut:
dracut --force /boot/initramfs-$(uname -r).img $(uname -r)
# посмотреть содержимое собранного образа
lsinitrd /boot/initramfs-$(uname -r).img | grep -E 'md|lvm|crypt'
В Arch Linux — mkinitcpio, который читает список хуков из /etc/mkinitcpio.conf (параметр HOOKS=) и по нему определяет, какие модули и утилиты класть в образ:
mkinitcpio -P
Общий принцип у всех трёх систем одинаковый: сборщик смотрит на текущую систему — какие модули ядра сейчас загружены, что написано в /etc/fstab, /etc/crypttab, /etc/mdadm/mdadm.conf, /etc/lvm/lvm.conf — и упаковывает в initramfs ровно то, что, по его мнению, понадобится при следующей загрузке. Это ключевая деталь для следующего раздела: initramfs — это снимок конфигурации на момент сборки, а не что-то, что автоматически подстраивается под изменения задним числом.
Путь загрузки: от GRUB до переключения на настоящий корень
Чтобы понять, где именно initramfs встраивается в последовательность загрузки, полезно пройти её по шагам:
- GRUB читает свой конфиг, находит записи
linuxиinitrdдля выбранного пункта меню и загружает в память два файла: образ ядра и образ initramfs. - GRUB передаёт управление ядру вместе со строкой параметров (
cat /proc/cmdlineпосле загрузки покажет, что там было) — в том числеroot=UUID=..., которая говорит ядру, куда нужно попасть в итоге (откуда вообще берётся этот UUID и как устроены разделы диска — в статье про разметку диска). - Ядро инициализирует базовые структуры, находит переданный initramfs в памяти и распаковывает его как временную корневую файловую систему (tmpfs).
- Управление передаётся
/initвнутри initramfs. Именно этот скрипт, а не ядро напрямую, дальше определяет судьбу загрузки. /initподгружает нужные модули ядра под это железо, запускает udev, чтобы устройства/dev/*появились, и по порядку собирает то, что требуется: активирует RAID черезmdadm --assemble(детали сборки и замены дисков в массиве — в статье про mdadm на практике), поднимает LVM черезvgchange -ay, при необходимости спрашивает пароль и расшифровывает раздел черезcryptsetup luksOpen.- Когда после всех этих шагов путь, указанный в
root=, наконец существует и доступен как обычное блочное устройство,/initмонтирует его во временную точку. - Выполняется
switch_root(современный аналогpivot_rootдля случая initramfs на tmpfs) — временная корневая файловая система из памяти заменяется на настоящую, размонтируется, а управление передаётся/sbin/initуже на реальном диске — как правило, это systemd, и дальше начинается уже отдельная история про то, как systemd поднимает сервисы при загрузке.
Всё, что происходит до шага 7, — целиком забота initramfs. Реальная система, её сервисы, её systemd-юниты в этой части ещё вообще не участвуют — их для ядра просто не существует, пока не выполнен переход.
Почему без initramfs или с устаревшим initramfs загрузка ломается
Возможны, по сути, два разных сценария поломки, и их полезно различать, потому что чинятся они по-разному.
Initramfs отсутствует или GRUB его не подключил. Тогда ядро остаётся один на один с сырым root=, без модулей и утилит для его сборки. Если корень — простой раздел на давно известном контроллере, ядро иногда всё же справляется. Если нет — вы увидите что-то вроде VFS: Unable to mount root fs on unknown-block(0,0) или зависание с Gave up waiting for root device. Такое бывает, если initramfs случайно не был указан в конфиге GRUB после ручной правки, или файл образа пропал/повредился.
Initramfs есть, но устарел относительно реальной конфигурации диска. Это встречается чаще и обманчивее — ошибка выглядит так же, но initramfs при этом «валидный» файл, просто собранный под другую ситуацию. Типичные причины:
- диск переносили в другой массив/пул или меняли UUID, а initramfs всё ещё ссылается на старый
/etc/lvm/lvm.confили/etc/mdadm/mdadm.confс прежним составом; - систему перевели на LUKS-шифрование или, наоборот, включили LVM поверх уже установленной системы, но initramfs не пересобрали — новый механизм добавления слоя просто не попал в набор модулей;
- ядро обновили, а initramfs для нового
uname -rне сгенерировался (частая ситуация при ручной установке ядра без hook'а пакетного менеджера, который обычно делает это автоматически); - поменяли контроллер диска (например, при переезде на другое железо или другой тип виртуализации) на такой, чей драйвер не был включён в initramfs, собранный на старом железе.
Итог во всех этих случаях одинаковый: /init внутри initramfs пытается собрать то, что он умеет собирать по своим старым инструкциям, не находит устройство по ожидаемому пути и в лучшем случае падает в аварийный shell initramfs с подсказкой (initramfs), а в худшем — просто виснет на попытке дождаться устройства, которое никогда не появится.
Из этого следует практическое правило: initramfs нужно пересобирать при любом изменении дисковой конфигурации, а не только при обновлении ядра — добавили шифрование, изменили состав RAID, перешли на LVM, сменили контроллер — везде нужен update-initramfs -u (или аналог для вашего дистрибутива) после изменения.
Диагностика: что смотреть, когда загрузка встала на этом этапе
Если сервер завис между GRUB и появлением обычного логина, а на экране мелькают сообщения про root device, порядок действий такой.
Если у вас есть доступ к аварийному shell initramfs ((initramfs)# в консоли), можно диагностировать прямо там:
# что вообще видит ядро из блочных устройств
ls /dev/sd* /dev/nvme* /dev/mapper/* 2>/dev/null
# что говорит udev о найденных дисках
blkid
# для RAID — собрался ли массив
cat /proc/mdstat
mdadm --assemble --scan
# для LVM — видны ли volume group
vgscan
vgchange -ay
lvs
# для LUKS — есть ли зашифрованное устройство и удаётся ли открыть
cryptsetup luksOpen /dev/sdaX имя_тома
Если оболочка initramfs говорит, что нужного устройства просто нет и модуль не грузится — значит, дело действительно в устаревшем или неполном образе, и решать нужно уже с работающей системы (например, загрузившись с LiveCD/rescue-режима, смонтировав реальный корень и выполнив chroot в него):
mount /dev/mapper/vg-root /mnt
mount /dev/sda1 /mnt/boot
for d in proc sys dev; do mount --bind /$d /mnt/$d; done
chroot /mnt /bin/bash
update-initramfs -u -k all
После этого стоит явно проверить, что новый образ содержит нужные модули, а не полагаться на то, что пересборка сама всё исправила:
lsinitramfs /boot/initrd.img-$(uname -r) | grep -E 'dm-crypt|raid|lvm'
Если строк нет — значит, конфиги, на которые опирается сборщик (/etc/crypttab, /etc/mdadm/mdadm.conf, /etc/lvm/lvm.conf), сами не отражают реальность, и правку нужно начинать с них, а не с самого initramfs.
Отдельно стоит проверить конфиг GRUB — initramfs может быть идеально собран, но GRUB может ссылаться на файл со старым именем, если ядро обновлялось вручную:
grep -E '^linux|^initrd' /boot/grub/grub.cfg | head -20
update-grub # Debian/Ubuntu
grub2-mkconfig -o /boot/grub2/grub.cfg # RHEL-подобные
Если у вас арендованный VPS или выделенный сервер и обычный доступ к консоли недоступен, для таких случаев обычно предусмотрен rescue-режим панели управления — он загружает независимую минимальную систему в обход диска сервера, и уже из неё можно смонтировать реальные разделы и выполнить chroot тем же способом, что описан выше.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
Почему initramfs не пересобирается автоматически при изменении LVM или RAID?
Потому что сборщик initramfs не следит за системой в реальном времени — он читает конфигурацию только в момент явного запуска (обычно как hook пакетного менеджера при обновлении ядра). Изменения в составе RAID, добавление шифрования или перенос на LVM не запускают такой hook автоматически, поэтому пересборку нужно выполнять руками после подобных изменений.
Чем initramfs отличается от initrd на практике, если файл всё равно называется initrd.img?
Название файла — это только историческое наследие, механизм внутри современный: cpio-архив, распаковываемый в tmpfs, а не отдельный блочный образ файловой системы, который нужно монтировать через loop-устройство, как было в старом initrd.
Можно ли загрузиться вообще без initramfs, если корень — простой раздел без RAID, LVM и шифрования?
В принципе да, если нужные драйверы вкомпилированы прямо в ядро, а не собраны как модули. На практике большинство дистрибутивных ядер собирают многое как загружаемые модули, поэтому initramfs используется почти всегда, даже для простых конфигураций — это унифицирует процесс загрузки и упрощает поддержку разного железа одним и тем же ядром.
Как понять, что проблема именно в initramfs, а не в самом диске или GRUB?
Если /proc/mdstat, blkid или vgs, запущенные из аварийного shell initramfs, видят диск и его разделы корректно, но /init всё равно не может собрать нужное устройство — дело в конфигурации initramfs. Если же и низкоуровневые команды не видят диск вообще, стоит сначала проверить физическое подключение диска и вывод dmesg на ошибки контроллера — это уже не про initramfs.
Нужно ли пересобирать initramfs при простом обновлении пакетов без смены ядра?
Обычно нет — initramfs привязан к конкретной версии ядра (uname -r), и для уже установленных версий он не меняется автоматически при обновлении других пакетов. Исключение — если обновился сам пакет, отвечающий за конкретный драйвер или утилиту внутри initramfs (например, новая версия cryptsetup с изменённым форматом): в такой ситуации разумно пересобрать образ вручную, чтобы не разойтись версиями между системой и тем, что лежит в initramfs.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →