среда, 15 сентября 2010 г.

Настройка программного RAID1 на работающей системе

В этой статье описывается настройка RAID1-массива на уже установленном и запущенном Debian etch/lenny с конфигурацией загрузчика GRUB для корректной загрузки системы даже в том случае, если один из винчестеров поврежден.

Предварительные замечания

Все действия описаны для Debian etch/lenny, с двумя жесткими дисками одинакового размера: /dev/sda и /dev/sdb. /dev/sdb пока не используется, /dev/sda размечен следующим образом:
  • /dev/sda1 - /boot, файловая система ext3
  • /dev/sda2 - swap
  • /dev/sda3 - /, файловая система ext3
В итоге мы хотим получить следующую конфигурацию:
  • /dev/md0 (составлен из /dev/sda1 и /dev/sdb1) - /boot, ext3
  • /dev/md1 (составлен из /dev/sda2 и /dev/sdb2) - swap
  • /dev/md2 (составлен из /dev/sda3 и /dev/sdb3) - /, ext3
Текущая ситуация выглядит следующим образом:
server1:~# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/sda3 4.4G 729M 3.4G 18% /
tmpfs 126M 0 126M 0% /lib/init/rw
udev 10M 56K 10M 1% /dev
tmpfs 126M 0 126M 0% /dev/shm
/dev/sda1 137M 12M 118M 10% /boot
server1:~# fdisk -l
Disk /dev/sda: 5368 MB, 5368709120 bytes
255 heads, 63 sectors/track, 652 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Device Boot Start End Blocks Id System
/dev/sda1 * 1 18 144553+ 83 Linux
/dev/sda2 19 80 498015 82 Linux swap / Solaris
/dev/sda3 81 652 4594590 83 Linux

Disk /dev/sdb: 5368 MB, 5368709120 bytes
255 heads, 63 sectors/track, 652 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes

Disk /dev/sdb doesn't contain a valid partition table

Установка mdadm

mdadm - это утилита для построения программных RAID-массивов. Установите ее командой
# apt-get install initramfs-tools mdadm
Вам будет задан следующий вопрос:
MD arrays needed for the root filesystem <- all
Затем подгрузите необходимые модули ядра (чтобы избежать перезагрузки):
# modprobe md
# modprobe linear
# modprobe multipath
# modprobe raid0
# modprobe raid1
# modprobe raid5
# modprobe raid6
# modprobe raid10
И выполните команду
# cat /proc/mdstat
Вывод должен быть примерно следующим:
server1:~# cat /proc/mdstat
Personalities : [linear] [multipath] [raid0] [raid1] [raid6] [raid5] [raid4] [raid10]
unused devices:

Подготовка /dev/sdb

Для создания RAID1 нам необходимо подготовить второй жесткий диск (/dev/sdb), скопировать на него все данные с /dev/sda и добавить его в массив.

Сначала скопируем таблицу разделов
server1:~# sfdisk -d /dev/sda | sfdisk /dev/sdb
Checking that no-one is using this disk right now ...
OK

Disk /dev/sdb: 652 cylinders, 255 heads, 63 sectors/track

sfdisk: ERROR: sector 0 does not have an msdos signature
/dev/sdb: unrecognized partition table type
Old situation:
No partitions found
New situation:
Units = sectors of 512 bytes, counting from 0

Device Boot Start End #sectors Id System
/dev/sdb1 * 63 289169 289107 83 Linux
/dev/sdb2 289170 1285199 996030 82 Linux swap / Solaris
/dev/sdb3 1285200 10474379 9189180 83 Linux
/dev/sdb4 0 - 0 0 Empty
Successfully wrote the new partition table

Re-reading the partition table ...

If you created or changed a DOS partition, /dev/foo7, say, then use dd(1)
to zero the first 512 bytes: dd if=/dev/zero of=/dev/foo7 bs=512 count=1
(See fdisk(8).)
Проверим, что оба диска имеют одинаковую таблицу:
server1:~# fdisk -l

Disk /dev/sda: 5368 MB, 5368709120 bytes
255 heads, 63 sectors/track, 652 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes

Device Boot Start End Blocks Id System
/dev/sda1 * 1 18 144553+ 83 Linux
/dev/sda2 19 80 498015 82 Linux swap / Solaris
/dev/sda3 81 652 4594590 83 Linux

Disk /dev/sdb: 5368 MB, 5368709120 bytes
255 heads, 63 sectors/track, 652 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes

Device Boot Start End Blocks Id System
/dev/sdb1 * 1 18 144553+ 83 Linux
/dev/sdb2 19 80 498015 82 Linux swap / Solaris
/dev/sdb3 81 652 4594590 83 Linux
Теперь изменим тип разделов на втором жестком диске на Linux raid autodetect
server1:~# fdisk /dev/sdb

Command (m for help): <-- t
Partition number (1-4): <-- 1
Hex code (type L to list codes): <-- fd
Changed system type of partition 1 to fd (Linux raid autodetect)

Command (m for help): <-- t
Partition number (1-4): <-- 2
Hex code (type L to list codes): <-- fd
Changed system type of partition 2 to fd (Linux raid autodetect)

Command (m for help): <-- t
Partition number (1-4): <-- 3
Hex code (type L to list codes): <-- fd
Changed system type of partition 3 to fd (Linux raid autodetect)

Command (m for help): <-- w
The partition table has been altered!
Calling ioctl() to re-read partition table. Syncing disks.
Чтобы быть уверенным, что на /dev/sdb не осталось никаких следов от возможных предыдущих установок RAID-массивов, выполните следующие команды:
# mdadm --zero-superblock /dev/sdb1
# mdadm --zero-superblock /dev/sdb2
# mdadm --zero-superblock /dev/sdb3
Если никаких остатков предыдущих установок RAID не обнаружится, то каждая из приведенных выше команд mdadm выдаст ошибку (не надо беспокоиться) примерно следующего вида:
server1:~# mdadm --zero-superblock /dev/sdb1
mdadm: Unrecognised md component device - /dev/sdb1
В противном случае никакого вывода не будет.

Создание RAID-массива

Пришло время для создания самих массивов: /dev/md0, /dev/md1, и /dev/md2. /dev/sdb1 будет добавлен в /dev/md0, /dev/sdb2 в /dev/md1 и /dev/sdb3 в /dev/md2. Разделы на первом диске мы пока не трогаем, так как с него загружена система. Мы будем использовать указатель missing при создании массива:
# mdadm --create /dev/md0 --level=1 --raid-disks=2 missing /dev/sdb1
# mdadm --create /dev/md1 --level=1 --raid-disks=2 missing /dev/sdb2
# mdadm --create /dev/md2 --level=1 --raid-disks=2 missing /dev/sdb3
Проверка состояния нашего массива должна показать, что у нас есть три поврежденных RAID-массива ([_U] или [U_] означает, что массив поврежден, а [UU] означает, что все в порядке):
server1:~# cat /proc/mdstat
Personalities : [raid1] [linear] [multipath] [raid0] [raid6] [raid5] [raid4] [raid10]
md2 : active raid1 sdb3[1]
4594496 blocks [2/1] [_U]

md1 : active raid1 sdb2[1]
497920 blocks [2/1] [_U]

md0 : active raid1 sdb1[1]
144448 blocks [2/1] [_U]

unused devices:
Теперь создадим файловые системы на массивах
# mkfs.ext3 /dev/md0
# mkswap /dev/md1
# mkfs.ext3 /dev/md2
и отредактируем конфигурационный файл /etc/mdadm/mdadm.conf
# cp /etc/mdadm/mdadm.conf /etc/mdadm/mdadm.conf_orig
# mdadm --examine --scan >> /etc/mdadm/mdadm.conf
Он должен выглядеть примерно так (в последних строках расположена информация о наших массивах):
# cat /etc/mdadm/mdadm.conf

DEVICE partitions
CREATE owner=root group=disk mode=0660 auto=yes

HOMEHOST

MAILADDR root

ARRAY /dev/md0 level=raid1 num-devices=2 UUID=72d23d35:35d103e3:01b5209e:be9ff10aARRAY /dev/md1 level=raid1 num-devices=2 UUID=a50c4299:9e19f9e4:01b5209e:be9ff10a
ARRAY /dev/md2 level=raid1 num-devices=2 UUID=99fee3a5:ae381162:01b5209e:be9ff10a
Подготовка и перенос данных
Смонтируем массивы (swap монтировать, естественно, не надо):
# mkdir /mnt/md0
# mkdir /mnt/md2
# mount /dev/md0 /mnt/md0
# mount /dev/md2 /mnt/md2
и отредактируем файлы /etc/fstab и /etc/mtab. Заменим /dev/sda1 на /dev/md0 , /dev/sda2 на /dev/md1 и /dev/sda3 на /dev/md2, чтобы эти файлы приняли следующий вид:
# cat /etc/fstab
proc /proc proc defaults 0 0
/dev/md2 / ext3 defaults,errors=remount-ro 0 1
/dev/md0 /boot ext3 defaults 0 2
/dev/md1 none swap sw 0 0
/dev/hdc /media/cdrom0 udf,iso9660 user,noauto 0 0
/dev/fd0 /media/floppy0 auto rw,user,noauto 0 0

# cat /etc/mtab
/dev/md2 / ext3 rw,errors=remount-ro 0 0
tmpfs /lib/init/rw tmpfs rw,nosuid,mode=0755 0 0
proc /proc proc rw,noexec,nosuid,nodev 0 0
sysfs /sys sysfs rw,noexec,nosuid,nodev 0 0
udev /dev tmpfs rw,mode=0755 0 0
tmpfs /dev/shm tmpfs rw,nosuid,nodev 0 0
devpts /dev/pts devpts rw,noexec,nosuid,gid=5,mode=620 0 0
/dev/md0 /boot ext3 rw 0 0
Пришло время для настройки GRUB. Откройте файл /boot/grub/menu.lst и добавьте опцию fallback сразу после default
[...]
default 0
fallback 1
[...]
Это значит, что если первое ядро (нумерация начинается с нуля) не сможет загрузиться, то будет загружено следующее в списке.

В конце этого файла расположены блоки, описывающие параметры ядер для загрузки. Скопируйте первый блок, замените в копии root=/dev/sda3 на root=/dev/md2 и root (hd0,0) на root (hd1,0), после чего поставьте полученный блок первым в списке. После редактирования файл должен выглядеть примерно так:
[...]
## ## End Default Options ##

title Debian GNU/Linux, kernel 2.6.18-4-486 RAID (hd1)
root (hd1,0)
kernel /vmlinuz-2.6.18-4-486 root=/dev/md2 ro
initrd /initrd.img-2.6.18-4-486
savedefault

title Debian GNU/Linux, kernel 2.6.18-4-486
root (hd0,0)
kernel /vmlinuz-2.6.18-4-486 root=/dev/sda3 ro
initrd /initrd.img-2.6.18-4-486
savedefault

title Debian GNU/Linux, kernel 2.6.18-4-486 (single-user mode)
root (hd0,0)
kernel /vmlinuz-2.6.18-4-486 root=/dev/sda3 ro single
initrd /initrd.img-2.6.18-4-486
savedefault

### END DEBIAN AUTOMAGIC KERNELS LIST
root (hd1,0) ссылается на диск /dev/sdb, который уже входит в RAID-массив. Вскоре мы будем перезагружать систему, при этом система попытается загрузиться с нашего (все еще поврежденного) массива /dev/md2. В случае неудачи загрузка продолжится со следующего по списку раздела /dev/sda (-> fallback 1).

Теперь обновим RAM-диск
# update-initramfs -u
И скопируем данные на /dev/sdb
# cp -dpRx / /mnt/md2
# cd /boot
# cp -dpRx . /mnt/md0

Настройка GRUB

Теперь необходимо установить загрузчик на второй винчестер. Все последующие команды выполняются в оболочке GRUB (она запускается командой grub):
grub> root (hd0,0)
Filesystem type is ext2fs, partition type 0x83

grub> setup (hd0)
Checking if "/boot/grub/stage1" exists... no Checking if "/grub/stage1" exists... yes Checking if "/grub/stage2" exists... yes Checking if "/grub/e2fs_stage1_5" exists... yes Running "embed /grub/e2fs_stage1_5 (hd0)"... 15 sectors are embedded. succeeded Running "install /grub/stage1 (hd0) (hd0)1+15 p (hd0,0)/grub/stage2 /grub/menu.lst"... succeeded Done.

grub> root (hd1,0)
Filesystem type is ext2fs, partition type 0xfd

grub> setup (hd1)
Checking if "/boot/grub/stage1" exists... no Checking if "/grub/stage1" exists... yes Checking if "/grub/stage2" exists... yes Checking if "/grub/e2fs_stage1_5" exists... yes Running "embed /grub/e2fs_stage1_5 (hd1)"... 15 sectors are embedded. succeeded Running "install /grub/stage1 (hd1) (hd1)1+15 p (hd1,0)/grub/stage2 /grub/menu.lst"... succeeded Done.

grub> quit
После этих действий возвращаемся в оболочку, выполняем перезагрузку
# reboot
и надеемся, что наша система загрузится с RAID-массива :)

Подготовка /dev/sda

Если все прошло нормально, то вы должны увидеть /dev/md0 и /dev/md2 в выводе команды df -h
server1:~# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/md2 4.4G 730M 3.4G 18% /
tmpfs 126M 0 126M 0% /lib/init/rw
udev 10M 68K 10M 1% /dev
tmpfs 126M 0 126M 0% /dev/shm
/dev/md0 137M 17M 114M 13% /boot
Вывод cat /proc/mdstat должен быть примерно таким:
server1:~# cat /proc/mdstat
Personalities : [raid1]
md2 : active raid1 sdb3[1]
4594496 blocks [2/1] [_U]

md1 : active raid1 sdb2[1]
497920 blocks [2/1] [_U]

md0 : active raid1 sdb1[1]
144448 blocks [2/1] [_U]

unused devices:
Теперь изменим тип разделов на /dev/sda на Linux raid autodetect
server1:~# fdisk /dev/sda

Command (m for help): <-- t
Partition number (1-4): <-- 1
Hex code (type L to list codes): <-- fd
Changed system type of partition 1 to fd (Linux raid autodetect)

Command (m for help): <-- t
Partition number (1-4): <-- 2
Hex code (type L to list codes): <-- fd
Changed system type of partition 2 to fd (Linux raid autodetect)

Command (m for help): <-- t
Partition number (1-4): <-- 3
Hex code (type L to list codes): <-- fd
Changed system type of partition 3 to fd (Linux raid autodetect)

Command (m for help): <-- w
The partition table has been altered!
Calling ioctl() to re-read partition table.
WARNING: Re-reading the partition table failed with error 16: Device or resource busy. The kernel still uses the old table. The new table will be used at the next reboot. Syncing disks.
Добавим /dev/sda1, /dev/sda2 и /dev/sda3 в RAID-массив
# mdadm --add /dev/md0 /dev/sda1
# mdadm --add /dev/md1 /dev/sda2
# mdadm --add /dev/md2 /dev/sda3
И проверим состояние массива. Вы должны увидеть, что идет процесс синхронизации
server1:~# cat /proc/mdstat
Personalities : [raid1]
md2 : active raid1 sda3[2] sdb3[1]
4594496 blocks [2/1] [_U] [=====>...............] recovery = 29.7% (1367040/4594496) finish=0.6min speed=85440K/sec
md1 : active raid1 sda2[0] sdb2[1]
497920 blocks [2/2] [UU]
md0 : active raid1 sda1[0] sdb1[1]
144448 blocks [2/2] [UU]
unused devices:
(Вы можете запустить watch cat /proc/mdstat для наблюдения за ходом процесса. Выход из watch осуществляется нажатием CTRL+C.)

Дождитесь окончания процесса синхронизации, после чего состояние массива должно выглядеть примерно так:
server1:~# cat /proc/mdstat
Personalities : [raid1]
md2 : active raid1 sda3[0] sdb3[1]
4594496 blocks [2/2] [UU]

md1 : active raid1 sda2[0] sdb2[1]
497920 blocks [2/2] [UU]

md0 : active raid1 sda1[0] sdb1[1]
144448 blocks [2/2] [UU]

unused devices:
Затем отредактируем /etc/mdadm/mdadm.conf, чтобы он соотвествовал новой ситуации.
# cp /etc/mdadm/mdadm.conf_orig /etc/mdadm/mdadm.conf
# mdadm --examine --scan >> /etc/mdadm/mdadm.conf
Теперь он выглядит так:
DEVICE partitions
CREATE owner=root group=disk mode=0660 auto=yes
HOMEHOST
MAILADDR root
ARRAY /dev/md0 level=raid1 num-devices=2 UUID=72d23d35:35d103e3:2b3d68b9:a903a704
ARRAY /dev/md1 level=raid1 num-devices=2 UUID=a50c4299:9e19f9e4:2b3d68b9:a903a704
ARRAY /dev/md2 level=raid1 num-devices=2 UUID=99fee3a5:ae381162:2b3d68b9:a903a704

Настройка GRUB (Часть 2)

Почти все готово. Теперь отредактируем /boot/grub/menu.lst. На данный момент GRUB настроен на загрузку с /dev/sdb (hd1,0). Конечно же, мы все еще хотим, чтобы система грузилась, если /dev/sdb содержит какие-то ошибки. Создадаим копию первого блока с описанием параметров загрузки (в котором описан hd1), вставим ее ниже и заменим в этом блоке hd1 на hd0. Остальные блоки закомментируем. Теперь конфиг загрузчика должен выглядеть примерно так:
[...]
## ## End Default Options ##

title Debian GNU/Linux, kernel 2.6.18-4-486 RAID (hd1)
root (hd1,0)
kernel /vmlinuz-2.6.18-4-486 root=/dev/md2 ro
initrd /initrd.img-2.6.18-4-486
savedefault

title Debian GNU/Linux, kernel 2.6.18-4-486 RAID (hd0)
root (hd0,0)
kernel /vmlinuz-2.6.18-4-486 root=/dev/md2 ro
initrd /initrd.img-2.6.18-4-486
savedefault

#title Debian GNU/Linux, kernel 2.6.18-4-486
#root (hd0,0)
#kernel /vmlinuz-2.6.18-4-486 root=/dev/sda3 ro
#initrd /initrd.img-2.6.18-4-486
#savedefault

#title Debian GNU/Linux, kernel 2.6.18-4-486 (single-user mode)
#root (hd0,0)
#kernel /vmlinuz-2.6.18-4-486 root=/dev/sda3 ro single
#initrd /initrd.img-2.6.18-4-486
#savedefault

### END DEBIAN AUTOMAGIC KERNELS LIST
В строке, начинающейся с kopt замените /dev/sda3 на /dev/md2
НЕ УДАЛЯЙТЕ символ # из начала строки!!!
[...]
# kopt=root=/dev/md2 ro
[...]
Обновляем RAM-диск и перезагружаемся:
# update-initramfs -u
# reboot
Загрузка должна пройти без проблем:

Все работает, мы только что настроили программный RAID-массив первого уровня на работающей системе.

Тестирование

Давайте попробуем сэмулировать сбой жесткого диска. Абсолютно неважно, как ой из дисков вы выберите для эксперимента. Я выбрал /dev/sdb
Для эмуляции сбоя необходимо либо остановить систему и физически удалить второй винчестер (/dev/sdb) из компьютера, либо сэмулировать это на программном уровне:
# mdadm --manage /dev/md0 --fail /dev/sdb1
# mdadm --manage /dev/md1 --fail /dev/sdb2
# mdadm --manage /dev/md2 --fail /dev/sdb3

# mdadm --manage /dev/md0 --remove /dev/sdb1
# mdadm --manage /dev/md1 --remove /dev/sdb2
# mdadm --manage /dev/md2 --remove /dev/sdb3
Выключите компьютер. Если вы физически удаляли винчестер, то поместите на его место новый. Загрузка должна пройти без проблем.

Посмотрим статус нашего массива:
server1:~# cat /proc/mdstat
Personalities : [raid1]
md2 : active raid1 sda3[0]
4594496 blocks [2/1] [U_]

md1 : active raid1 sda2[0]
497920 blocks [2/1] [U_]

md0 : active raid1 sda1[0]
144448 blocks [2/1] [U_]

unused devices:
Видно, что массив опять поврежден.

Состояние разделов должно быть примерно следующим:
server1:~# fdisk -l

Disk /dev/sda: 5368 MB, 5368709120 bytes
255 heads, 63 sectors/track, 652 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes

Device Boot Start End Blocks Id System
/dev/sda1 * 1 18 144553+ fd Linux raid autodetect
/dev/sda2 19 80 498015 fd Linux raid autodetect
/dev/sda3 81 652 4594590 fd Linux raid autodetect

Disk /dev/sdb: 5368 MB, 5368709120 bytes
255 heads, 63 sectors/track, 652 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes

Disk /dev/sdb doesn't contain a valid partition table

Disk /dev/md0: 147 MB, 147914752 bytes
2 heads, 4 sectors/track, 36112 cylinders
Units = cylinders of 8 * 512 = 4096 bytes

Disk /dev/md0 doesn't contain a valid partition table

Disk /dev/md1: 509 MB, 509870080 bytes
2 heads, 4 sectors/track, 124480 cylinders
Units = cylinders of 8 * 512 = 4096 bytes

Disk /dev/md1 doesn't contain a valid partition table

Disk /dev/md2: 4704 MB, 4704763904 bytes
2 heads, 4 sectors/track, 1148624 cylinders
Units = cylinders of 8 * 512 = 4096 bytes

Disk /dev/md2 doesn't contain a valid partition table
Теперь скопируем таблицу разделов с /dev/sda на /dev/sdb (В случае ошибок попробуйте опцию --force)
server1:~# sfdisk -d /dev/sda | sfdisk /dev/sdb

Checking that no-one is using this disk right now ...
OK

Disk /dev/sdb: 652 cylinders, 255 heads, 63 sectors/track

sfdisk: ERROR: sector 0 does not have an msdos signature
/dev/sdb: unrecognized partition table type
Old situation:
No partitions found
New situation:
Units = sectors of 512 bytes, counting from 0

Device Boot Start End #sectors Id System
/dev/sdb1 * 63 289169 289107 fd Linux raid autodetect
/dev/sdb2 289170 1285199 996030 fd Linux raid autodetect
/dev/sdb3 1285200 10474379 9189180 fd Linux raid autodetect
/dev/sdb4 0 - 0 0 Empty
Successfully wrote the new partition table

Re-reading the partition table ...

If you created or changed a DOS partition, /dev/foo7, say, then use dd(1)
to zero the first 512 bytes: dd if=/dev/zero of=/dev/foo7 bs=512 count=1
(See fdisk(8).)
Удаляем с /dev/sdb предыдущие установки RAID
# mdadm --zero-superblock /dev/sdb1
# mdadm --zero-superblock /dev/sdb2
# mdadm --zero-superblock /dev/sdb3
... и добавляем /dev/sdb в массив:
# mdadm -a /dev/md0 /dev/sdb1
# mdadm -a /dev/md1 /dev/sdb2
# mdadm -a /dev/md2 /dev/sdb3
Если посмотреть на статус массива, то мы увидим знакомый процесс синхронизации
server1:~# cat /proc/mdstat

Personalities : [raid1]
md2 : active raid1 sdb3[2] sda3[0]
4594496 blocks [2/1] [U_] [======>..............] recovery = 30.8% (1416256/4594496) finish=0.6min speed=83309K/sec
md1 : active raid1 sdb2[1] sda2[0]
497920 blocks [2/2] [UU]
md0 : active raid1 sdb1[1] sda1[0]
144448 blocks [2/2] [UU]
unused devices:
По окончании синхронизации настроим загрузчик на новом винчестере
root (hd0,0)
setup (hd0)
root (hd1,0)
setup (hd1)
quit
И все! Сбойный жесткий диск в RAID-массиве успешно заменен без потери данных.

Источник

1 комментарий:

  1. Намного лучше LVM. Хотя бы появляется шанс спасти данные :)

    ОтветитьУдалить