Всем привет!
Давно я сюда не писал, интересно, кто ни будь еще читает мои пустотные заметки? Ау!
Темой сегодняшнего занятия будет восстановление зеркала на программном рейде удаленного компьютера.
Правило первое - работает, не трогай.
Правило второе - лучшее враг хорошего.
Правило третье - кто не хочет работать головой, тот будет работать руками.
На сервере, расположенном в германском дата-центре
hetzner внезапно корневая файловая система решила стать только для чтения. На сервере было два сата диска, три раздела (SWAP, /boot и root) каждый из которых отдельно зазеркален через программный рейд.
Система - centos 5.
Внимательное рассмотрение показало кучу ошибок в dmesg:
SCSI error: return code = 0x08000002
Result: hostbyte=DID_OK driverbyte=DRIVER_SENSE,SUGGEST_OK
sda: Current [descriptor]: sense key: Medium Error
Add. Sense: Unrecovered read error - auto reallocate failed
Descriptor sense data with sense descriptors (in hex):
72 03 11 04 00 00 00 0c 00 0a 80 00 00 00 00 00
01 02 26 46
ata2: EH complete
SCSI device sda: 2930277168 512-byte hdwr sectors (1500302 MB)
sda: Write Protect is off
sda: Mode Sense: 00 3a 00 00
SCSI device sda: drive cache: write back
ata2.00: exception Emask 0x0 SAct 0x2 SErr 0x0 action 0x0
ata2.00: irq_stat 0x40000008
ata2.00: cmd 60/08:08:3f:26:02/00:00:01:00:00/40 tag 1 ncq 4096 in
res 41/40:08:46:26:02/00:00:01:00:00/00 Emask 0x409 (media
error)
ata2.00: status: { DRDY ERR }
ata2.00: error: { UNC }
ata2.00: configured for UDMA/133
ata2: EH complete
SCSI device sda: 2930277168 512-byte hdwr sectors (1500302 MB)
sda: Write Protect is off
sda: Mode Sense: 00 3a 00 00
SCSI device sda: drive cache: write back
ata2.00: exception Emask 0x0 SAct 0x3 SErr 0x0 action 0x0
ata2.00: irq_stat 0x40000008
ata2.00: cmd 60/08:00:3f:26:02/00:00:01:00:00/40 tag 0 ncq 4096 in
res 41/40:08:46:26:02/8f:00:01:00:00/00 Emask 0x409 (media
error)
Предварительный диагноз - смерть второго жесткого диска.
Саппорт подтвердил эту версию, но предупредил, что и первому диску не хорошо. Бэкапьте, говорят, все данные и будем менять диски и переставлять систему. Полная перестановка систему не очень радовала, ибо там почти террабайт данных, которые надо сначала гнать куда-то, а потом восстанавливать.
Я предложил попробовать сначала заменить совсем сдохший диск(sdb), восстановить на него рейды, после чего повторить процедуру с диском sda. Немцы согласились попробовать, но предупредили, что возможны неполадки из за сбоев на диске sda.
Так и получилось. Два маленьких раздела восстановились без разговоров, а большой - после трех процентов восстановления сбрасывался без объявления войны.
Да, а алгоритм действий следующий:
Просматриваем конфигурацию рейд-массивов:
cat /proc/mdstat
Personalities : [raid1] [raid0] [raid6] [raid5] [raid4] [raid10]
md1 : active raid1 sda2[0]
264960 blocks [1/2] [U_]
md0 : active raid1 sda1[0]
2102464 blocks [1/2] [U_]
md2 : active raid1 sda3[0]
1462635200 blocks [1/2] [U_]
Просматриваем таблицу разделов на диске /dev/sda:
fdisk -l /dev/sda
Disk /dev/sda: 1500.3 GB, 1500301910016 bytes
255 heads, 63 sectors/track, 182401 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Device Boot Start End Blocks Id System
/dev/sda1 1 262 2102562 fd Linux raid autodetect
/dev/sda2 263 295 265072+ fd Linux raid autodetect
/dev/sda3 296 182401 1462766445 fd Linux raid autodetect
И дублируем ее на диске /dev/sdb. Либо воссоздаем такую же с помощью fdisk, либо, что проще, через dd:
dd if=/dev/sda of=/dev/sdb bsize=512 count=1
И добавляем новые разделы в рейд:
mdadm /dev/md0 --add /dev/sdb1
mdadm /dev/md1 --add /dev/sdb2
mdadm /dev/md2 --add /dev/sdb3
Соответственно, последняя команда не возымела результата из за ошибок диска sda.
Не беда, меняем раздел /dev/sdb3 на тип 83 - Linux и создаем там файловую систему.
Вот тут то я и допустил первую ошибку. Для скорости копирования я разбил раздел в ext4 fs. На множестве мелких файлов она работает заметно бодрее, чем ext3. Что бы сохранить всю метаинформацию, я копировал с помощью rsync:
mkdir /olddisk; mount /dev/md2 /olddisk
mkdir /newdisk; mount /dev/sdb3 /newdisk
rsync -av /olddisk/* /newdisk
Процентов 15 скопировалось, после чего rsync на каком-то файле выдал ошибку. Вот он бедсектор. Сбойный файл я добавил в список исключений и продолжил копирование. К утру все перенеслось и я написал в поддержку, что можно менять и второй диск.
Надо заметить, что техподдержка у немцев работает с четкостью хорошо смазанного K98. Не взирая на время суток, в течении 5-10 минут приходит осмысленный и квалифицированый ответ на понятном английском.
Да, естественно все эти действия производились через режим rescue, при котором машина загружается с сетевого образа. В этом режиме выявился один крупный неочевидный подводный камень, но об этом позже.
После замены второго диска (sda) я воссоздал на нем таблицу разделов и добавил два маленьких раздела в рейды.
Все получилось и мне показали вот такую картинку:
cat /proc/mdstat
Personalities : [raid1] [raid0] [raid6] [raid5] [raid4] [raid10]
md1 : active raid1 sdb2[1] sda2[0]
264960 blocks [2/2] [UU]
md0 : active raid1 sda1[0] sdb1[1]
2102464 blocks [2/2] [UU]
Теперь надо было разбираться с большим корневым разделом.
Сначала я изменил тип раздела /dev/sda3 обратно на fd - Linux Raid. Потом создал в нем зеркальный массив из одного диска :)) (Как ни странно в линуксе возможно даже такое извращение)
mdadm --create /dev/md2 --level=1 --raid-disk=2 missing /dev/sda3
Вот на этом месте mdadm что-то пробормотал про старые версии grub, но я пропустил это мимо себя, решив, что у меня все новое и все будет хорошо.
Создаем файловую систему в массиве и копируем туда все данные из /dev/sdb3. Вот тут я уже сглупил по полной, поскольку я копировал раздел /dev/sdb3, то и файловую систему я создал как в нем - ext4.
mkdir /olddisk; mount /dev/sdb3 /olddisk
mkdir /newdisk; mount /dev/md2 /newdisk
rsync -av /olddisk/* /newdisk
Пол дня на копирование данных, после чего можно посмотреть, что получилось. Теперь точка монтирования называется /newdisk.
Визуально вроде бы все в порядке. Поправляем тип корневой файловой системы в файле /newdisk/etc/fstab на ext4 и перезагружаемся. И - и тишина... Даю пол-часа на проверку фс при старте, но нет, явно что-то не так... Надо опять теребить поддержку. Добрая хетцнеровская поддержка для таких несчастных предоставляет джавовское приложение для доступа к квм-свитчу, позволяющее увидеть, что происходит на экране компьютера от самого биоса начиная. И тут мы видим, что при попытке подмонтировать корневой раздел ядро выдает ошибку и вылетает в синий экран.
Опущу два дня мучительных исследований и сразу перейду к общим выводам:
Ошибок было две, в одной виноват я сам прямо, а в другой - косвенно.
Первая ошибка простая, надо было пересобрать initrd c поддержкой ext4
mkinitrd with=ext4 with=ext3 /boot/initrd-2.6.18-128.el5.img 2.6.18-128.el5
А вот вторая ошибка была здорово по заковыристее. Дело в том, что при загрузке по сети образа rescue системы у них используется не centos, а debian 7 с существенно более современным ядром и многими прикладными пакетами. В том числе здорово более свежая версия mdadm создает по умолчанию массив с суперблоком (superblock) версии 1.2, в то время как старинное ядро 2.6.18 используемое в консервативном пятом центосе способно автоматически определять только superblock 0.9 при загрузке системы. Способ откатить суперблок до 0.9 не снося при этом массив науке не известен.
Решение проблемы собственно описано на сайте centos, если понять в чем дело и суметь правильно сформулировать запрос.
http://wiki.centos.org/HowTos/Install_On_Partitionable_RAID1 По сути нам надо подсунуть ядру конфиг файл рейдов, что бы ему не нужно было самому определять. Для этого для начала создадим такой конфиг на диске:
mdadm --detail --scan > /newdisk/etc/mdadm.conf
Теперь скачаем патч для скрипта mkinitrd и пропатчим скрипт. После эт
#Монтируем все разделы и переходим в чрут
mount /dev/md2 /newdisk
mount /dev/md1 /newdisk/boot
mount -o bind /proc /newdisk/proc
mount -o bind /dev /newdisk/dev
mount -o bind /dev/shm /newdisk/dev/shm
mount -o bind /sys /newdisk/sys
chroot /newdisk
cd /tmp
wget
http://wiki.centos.org/HowTos/Install_On_Partitionable_RAID1?action=AttachFile&do=get&target=mkinitrd-md_d0.patchcd /sbin
cp mkinitrd mkinitrd.dist
patch -p0 < /tmp/mkinitrd-md_d0.patch
cd /boot
mv initrd-2.6.18-128.el5.img initrd-2.6.18-128.el5.img.bak
mkinitrd /boot/initrd-2.6.18-128.el5.img 2.6.18-128.el5
Теперь, для очистки совести запретим обновлять mkinitrd, для этого пропишем в /etc/yum.conf
exclude=mkinitrd*
Все! Теперь у нас восстановленный рейд и новым суперблоком и более современной файловой системой. Следует помнить, что при обновлении ядра возможно потребуется опять пересоздать initrd.