evgen@spb: ~/2026/07/grub-na-mdadm-raid-legacy-bios/

GRUB на программном RAID: как не остаться без загрузки при вылете диска

Проблема, которую замечают слишком поздно

Собрали зеркало на mdadm, поставили систему, всё красиво: /dev/md0 в статусе clean, оба диска на месте. Через полгода первый диск умирает — и сервер не грузится вообще. Массив цел, данные целы, но BIOS не находит, с чего стартовать.

Причина простая: mdadm работает на уровне блочного устройства, а загрузчик живёт вне его. MBR — это первые 512 байт физического диска, они не входят в RAID-раздел и не реплицируются. Если GRUB был установлен только на /dev/sda, то на /dev/sdb в MBR лежат нули.

Ниже — как сделать правильно и как чинить, если уже поздно.

Базовый вариант

В Legacy/BIOS-режиме GRUB ставится в MBR каждого диска массива по отдельности:

grub-install --target=i386-pc --recheck /dev/sda
grub-install --target=i386-pc --recheck /dev/sdb
update-grub

Ключевой момент: аргументом идёт физический диск/dev/sda, а не /dev/md0 и не раздел /dev/sda1. Попытка установить загрузчик на md-устройство либо завершится ошибкой, либо (что хуже) отработает не так, как вы ожидаете.

Правильный вариант для Debian и Ubuntu

Ручной grub-install — разовое действие. При очередном обновлении пакета grub-pc система переустановит загрузчик только на те диски, которые записаны в debconf. Поэтому вместо ручного вызова используем:

dpkg-reconfigure grub-pc

В диалоге пробелом отмечаем все диски массива. После этого каждое обновление GRUB будет автоматически раскатываться на оба диска.

Проверить текущее состояние и задать значение неинтерактивно (пригодится в Puppet, Ansible или в скрипте развёртывания):

debconf-show grub-pc | grep install_devices

echo 'grub-pc grub-pc/install_devices multiselect /dev/disk/by-id/ata-XXXX,/dev/disk/by-id/ata-YYYY' \
  | debconf-set-selections

Обратите внимание на /dev/disk/by-id/. Имена вида sda/sdb не гарантированы: смена контроллера, добавление диска или просто другой порядок инициализации ядра — и sdb станет sdc. Загрузчик после этого поедет не туда, куда вы думали.

Требования к массиву, на котором лежит /boot

Уровень RAID

Для раздела с /bootRAID1. Формально GRUB в BIOS-режиме умеет читать RAID5/6/10 через свои модули, но это лишний слой хрупкости в самом критичном месте загрузки. Классическая схема: небольшой отдельный /boot на зеркале, всё остальное — на любом уровне, хоть на RAID10, хоть поверх LVM.

Версия метаданных

Метаданные 1.2 работают — GRUB подхватывает их модулем mdraid1x. Но суперблок при этом лежит в начале раздела, то есть BIOS видит там не файловую систему, а служебную структуру mdadm.

Максимально безопасный вариант для /boot — метаданные 0.90 или 1.0: суперблок пишется в конец раздела, и с точки зрения любого стороннего загрузчика раздел выглядит как обычный ext2/ext4. Это тот случай, когда «устаревший» формат объективно надёжнее.

mdadm --create /dev/md1 --level=1 --raid-devices=2 \
      --metadata=1.0 /dev/sda1 /dev/sdb1

Флаги и служебные разделы

  • Раздел с /boot должен иметь флаг boot в MBR-таблице.
  • Если диски размечены в GPT, но загрузка идёт через BIOS — на каждом диске нужен BIOS boot partition размером около 1 МБ, тип EF02. Без него grub-install просто откажется работать: между GPT-заголовком и первым разделом нет места под core.img.
sgdisk -n1:2048:+1M -t1:EF02 /dev/sdb

Именно на этом шаге чаще всего спотыкаются при добавлении нового диска в существующий массив: разделы скопировали через sgdisk --backup/--load-backup, а вот grub-install на новый диск выполнить забыли.

Восстановление из live-системы

Сценарий: диск вылетел, сервер не грузится. Загружаемся с любого live-образа и собираем массив вручную.

# Собрать все найденные массивы
mdadm --assemble --scan
cat /proc/mdstat

# Смонтировать корень и /boot
mount /dev/md0 /mnt
mount /dev/md1 /mnt/boot          # если /boot вынесен отдельно

# Пробросить служебные ФС
for i in dev dev/pts proc sys run; do mount --bind /$i /mnt/$i; done

chroot /mnt

Дальше — внутри chroot:

grub-install /dev/sda
grub-install /dev/sdb
update-grub

# Зафиксировать конфигурацию массива и пересобрать initramfs
mdadm --detail --scan >> /etc/mdadm/mdadm.conf
update-initramfs -u

Строку mdadm --detail --scan в конфиг стоит добавлять осознанно — проверьте, что там не появился дубликат ARRAY со старым UUID. Пересборка initramfs обязательна: без актуального mdadm.conf внутри initramfs ядро может собрать массив под другим именем (/dev/md127 — классика жанра) и не найти корень.

Проверка

Убедиться, что GRUB реально лежит в MBR обоих дисков:

dd if=/dev/sda bs=512 count=1 2>/dev/null | strings | grep -i grub
dd if=/dev/sdb bs=512 count=1 2>/dev/null | strings | grep -i grub

Обе команды должны что-то вывести. Если вторая молчит — загрузчика на диске нет.

Но настоящая проверка одна: физически отключить первый диск и попробовать загрузиться. Всё остальное — косвенные признаки. Пятнадцать минут даунтайма в удобное вам время стоят дешевле, чем выяснение этого вопроса в три часа ночи.

Заодно проверьте настройки BIOS/UEFI: порядок загрузки должен включать оба диска, иначе при вылете первого сервер честно упрётся в «No bootable device», имея рабочий загрузчик на втором.

Чек-лист

  1. grub-install выполнен на каждый физический диск массива.
  2. В Debian/Ubuntu все диски отмечены в dpkg-reconfigure grub-pc, устройства указаны через /dev/disk/by-id/.
  3. /boot — на RAID1, метаданные 1.0 или 0.90.
  4. Для GPT + BIOS на каждом диске есть раздел EF02.
  5. /etc/mdadm/mdadm.conf актуален, initramfs пересобран.
  6. В BIOS в списке загрузки присутствуют все диски.
  7. Загрузка с отключённым первым диском проверена вживую.

Пункт 7 не опционален. Резервный загрузчик, который никто не проверял, — это не резервный загрузчик, а предположение.

evgen@spb: ~/contacts
evgen@spbping -c1 evgen.info
64 bytes from evgen.info: отвечу в течение рабочего дня
evgen@spbcat contacts.txt
mail      ya@evgen.info
telegram  @EvgenOne
github    github.com/onegin
blog      evgen.info/blog
evgen@spbecho $ЗАЧЕМ_ПИСАТЬ
интересная инфраструктурная задача · вопрос по Proxmox или Icinga ·
желание обсудить, почему memtest молчал, а память была битая
evgen@spb
© 2026 Евгений Подолинский · Санкт-Петербург
синий здесь – не тот, о котором вы подумали.