Письмо от mdadm с пометкой DegradedArray, в выводе cat /proc/mdstat вместо [UU] красуется [U_], SMART-мониторинг шепчет про сбойные секторы. Один диск массива отказал, а сверху на RAID через LVM живут тома с базой, файлами и виртуальными машинами. Хорошая новость в том, что при RAID1 или RAID10 вся процедура замены выполняется на работающем сервере: массив продолжает отдавать и принимать данные, пользователи ничего не заметят, кроме лёгкой просадки скорости. Ниже полный цикл: диагностика, аккуратное извлечение сбойного диска, разметка нового, пересборка, регулировка её скорости и то, что происходит при этом со слоем LVM.

Как отличить отказ диска от проблем с кабелем или контроллером

Первое правило замены - убедиться, что менять нужно именно диск. Загляните в состояние массива:

cat /proc/mdstat
mdadm --detail /dev/md0

Строка [U_] означает, что один из членов массива выпал: U это живой диск, подчёркивание - отсутствующий. В деталях mdadm будет видно, кто именно помечен как faulty или removed. Дальше откройте журнал ядра и найдите ошибки ввода-вывода: dmesg | grep -E "sdb|ata|I/O error" покажет, на каком устройстве и порту они происходят.

Затем спросите у самого диска. Команда smartctl -H /dev/sdb даёт короткий вердикт, а smartctl -A /dev/sdb - полную таблицу атрибутов. Тревожные значения в сырых колонках: Reallocated_Sector_Ct растёт, когда диск прячет дефектные секторы в резервные, Current_Pending_Sector и Offline_Uncorrectable считают секторы, отложенные до переписывания. Сомневаетесь - запустите длинный тест smartctl -t long /dev/sdb и посмотрите результат через smartctl -l selftest, на диске 4 ТБ он занимает несколько часов.

Если ошибки есть, а SMART чистый, проверьте путь: перекиньте диск в другой отсек или порт. Ошибки уехали вместе с диском - меняйте диск. Ошибки остались на порту - виноват кабель, бэкплейн или контроллер, и установка нового диска в тот же слот закончится вторым письмом о деградации через неделю. Настройте и рассылку мониторинга, если её ещё нет: параметр MAILADDR в /etc/mdadm/mdadm.conf плюс служба mdmonitor, и сервер сам сообщит о следующем отказе, а не вы заметите его по жалобам пользователей.

Как найти в корпусе физический диск который отказал

До замены остаётся практическая задача: понять, какой именно диск дёргать из корзины. По имени /dev/sdb этого не видно, сопоставьте имя и серийный номер:

smartctl -i /dev/sdb | grep -i serial
ls -l /dev/disk/by-id/

Серийный номер напечатан на наклейке диска, и этого достаточно в небольшом корпусе. В серверных шасси удобнее светодиод: утилита ledctl из пакета ledmon умеет зажигать индикатор на нужной корзине командой ledctl locate=/dev/sdb, и через несколько секунд нужный отсек мигает. Символьные ссылки /dev/disk/by-id помогают привязать члены массива к физическим накопителям: в mdadm --detail с ключом --export или в конфигурации массива пути в стиле wwn- и ata- однозначнее, чем sda-sdz, которые меняются между загрузками.

Радикальный способ для смелых на избыточном массиве: выдернуть диск и посмотреть в /proc/mdstat, выпал ли именно он. RAID1 такое переживёт, но на RAID5 при одном уже выпавшем диске номер такой метод запрещён: массив уйдёт в нерабочее состояние целиком.

Подготовка нового диска разметка и перенос таблицы разделов

Новый диск должен быть не меньше старого, точнее - не меньше того раздела, который участвовал в массиве. mdadm жёстко требует, чтобы все члены были не меньше самого маленького, лишнее место на больших дисках просто не будет использоваться, пока все не станут одинаковыми. Ставить диск из той же партии, что и остальные члены, спорно: у однопартийных накопителей совпадает и дата рождения, и типовые болезни, лучше чередовать партии.

Если диск раньше использовался, сотрите старые подписи, иначе массив соберётся со странным прошлым:

wipefs -a /dev/sdc
mdadm --zero-superblock /dev/sdc

Таблицу разделов удобнее всего скопировать с живого члена массива - разметка обязана совпасть до сектора:

sgdisk -R /dev/sdc /dev/sdb
sgdisk -G /dev/sdc
sgdisk -t 1:FD00 /dev/sdc
partprobe /dev/sdc

Первая команда переносит таблицу с sdb на sdc, вторая генерирует свежий GUID, чтобы два диска не были копией друг друга с точки зрения разметки, третья ставит разделу тип Linux RAID (код FD00), четвёртая заставляет ядро перечитать таблицу. Для старой MBR-разметки то же самое делается в fdisk установкой типа fd. Проверить результат можно выводом sgdisk -p /dev/sdc и mdadm -E /dev/sdc1: до добавления в массив у раздела не должно быть суперблока.

Если таблицу копировать не с чего или хочется руками, тот же результат даёт parted: mklabel gpt, разметка от 1 МиБ до конца, флаг raid на раздел. Приём, который спасает при замене на диск другого производителя: делайте раздел на гигабайт-два меньше ёмкости накопителя. Диски с одинаковой паспортной ёткостью у разных вендоров различаются сотнями секторов, и раздел, занявший новый диск целиком, иногда оказывается чуть больше, чем позволяет следующая замена.

Пошаговая замена диска в работающем массиве mdadm

Если диск уже выпал сам, mdadm пометил его faulty, и первый шаг можно пропустить. Если он ещё числится активным, но сыплет ошибками, выводите его из работы принудительно - так надёжнее, чем ждать, пока ядро допишется до отказавшей головки.

Полный цикл замены на живом массиве выглядит так:

  1. пометьте раздел сбойным, если mdadm этого ещё не сделал: mdadm /dev/md0 --fail /dev/sdb1;
  2. уберите его из конфигурации массива командой mdadm /dev/md0 --remove /dev/sdb1;
  3. физически замените диск, в корпусах с горячей заменой это делается на ходу;
  4. перенесите таблицу разделов и проверьте совпадение размеров разделов;
  5. добавьте новый раздел в массив командой mdadm /dev/md0 --add /dev/sdc1;
  6. следите за ходом пересборки по выводу cat /proc/mdstat до состояния [UU].

Сразу после добавления массив перейдёт в состояние recovery, и /proc/mdstat начнёт показывать процент и оценку окончания. В серверах с корзинами горячей замены весь цикл проходит без остановки сервисов; в обычном корпусе придётся на пару минут выключить сервер - состояние массива живёт в суперблоках, при включении он соберётся сам и продолжит пересборку.

Ошибки на этом этапе стоят дороже всего, поэтому проговорим их отдельно. Стирая подписи, дважды сверьте имя устройства: wipefs по живому члену массива превращает замену одного диска в восстановление всего RAID. Копирование исправного диска через dd вместо добавления раздела в массив выглядит логично, но работает неверно: mdadm выстраивает члены по суперблокам, а побитовая копия подменяет один диск другим вместе со всеми его болячками. Наконец, следите за размером: слишком маленький раздел mdadm молча оставит в запасных, пересборка не начнётся, и массив так и будет жить в состоянии degraded, пока кто-нибудь не посмотрит в /proc/mdstat.

Контроль скорости пересборки и регулировка лимитов

Ядро ограничивает скорость пересборки двумя настройками: dev.raid.speed_limit_min по умолчанию 1000 килобайт в секунду на диск, dev.raid.speed_limit_max - 200000. Посмотреть текущие значения:

sysctl dev.raid.speed_limit_min dev.raid.speed_limit_max

Смысл такой: пока есть свободные ресурсы ввода-вывода, mdadm старается держаться выше минимума, но не выше максимума. На загруженной базе верхний порог часто снижают, чтобы пересборка не душила рабочую нагрузку:

echo 50000 > /sys/block/md0/md/sync_speed_max

Оценка времени честная арифметика. Диск на 4 ТБ при реальных 150 МБ/с пересобирается около восьми часов, при ограничении в 50 МБ/с - примерно 22 часа. Решение всегда компромисс: медленная пересборка дольше оставляет массив без зеркала, быстрая бьёт по задержкам базы. Ночью порог поднимают, днём возвращают. Чтобы значения пережили перезагрузку, их прописывают в /etc/sysctl.d/99-raid.conf строками dev.raid.speed_limit_min и dev.raid.speed_limit_max.

Два уточнения, которые экономят часы. Первое: пересборку после замены диска не путайте с проверкой scrub и с полной синхронизацией после создания массива, в /proc/mdstat они подписаны по-разному. Второе: если сервер перезагрузили посреди пересборки, mdadm продолжит её с контрольной точки, а не с нуля. Чтобы после нештатных выключений массив пересобирал только затронутые блоки, включите внутреннюю битовую карту:

mdadm --grow /dev/md0 --bitmap=internal

Стоит она немного пропускной способности на записи, но при нештатных остановках экономит часы.

Что происходит с LVM пока массив пересобирается

Слой LVM поверх mdadm устроен так, что пересборка для него невидима. Физический том объявлен на устройстве /dev/md0, а не на отдельных дисках, и пока md0 существует и отвечает, группы томов и логические тома продолжают работать. Проверить иерархию:

pvs
vgs
lvs

Вывод pvs покажет физический том на /dev/md0, vgs - группу томов поверх него, lvs - все логические тома с их размерами. Никаких команд LVM во время замены диска вводить не нужно - и это главное преимущество связки mdadm плюс LVM перед зеркалированием силами самого LVM.

Совсем другая история, если физический том был создан прямо на отказавшем диске, без массива. Тогда группа томов потеряла один из физических томов, и порядок такой: снять дамп метаданных vgcfgrestore -l vg_data, найти рабочую резервную копию в /etc/lvm/archive, удалить потерянный том из группы командой vgreduce --removemissing vg_data, затем создать на новом диске физический том через pvcreate, добавить его в группу vgextend и вернуть содержимое затронутых логических томов из бэкапа. Для зеркальных сегментов LVM есть lvconvert --repair, но на практике почти все держат зеркала уровнем ниже, в mdadm, где пересборка идёт сама и без ручного вмешательства.

После успешной пересборки зафиксируйте конфигурацию массива: mdadm --detail --scan, результат вписывается в /etc/mdadm/mdadm.conf или /etc/mdadm.conf в зависимости от дистрибутива, после чего пересобирается загрузочный образ командой update-initramfs -u либо dracut --force. Без этого шага массив на следующей загрузке может собраться под другим именем, и LVM не найдёт свой физический том.

Отдельный сценарий - плановая миграция на диски большего объёма. Диски меняются по одному, с полной пересборкой после каждого, и когда последний старый покинул массив, снимите ограничение размера члена: mdadm --grow /dev/md0 --size=max расширит массив до новой ёмкости. Дальше слой LVM забирает прирост сам: pvresize /dev/md0, затем lvextend -r +100G /dev/vg_data/lv_base растит логический том вместе с файловой системой. Ни одной перезагрузки, ни минуты простоя.

Проверка массива после пересборки и профилактика следующего отказа

Формально всё закончилось, когда в mdadm --detail /dev/md0 у всех членов state active sync, а State clean. Дальше начинается профилактика, потому что второй отказ до конца пересборки первого - худший сценарий для RAID5, там он означает потерю всего массива.

Регулярная проверка целостности: раз в месяц запускайте scrub, он читает все члены и сверяет данные с чётностью:

mdadm --action=check /dev/md0
cat /sys/block/md0/md/mismatch_cnt

Счётчик mismatch_cnt после проверки должен быть нулём; ненулевое значение означает расхождения, которые читались бы без ошибки, но с несовпадением копий. SMART-контроль настраивается постоянно: в /etc/smartd.conf строка DEVICESCAN -a -m root заставляет следить за дисками и писать при отклонениях, длинный тест smartctl -t long стоит гонять по графику, раз в месяц достаточно.

Горячий запасной диск сокращает окно уязвимости до минут: mdadm --add-spare /dev/md0 /dev/sdd добавляет запасной, который автоматически встанет в строй при следующем отказе. На больших массивах из дисков по 8-12 ТБ подумайте о RAID6: во время пересборки члены читаются всей поверхностью, а бытовой накопитель по спецификации допускает одну нечитаемую ошибку на 10^14 секторов, корпоративный - на 10^15, и при таких объёмах вероятность второй беды во время многочасовой пересборки перестаёт быть теорией. И главное, о чём забывают: RAID защищает от отказа диска, но не от удаления файла командой, испорченного блока в базе или шифровальщика - это уже задача резервных копий, и никакой уровень избыточности её не отменяет.