linux

Как перенести mdadm RAID10 с 4 дисками в RAID5

У меня есть программный RAID10,основанный на Linux' mdadm под Debian Buster.Первоначально я обнаружил,что RAID10 имеет лучшую производительность.Но мне нужно больше места,и я согласен обменять некоторую производительность записи на +50% места.

# кот /proc/mdstat
Personalities : [raid10] [linear] [multipath] [raid0] [raid1] [raid6] [raid5] [raid4]
md1 : active raid10 sdd1[5] sda1[4] sdb1[1] sdc1[2]
      3899738112 blocks super 1.2 512K chunks 2 near-copies [4/4] [UUUU]
      bitmap: 3/30 pages [12KB], 65536KB chunk

unused devices: <none>

Это хранилище обслуживается через NFS,и в идеале RAID можно было бы преобразовать без простоев.Да,у меня есть резервные копии,и сбой не будет критичным,но почему бы не мигрировать без сбоев,если все работает.

Я нашел статью от 2012 года, описывающую процесс. Команды оказались вполне верными. Тогда у автора были проблемы, что утилита mdadm (или, возможно, драйвер ядра) первой же командой сразу вешала систему. Похоже, с тех пор эта проблема была исправлена.

https://www.tummy.com/blogs/2012/03/29/changing-a-raid-10-into-a-raid-5/

В mdadm нет прямого пути от RAID10→RAID5.Вместо этого нужно сначала ухудшить RAID0:

# mdadm --grow /dev/md1 --level=0 --raid-devices=2
mdadm: /dev/md1: could not set level to raid0

Это мгновенно подействовало и привело к отказу 2 устройств и их удалению из массива. К сожалению, уровень RAID не был установлен на RAID0. dmesg показал:

md/raid0:md1: All mirrors must be already degraded!
md: md1: raid0 would not accept array

Я обнаружил, что проблема заключалась в том, что sysfs сообщила, что массив не деградировал, хотя на самом деле это было так, и mdadm и cat /proc/mdstat показали правильно:

# cat /sys/block/md1/md/degraded
0

Я не нашел другого способа исправить это,как остановить NFS-сервер,размонтировать файловую систему,закрыть устройство LUKS,остановить RAID-массив,заново собрать RAID-массив и перезапустить все службы.После этого он был правильно зарегистрирован как деградированный и мог быть преобразован в RAID0.

Затем я могу увеличить его до 4 устройств с помощью RAID5:

# mdadm --grow /dev/md1 --level=5 --raid-devices=5 --add /dev/sdb1 /dev/sdd1

В отличие от того, что когда-либо прежде, cat /proc/mdstat показывал не «перестроение», а «изменение формы». Это заняло довольно много времени (около 10 часов), и система реагировала намного медленнее, чем при перестроении RAID10. Я оставил его в покое на время восстановления.

После завершения переформирования RAID5 чист и скорость хорошая.Возможно,я допустил ошибки при измерении,но скорость чтения теперь выше,чем та,которую я регистрировал ранее,и скорость записи также приемлема для меня.

# кот /proc/mdstat
Personalities : [raid10] [linear] [multipath] [raid0] [raid1] [raid6] [raid5] [raid4] 
md1 : active raid5 sdd1[5] sdb1[3] sda1[4] sdc1[7]
      5849607168 blocks super 1.2 level 5, 512k chunk, algorithm 2 [4/4] [UUUU]

unused devices: <none>

(отказ от ответственности: вся история была записана, когда миграция уже была завершена. Я попытался тщательно описать фактические команды и сообщения об ошибках, но могут быть небольшие ошибки. В целом процесс работал, как описано.)




(Пока) не проверено (не доверяйте важные данные шагам ниже), но здесь есть идея для любого сценария, в котором полезное пространство увеличивается, а mdadm --grow говорит: «Схема RAID10 слишком сложна для операции Grow»:

  1. Остановите md
  2. Резервное копирование первых нескольких мегабайт каждого раздела md (предполагается,что суперблоки RAID находятся в начале каждого раздела)
  3. Протрите суперблоки
  4. Создайте RAID5 (или другой RAID) с --assume-clean , используя разделы
  5. Создайте снимки каждого раздела md, например, следуйте https://gist.github.com/jowagner/b36024636140ddf453c12eaf6e590b5d
  6. Восстановите резервную копию разделов из шага 2 в моментальные снимки разделов
  7. Соберите RAID10 из моментальных снимков
  8. dd все данные с RAID10 на RAID5. Использование наименьшего общего кратного двух размеров полос, вероятно, лучше всего подходит для производительности, но подойдет любой размер блока. Первые несколько операций чтения не будут повреждены при записи, поскольку они исходят из данных копирования при записи, записанных на шаге 5. Остальные операции чтения не будут повреждены, поскольку они находятся впереди на безопасном расстоянии от операций записи в каждом разделе (отсюда ограничение этой идеи сценариями, в которых полезное пространство увеличивается).
  9. Остановите RAID10
  10. Отбросить моментальные снимки

Это предполагает,что моментальный снимок только перенаправляет записи на моментальные снимки на устройство COW и что записи на исходное устройство не вызывают сохранение копии старых данных на устройстве COW (иначе решение было бы непрактичным,так как требуется слишком много дополнительного пространства).

Кроме того,если суперблоки старого RAID-массива находятся в конце каждого раздела,эти данные также необходимо резервировать перед шагом 3.Рассчитайте подходящую позицию для поиска и объем данных.Я бы использовал несколько строк Python,но,вероятно,существует инструмент командной строки,который может это сделать.