как собрать настраиваемый initramfs


Initrd (initramfs) — это временная файловая система, используемая ядром Linux для начальной загрузки. Обычно, туда помещают набор утилит, init, а также драйвера для монтирования корневой файловой системы. Изначально использовалась концепция создания маленькой файловой системы initrd, например ext2, которая загружалась в память и продолжала загрузку основной системы, но начиная с версии ядра 2.6 пришли к понятию initramfs. Это, обычно сжатый cpio архив, в котором располагается мини-система busybox, которая выполняет ту же роль, что и initrd

Расскажу свое мнение для чего может пригодится помещать всю систему в initramfs.

Во-первых, например, у вас нет жесткого диска и вы хотите загружаться по сети, яркий пример — тонкий клиент. Тогда вся система, помещенная в initrd — хороший выбор.

Или же вы просто хотите поместить всю систему в память, чтоб она быстро работала, при этом вам не важно, сохранятся ли ваши изменения после перезагрузки.

Еще вариант — вы хотите проделать некоторую работу до начала загрузки, тогда вы помещаете все нужные скрипты и программы в initramfs.

Для создания индивидуального образа initramfs нужно подготовить слепок корневой файловой системы. Рассмотрим это на примере Debian, для систем семейства Red Hat, вам потребуется утилита febootstrap

Устанавливаем multistrap. Это очень удобная программа для установки Debian в заданную директорию. Документация по ней находится здесь

sudo apt-get install multistrap

Теперь нужно подготовить конфиг с описанием системы, которую мы установим. На этом этапе желательно выбрать необходимые пакеты для установки ну и, саму версию Debian, а также архитектуру.

Вот пример моего конфига, надеюсь названия опций говорят сами за себя.

[General]
arch=amd64
directory=/tmp/linram/root
cleanup=true
noauth=true
unpack=true
aptsources=Grip Updates
debootstrap=Debian

[Debian]
packages=vim ssh e2fsprogs parted python mdadm screen iproute net-tools isc-dhcp-client netcat-openbsd less telnet zip unzip kmod lsof strace resolvconf curl ifupdown sysstat nmap tcpdump ngrep ftp gnupg cryptsetup lynx lftp dmsetup lvm2 testdisk lzop iptables
source=http://ftp.ru.debian.org/debian
keyring=debian-archive-keyring
suite=stable

Подготовим директорию, назовем ее linram, а внутри нее root, в которой будет находиться корень создаваемой системы initramfs.

mkdir -p /tmp/linram/root
vim /tmp/linram/bootstrap.conf

В bootstrap.conf поместим конфиг, приведенный выше.

В конфиге я выбрал архитектуру (amd64), нужные мне пакеты, указал ссылку на зеркало и директорию, куда будет установлен образ системы.

Подмонтируем dev, proc в новосозданную директорию

mkdir -p /tmp/linram/root/{proc,dev}
sudo mount -o bind /dev /tmp/linram/root/dev
sudo mount -o bind /proc /tmp/linram/root/proc

Дальше дело за малым — запустить multistrap, чтоб он выполнил свою работу.

sudo multistrap -f /tmp/linram/bootstrap.conf

Подождем окончания установки и обнаружим, что наша система готова, она располагается в /tmp/linram/root.

Можно зачрутится в неё для точечных изменений.

sudo chroot /tmp/linram/root

Удалим рутовый пароль

passwd -d

Изменим хостнейм. Кстати, процедура изменения описана в этой статье

echo 'new-hostname' > /etc/hostname

Не забудем отмонтировать dev и proc

sudo umount -l /tmp/linram/root/dev
sudo umount -l /tmp/linram/root/proc

После того, как мы внесли все изменения, создадим initramfs из нашей директории root.

Воспользуемся вот таким скриптом. Если вы хотите изменить алгоритм сжатия, советую lz4, как один из самых быстрых.

#!/bin/bash
cd root
echo "Creating initramfs"
find . | cpio -H newc -o | gzip > ../initramfs.gz
cd ..

Перейдем в директорию /tmp/linram/

cd /tmp/linram/

создадим его и запустим на исполнение.

vim mkinitramfs.sh
bash mkinitramfs.sh

Initramfs появится в /tmp/linram/ с именем initramfs.gz

Теперь нужно убедиться, что ядро, с которым будем подгружать этот initramfs, поддерживает загрузку initramfs и выбранный алгоритм сжатия.

Для примера возьмем текущее ядро.

grep CONFIG_BLK_DEV_INITRD /boot/config-$(uname -r)
CONFIG_BLK_DEV_INITRD=y
grep GZIP /boot/config-$(uname -r)
CONFIG_HAVE_KERNEL_GZIP=y
# CONFIG_KERNEL_GZIP is not set
CONFIG_RD_GZIP=y
CONFIG_DECOMPRESS_GZIP=y

Все поддерживается, отлично.

Можно запустить виртуальную машину, чтоб протестировать получившийся initramfs.

qemu-system-x86_64 -enable-kvm -m 1024M -kernel /boot/vmlinuz-$(uname-r) -initrd /tmp/linram/initramfs.gz

Если при загрузке появляются ошибки, скорей всего, не хватает оперативной памяти для размещения распакованной системы.

Если понадобится распаковать initramfs.gz, то вот скрипт.

#!/bin/bash
cd root
gzip -dc ../initramfs.gz | cpio -id
cd ..

Удачных сборок.