О том, что Hetzner использует подержанные жесткие диски, не писал только ленивый. Не вижу в этом ничего плохого, учитывая их постоянное уплотнение и снижение отказоустойчивости. Рано или поздно, любые жесткие диски выходят из строя. Но раньше и трава была зеленее, и железо стабильнее.
Отвалился один из дисков, входящих в стандартный софтварный RAID1, созданный с помощью mdadm. На работе сервера это никоим образом не сказалось, но отсутствие резервирования не есть хорошо. После полного бэкапа системы (файлы, базы данных, настройки) написали тикет в техподдержку.
Заблаговременно нужно поставить загрузчик на оставшийся в живых диск (делаем наверняка, вдруг мертвый диск был главным, и с него загружалась система). Для этого достаточно выполнить
grub-install /dev/sdb
(где sdb — живой диск).
При заполнении заявки в панели хостера просят указать серийный номер винчестера, требующего замены, если это представляется возможным. Либо же серийный номер второго винчестера, если первый приказал долго жить и замолчал.
Замену оборудования произвели за 10 минут после нажатия кнопки «Отправить заявку». Такой оперативной работе можно только позавидовать, учитывая, что в качестве подменного диска установили абсолютно новый 3ТБ винчестер (все параметры в SMART были около нуля).
Сервер сразу запустили в боевом режиме (без rescue-mode и лишних потерь драгоценного аптайма). Так как объем винчестера превышает 2ТБ, на дисках используется разметка GPT. Для копирования таблицы разделов на чистый диск в этом случае используется sgdisk. В качестве подстраховки делаем бэкап существующей таблицы разделов на живом винчестере с данными:
sgdisk --backup=/home/backup/sdb.gpt /dev/sdb
Копируем таблицу разделов (особое внимание следует обратить на последовательность аргументов, сначала указывается КУДА, а последним аргументом ОТКУДА копируется таблица):
sgdisk -R /dev/sda /dev/sdb
Генерируем для диска новый UUID:
sgdisk -G /dev/sda
И теперь можно добавить диск в массив (отдельно для каждого раздела):
mdadm /dev/md0 -a /dev/sda1 mdadm /dev/md1 -a /dev/sda2 mdadm /dev/md2 -a /dev/sda3 mdadm /dev/md3 -a /dev/sda4
После этого начинается синхронизация, которая на действующем сервере может затянуться на довольно продолжительное время (вплоть до нескольких дней, зависит от нагрузки). За статусом операции и общим состоянием массива можно следить командой
cat /proc/mdstat Personalities : [raid0] [raid1] [raid6] [raid5] [raid4] [raid10] md3 : active raid1 sda4[2] sdb4[1] 1822442815 blocks super 1.2 [2/2] [UU] md2 : active raid1 sda3[2] sdb3[1] 1073740664 blocks super 1.2 [2/2] [_U] [=============>.] resync = 99.9% (1072884736/1073740664) finish=0.2min speed=65787K/sec md1 : active raid1 sda2[2] sdb2[1] 524276 blocks super 1.2 [2/2] [UU] md0 : active raid1 sda1[2] sdb1[1] 33553336 blocks super 1.2 [2/2] [UU] unused devices:
В моем случае операция синхронизации привела к выпаданию нового диска в Spare и ошибке добавления диска в массив на нескольких разделах (корневой / и загрузочный /boot). Вот тут то и началось самое интересное. При синхронизации происходит чтение текущего активного элемента массива и дублирование информации на новый диск. Если происходят ошибки чтения, то сбойный сектор фиксируется в kern.log, и операция прекращается после нескольких попыток.
Jan 22 19:14:29 server kernel: [294309.656319] end_request: I/O error, dev sdb, sector 1190677512 Jan 22 19:14:29 server kernel: [294309.656359] raid1: sdb: unrecoverable I/O read error for block 1122513920 Jan 22 19:14:29 server kernel: [294309.656362] ata2: EH complete Jan 22 19:14:29 server kernel: [294309.703991] md: md2: recovery done.
Одним из возможных вариантов выхода из сложившейся ситуации было проверить диск на ошибки чтения, отремапить сбойные сектора и попытаться любыми правдами-неправдами синхронизировать разделы.
Personalities : [raid0] [raid1] [raid6] [raid5] [raid4] [raid10] md3 : active raid1 sda4[2] sdb4[1] 1822442815 blocks super 1.2 [2/2] [UU] md2 : active raid1 sda3[2](S) sdb3[1] 1073740664 blocks super 1.2 [2/1] [_U] md1 : active raid1 sdb2[1] 524276 blocks super 1.2 [2/1] [_U] md0 : active raid1 sda1[2] sdb1[1] 33553336 blocks super 1.2 [2/2] [UU] unused devices:
Репамить наживую, как оказалось, умеет hdparm (следующую команду копировать не рекомендую в целях безопасности, лучше вбить заново в консоли):
hdparm --write-sector 1190677512 --yes-i-know-what-i-am-doing /dev/sdb
Но для начала нужно было как-то найти все бэды, потому что забрав сбойный сектор из логов и отремапив его, приходилось заново запускать синхронизацию разделов сначала и ждать несколько часов следующей ошибки чтения. В качестве инструмента для поиска была использована утилита badblocks, выводящая ошибки чтения блоков.
Дальше в ход пошла математика, операции перевода блоков в сектора были выведены экспериментально (зачем искать легкие пути).
Вывод badblocks (частичный)
badblocks -v -s /dev/sdb3 Checking blocks 0 to 1073741823 Checking for bad blocks (read-only test): 561257984
Смотрим на таблицу разделов в секторном представлении с помощью
parted /dev/sdb 'unit s print' Model: ATA ST3000DM001-9YN1 (scsi) Disk /dev/sdb: 5860533168s Sector size (logical/physical): 512B/4096B Partition Table: gpt Number Start End Size File system Name Flags 5 2048s 4095s 2048s bios_grub 1 4096s 67112959s 67108864s raid 2 67112960s 68161535s 1048576s raid 3 68161536s 2215645183s 2147483648s raid 4 2215645184s 5860533134s 3644887951s raid
Нас интересует раздел под номером 3, смещение 68161536 от начала диска. Весь раздел размером 2147483648 секторов или 1073741824 блока (что следует из вывода badblocks выше). Значит для получения сбойного сектора делаем следующее:
Берем блок из вывода badblocks 561257984, умножаем на 2, прибавляем смещение 68161536. Полученный сектор 1190677504 и его окрестность пробуем читать hdparm —read-sector 1190677504 /dev/sdb. Про окрестность упомянуто не просто так, мне для получения требуемых секторов пришлось в операцию перевода добавить везде «плюс 2».
После исправления 300+ секторов (частично вручную, частично примитивными bash-скриптами) синхронизация завершилась успешно. В течение всей работы по восстановлению дисков производился мониторинг SMART старого диска, в котором изменялся не в лучшую сторону параметр Current_Pending_Sector, в конце концов он обнулился. Выросло значение Reallocated_Sector_Ct, что показывает, что сектора были успешно заменены на резервные.
В финале можно повторить установку загрузчика для обоих дисков (чтобы наверняка), а также проверить чек-суммы ядра и загрузчика (для тех, кто сначала читает, а потом делает — скопируйте до операций ремапа папку /boot в безопасное место, например на живой раздел).
Ссылки: