Grub - Debian автоматическая загрузка при сбое 1 диска в RAID массиве

Материал из support.qbpro.ru

Для Debian Stretch:

  • Открываем скрипт:
mcedit /usr/share/initramfs-tools/scripts/local-block/mdadm
  • Заменяем параметр --assemble на --incremental
#!/bin/sh

PREREQ="multipath"

prereqs()
{
        echo "$PREREQ"
}

case $1 in
# get pre-requisites
prereqs)
        prereqs
        exit 0
        ;;
esac

. /scripts/functions

# Poor man's mdadm-last-resort@.timer
# That kicks in 2/3rds into the ROOTDELAY

if [ ! -f /run/count.mdadm.initrd ]
then
    COUNT=0

    # Unfortunately raid personalities can be registered _after_ block
    # devices have already been added, and their rules processed, try
    # triggering again.  See #830770
    udevadm trigger --action=add -s block || true
    wait_for_udev 10
else
    COUNT=$(cat /run/count.mdadm.initrd)
fi
COUNT=$((COUNT + 1))

echo $COUNT > /run/count.mdadm.initrd

# Run pure assemble command, even though we default to incremental
# assembly it is supported for users to export variables via
# param.conf such as IMSM_NO_PLATFORM.  See #830300
mdadm -q --incremental --scan --no-degraded || true

MAX=30
if [ ${ROOTDELAY:-0} -gt $MAX ]; then
    MAX=$ROOTDELAY
fi
MAX=$((MAX*2/3))

if [ "$COUNT" = "$MAX" ]
then
    # Poor man's mdadm-last-resort@.service for incremental devices
    mdadm -q --run /dev/md?*

    # And last try for all others
    mdadm -q --incremental --scan --run

    rm -f /run/count.mdadm.initrd
fi

exit 0

  • Обновляем образ initramfs.
update-initramfs -kall -u


Для Debian Jessie:

Для Debian 8.6 данная статья уже не очень актуальна, т.к. там всё уже грузится "из коробки", даже при деградированном массиве с загрузочным разделом, однако я оставлю нижеследующий текст в исторических целях, да и мало ли где ещё такая проблема всплывёт, плюс часть о собственно восстановлении массивов по-прежнему актуальна, хотя это в общем-то элементарная вещь, легко находимая гуглом.

В последней (восьмой на момент написания статьи) версии Debian восстановление развалившегося загрузочного software-raid-массива, как оказалось - дело не совсем тривиальное. Когда-то давно, во времена первого GRUB-а - компьютер спокойно загружался при отсутствии части дисков в массиве, однако в 7 и 8 версиях Debian - что-то сломали. Система выдаёт примерно такое: ALERT /dev/disks/by-uuid/куча-разных-кракозябликов does not exist.

Dropping to a shell!

Мне, если честно, лень искать что именно и где там изменилось в поведении mdadm и в загрузочных скриптах. Однако факт остаётся фактом - если в процессе загрузки какой-либо из массивов окажется в деградированном состоянии - этот массив будет неактивен, и если он нужен для загрузки - операционка просто не стартует, выдав вместо этого командную строку busybox, а там возможность что-то исправить - крайне ограничена. И если восстановить массивы на загрузившейся системе - человек, не имеющий серьёзного опыта настройки linux ещё сможет (нагуглить про sfdisk и "магические" mdadm -r / mdadm -a не сложно), то встретившись с куцым busybox, в котором из текстовых редакторов только vi (а он в неумелых руках лишь бибикает и всё портит) - ему не останется ничего иного, кроме как вызванивать вас вечером в субботу. А это, согласитесь, не очень приятно :).

Поэтому распишу вкратце, во-первых, о том, что стоит сразу же подшаманить в установленном на программный raid Debian-е, во-вторых - как это дело быстро восстановить. Здесь не будет ничего о том, как устанавливать систему на raid или как перевести существующую. Кроме того, крайне рекомендуется помнить о том, что манипуляции с raid и дисками могут привести к необратимой потере данных, поэтому убедитесь, что для всего важного есть бекап.

Первым делом - подшаманим загрузочный скрипт. Это позволит системе загружаться даже с деградировавшего массива.

nano -w /usr/share/initramfs-tools/scripts/local-top/mdadm

Открываем файл /usr/share/initramfs-tools/scripts/local-top/mdadm, находим там все вхождения --assemble и заменяем их на --incremental - скорее всего, это нужно будет сделать в двух строчках. Обновляем образ initramfs.

update-initramfs -kall -u

Опции означают, что обновляются образы для всех имеющихся версий ядра (-kall), в том числе те, которые уже существуют (-u).

Теперь, даже если массив деградировал - система всё равно загрузится полностью, что значительно упрощает разбивку и подключение к raid нового жёсткого диска. Однако если вы в эту ситуацию уже попали - проще будет загрузиться с чего-то навроде SystemRescueCD и либо поправить загрузочный скрипт и образ initramfs с помощью chroot, либо прямо из загруженной спасательной системы восстанавливать raid-массивы. Возможно, подобное поведение Debian - не бага а фича, т.е. так и задумано - мол, если raid развалился - не трогать его во-избежание, и пусть юзверь занимается камасутрой с busybox, вероятно это действительно где-то оправдано... однако raid - всё равно не backup, а главная его задача - обеспечение бесперебойной работы, поэтому ценность подобной фичи - имхо крайне сомнительна.

Дальше - важно, чтобы загрузчик (по умолчанию в Debian используется GRUB) был установлен на все загрузочные жёсткие диски. Предположим, у вас два жёстких диска, на которых расположена корневая файловая система вместе с /boot и лежит это всё в виде зеркалки - raid1. По-умолчанию, если в таком виде всё изначально устанавливалось - инсталлятор debian установит GRUB только на один жёсткий диск. Поэтому имеет смысл повторить установку для обоих жёстких дисков - выполнить от root-а примерно такие команды:

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

Здесь /dev/sda и /dev/sdb - ваши два диска. В результате система будет загружаться с любого из имеющихся дисков. Если система даже после этих мер не грузится - проверьте настройки BIOS, не пытается ли он грузиться с какого-нибудь флоппика? Подобное тоже бывает в некоторых материнках после удаления одного из дисков (приоритет в загрузке для оставшегося диска оказывается ниже, чем DVD-привода, например).

Теперь перейдём к восстановлению. Допустим, у нас два одинаковых по объёму жёстких диска, на которых в raid1 работают два массива - md0 и md1. На md1 у нас лежит swap (оно нужно на случай умирания диска в процессе работы, чтобы запущенным процессам не стало плохо при обращении к сбойной странице памяти). На md0 - корневая файловая система с /boot и всеми остальными файлами. Т.е. предельно упрощённый вариант, без всяческих выделений под /boot или /home отдельных разделов. Допустим, диски у нас обозначаются /dev/sda и /dev/sdb. И вот, работал себе /dev/sdb, работал... и внезапно умер. Печальный итог его жизни. В случае если вы не подшаманили скрипт загрузки - теперь при попытке стартовать система будет выдавать вышеприведённый ALERT и выкидываться в busybox. С подшаманенным же скриптом - система, скорее всего, загрузится. Если вы не настроили никаких действий и уведомлений на сбой raid - вы о проблеме с диском можете даже не узнать, но настройка уведомлений - выходит за рамки этой статьи. Чтобы проверить состояние raid-а вручную - достаточно выполнить вот такую команду:

cat /proc/mdstat

Или посмотреть содержимое файлика любым другим способом. В файле будет что-то примерно такое:

md0 : active raid1 sda1[1]
      2926528 blocks super 1.2 [2/2] [_U]

md1 : active raid1 sda2[1]
      5855168 blocks super 1.2 [2/2] [_U]

Здесь для каждого массива перечислены оставшиеся в массиве разделы (как видно, расположенные на sda) + видно, что из двух разделов в массиве работает только один - в норме в квадратных скобках было бы написано [UU].

Итак, диск умер, но raid жив. Отключаем компьютер. Достаём где-нибудь новый (или выдранный из потрохов другого компа) винчестер такого-же или бОльшего размера. Подключаем его на место умершего. Включаем комп и тут же лезем в BIOS - нужно убедиться, что загрузка пойдёт с выжившего старого винта, а не с только что добавленного. Загружаем операцинку. Теперь нужно удалить разделы на новом жёстком диске (если имеются) и заново разбить его - так, чтобы /dev/sdb1 и /dev/sdb2 совпадали по размерам с /dev/sda1 и /dev/sda2 соответственно. Можно сделать это с помощью fdisk. Можно воспользоваться графическим gparted. Кто-то сделает это webmin-ом. Выбор за вами. Меня больше всего устраивает parted. Вызываем его и смотрим, что есть на дисках.

root@testserver:~# parted
GNU Parted 3.2
Using /dev/sda
Welcome to GNU Parted! Type 'help' to view a list of commands.
(parted) unit s
(parted) print /dev/sda
Model: ATA ST3802110AS (scsi)
Disk /dev/sda: 156299375s
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags:

Number  Start      End         Size        Type     File system  Flags
 1      2048s      5859327s    5857280s    primary               boot, raid
 2      5859328s   17577983s   11718656s   primary               raid

(parted) print /dev/sdb
Model: ATA ST3802110AS (scsi)
Disk /dev/sda: 156299375s
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags:

(parted)

Красным цветом - обозначены команды, введённые пользователем. Итак, у нас два диска по 80 гиг, на /dev/sda - разделы raid-а, на /dev/sdb - пусто. Команда unit s заставляет parted показывать размеры и смещения в секторах, в противном случае - parted показывает эти цифры в человеко-читаемой и усреднённой форме (типа 7,45GB), установить по которым точное количество байт не представляется возможным. Значения в секторах удобнее тем, что один сектор по умолчанию равен 512 байтам (см. строку Sector size в выводе parted). Строчка "Using /dev/sda" означает, что отданные пользователем команды по умолчанию будут применяться к диску /dev/sda. Нас это не устраивает. Поступаем следующим образом:

(parted) select /dev/sdb
Using /dev/sdb

Теперь команды будут применяться ко второму диску. На оном, как видно - уже есть таблица разделов типа msdos. Если бы её не было - пришлось бы создавать командой mklabel. Этим же способом можно быстро удалить старую таблицу разделов, если там сейчас что-то старое и не нужное.

(parted) mklabel msdos

Теперь, когда диск пуст и таблица разделов создана - создаём два новых раздела с теми же размерами, какие видно на первом диске.

(parted) mkpart primary 2048s 5859327s
(parted) set 1 lba off
(parted) set 1 raid on
(parted) set 1 boot on
(parted) mkpart primary 5859328s 17577983s
(parted) set 2 lba off
(parted) set 2 raid on
(parted) print /dev/sdb
Model: ATA MAXTOR STM380215 (scsi)
Disk /dev/sdb: 156299375s
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags:

Number  Start      End         Size        Type     File system  Flags
 1      2048s      5859327s    5857280s    primary               boot, raid
 2      5859328s   17577983s   11718656s   primary               raid

(parted)

Как видно, размеры указываются в секторах - такие же, какие видны на /dev/sda. Команды set на разделы - включают и отключают нужные и ненужные флаги - например, флаг lba ставится по-умолчанию, но он нам особо не нужен, в то же время нужен флаг raid и флаг boot для загрузочного раздела. Теперь можно восстановить деградировавшие массивы. Это весьма просто:

mdadm /dev/md0 -a /dev/sdb1
mdadm /dev/md1 -a /dev/sdb2
cat /proc/mdstat

Последняя команда должна вывести информацию по массивам, в которых будет что-то вроде прогрессбара (полоски с процентами) для процесса восстановления. Эпизодически посматривая содержимое /proc/mdstat можно отслеживать этот процесс. Либо можно делать это в реальном времени примерно такой командой:

watch -n 1 cat /proc/mdstat

Команда будет выводить содержимое файла на экран раз в секунду.

ИСТОЧНИКИ