Работа с утилитой mdadm. Изменение типа массива, chunk size, расширение

Введение


К написанию данной статьи меня побудило отсутствие внятной информации на русском языке по работе с утилитой mdadm, реализующей RAID различных типов в ОС linux. В принципе, основные положения работы данной утилиты освещаются достаточно подробно. Почитать об этом можно, например, раз, два, три.

Преобразование RAID1 в RAID5


Основным посылом было преобразование RAID1, созданного при установке Ubuntu массива из двух дисков к RAID5. Начал я, как водится с гугления, и набрел на более раннюю статью на Хабре К сожалению, протестированный на виртуальных машинах, этот способ гарантировано убивал возможность загрузки с корневого раздела. С чем это связано, с более новой версией mdadm, или со спецификой тестирования (корневой раздел на массиве, требуется работа с live CD) выявить не удалось.

Версия системы
root@u1:/home/alf# uname -a
Linux u1 3.2.0-23-generic #36-Ubuntu SMP Tue Apr 10 20:39:51 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux


Разметка диска в моем случае была проще некуда, я смоделировал ее на тестовой виртуальной машине, выделив для дисков по 20 гигов:


Корневой раздел находится на собранных в массив устройствах /dev/sda2 /dev/sdb2 и имеет имя /dev/md0 в базовой системе. Загрузочный раздел находится на обоих дисках, /boot в отдельный диск не выделен.
В версии mdadm v3.2.5, которая устанавливается по умолчанию в Ubuntu, процедура конвертации RAID возможна в направлении 1->5, и невозможна обратно. Выполняется она командой изменения массива –grow, -G. Перед конвертацией вставьте в устройство флешку и примонтируйте ее для сохранения резервного суперблока. В случае сбоев с нее мы будем восстанавливать массив. Монтируем ее в /mnt/sdd1
mkdir /mnt/sdd1
mount /dev/sdd1 /mnt/sdd1
mdadm --grow /dev/md0 --level=5 --backup-file=/mnt/sdd1/backup1

Операция обычно проходит очень быстро и безболезненно. Тут нужно отметить, что получившийся массив типа RAID5 на двух дисках является фактически массивом RAID1, с возможностью расширения. Полноценным RAID5 он станет только при добавлении еще хотя бы одного диска.
Чрезвычайно важно то, что наш загрузочный раздел находится на этом массиве и после перезагрузки GRUB автоматически не подгрузит модули для запуска. Для этого мы делаем обновление загрузчика
update-grub

Если же вы все-таки забыли сделать обновление, и после перезагрузки получили
cannot load raid5rec
grub rescue>

то не отчаивайтесь, вам достаточно загрузится с LiveCD, скопировать на флешку каталог /boot, перегрузиться снова с основного раздела в grub rescue> и подгрузить модуль RAID5 c флешки согласно распространенным инструкциям, например так.
Добавляете строчку insmod /boot/grub/raid5rec.mod
После загрузки с основного раздела не забываем сделать update-grub

Расширение массива RAID5


Расширения измененного массива описано во всех источниках и проблем не представляет. Питание не выключаем.
  1. Клонируем структуру существующего диска
    sfdisk –d /dev/sda | sfdisk /dev/sdc
  2. Добавляем диск к массиву
    mdadm /dev/md0 --add /dev/sdc2
  3. Расширяем массив
    mdadm --grow /dev/md0 --raid-device=3 --backup-file=/mnt/sdd1/backup2
  4. Ждем окончания переконфигурации и наблюдаем за процессом
    watch cat /proc/mdstat
  5. Устанавливаем загрузочный сектор на новый диск
    grub-install /dev/sdc
  6. Обновляем загрузчик
    update-grub
  7. Расширяем свободное место до максимального, работает на живом и смонтированном разделе.
    resize2fs /dev/md0
  8. Смотрим на получившийся массив
    mdadm --detail /dev/md0
  9. Смотрим на свободное место
    df -h


Изменение Chunk Size существующего массива RAID5


В массиве RAID1 понятие Chunk Size отсутствует, т.к. это размер блока, который по очереди пишется на разные диски. При конвертации типа массива к RAID5 этот параметр появляется в выводе детализированной информации о массиве:
Mdadm –detail /dev/md0
/dev/md0:
        Version : 1.2
  Creation Time : Tue Oct 29 03:57:36 2013
     Raid Level : raid5
     Array Size : 20967352 (20.00 GiB 21.47 GB)
  Used Dev Size : 20967352 (20.00 GiB 21.47 GB)
   Raid Devices : 2
  Total Devices : 2
    Persistence : Superblock is persistent

    Update Time : Tue Oct 29 04:35:16 2013
          State : clean
 Active Devices : 2
Working Devices : 2
 Failed Devices : 0
  Spare Devices : 0

         Layout : left-symmetric
     Chunk Size : 8K

           Name : u1:0  (local to host u1)
           UUID : cec71fb8:3c944fe9:3fb795f9:0c5077b1
         Events : 20

    Number   Major   Minor   RaidDevice State
       0       8        2        0      active sync   /dev/sda2
       1       8       18        1      active sync   /dev/sdb2


При этом размер chunk выбирается согласно правилу: Наибольший общий делитель размера массива (в нашем случае 20967352К) и максимального автоматически выставляемого размера chunk(который составляет 64К). В моем случае максимально возможный размер chunk составляет 8K (20967352/8=2620919 дальше на 2 не делится).

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

Как вычислить необходимый размер раздела для нужного вам размера chunk? Берем максимальный текущий размер раздела в килобайтах
mdadm --detail /dev/md0 | grep Array
Делим нацело на требуемый нам размер chunk и на (количество дисков в массиве-1, для RAID5). Полученное число снова умножаем на размер chunk и на (количество дисков в массиве -1), и итогом будет нужный нам размер раздела.
(41934704/256)/2=81903; 81903*256*2=41934336

Изменить размер раздела в сторону уменьшения невозможно на рабочем, смонтированном разделе, и, поскольку он у нас корневой, мы перезагружаемся с любого LiveCD (мне нравится RescueCD, у него mdadm загружается автоматически)
  1. Проверяем запущенные массивы
    Cat /proc/mdstat
    Обнаруживаем, что наш массив в режиме RO
  2. Пересобираем его в обычном режиме
    Mdadm --stop /dev/md127
    Mdadm --assemble --scan
  3. Выполняем проверку массива на ошибки с автоисправлением
    e2fsck -f /dev/md127
  4. Меняем размер активного раздела, указывая в качестве параметра -S 256, чтобы утилита понимала, что данный раздел будет находится на RAID-массиве и добавляя в конец нового размера массива буковку K, чтобы утилита не посчитала данное число — числом блоков
    resize2fs -p S 256 /dev/md127 41934336K
  5. Для изменения размеров массива используем снова параметр --grow в утилите mdadm. Нужно учитывать, изменение массива происходит на каждом диске, а потому в параметрах указываем не общий требуемый размер массива, а размер массива на каждом диске, соответственно делить нужно на (количество дисков в массиве -1). Операция проходит мгновенно
    41934336/2=20967168
    mdadm --grow /dev/md127 --size=20967168
  6. Перезагружаемся в обычный режим, изменяем размер chunk, не забывая предварительно смонтировать флешку для бэкапа суперблока, и ждем окончания пересинхронизации массива.
    mdadm --grow /dev/md0 --chunk=256 --backup-file=/mnt/sdd1/backup3
    watch cat /proc/mdstat

Операция долгая, гораздо дольше, чем добавление диска, приготовьтесь ждать. Питание, как водится, отключать нельзя.

Восстановление массива


Если на каком-то этапе работы с массивом через mdadm у вас произошел сбой, то для восстановления массива из бэкапа (вы же не забыли указать файл для бэкапа?) вам необходимо загрузится с liveCD и пересобрать массив заново с указанием правильной последовательности дисков, входящих в массив и указанием суперблока для загрузки
mdadm --assemble /dev/md0 /dev/sda2 /dev/sdb2 /dev/sdc2 --backup-file=/mnt/sdd1/backup3
В моем случае последняя операция по изменению chunk массива перевела его в состояние *reshape, однако сам процесс пересборки не начинался длительное время. Пришлось перезагружаться с liveCD и восстанавливать массив. После этого пошел процесс пересборки массива, и по окончанию оного размер Chunk Size был уже новый, 256K.

Заключение


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

Дополнительно почитать


www.spinics.net/lists/raid/msg36182.html
www.spinics.net/lists/raid/msg40452.html
enotty.pipebreaker.pl/2010/01/30/zmiana-parametrow-md-raid-w-obrazkach
serverhorror.wordpress.com/2011/01/27/migrating-raid-levels-in-linux-with-mdadm
lists.debian.org/debian-kernel/2012/09/msg00490.html
www.linux.org.ru/forum/admin/9549160
Для особых гурманов fossies.org/dox/mdadm-3.3/Grow_8c_source.html
AdBlock has stolen the banner, but banners are not teeth — they will be back

More
Ads

Comments 20

    0
    RAID5 на двух дисках никоим образои не может быть RAID1, т.к. у RAID1 нет parity.
    Да и сама возможность создания RAID5 на двух дисках какая-то странная, мне на ум приходит только RAID5EE.
      0
      В выводе утилиты mdadm --detail он отображается как RAID5, и количество дисков равняется UU, то есть двум. При этом если не добавляя диск мы удалим из конфигурации один mdadm --fail /dev/sdb2 --remove /dev/sdb2, то система продолжит свою работу, массив перейдет в состояние degraded, однако данные будут по прежнему доступны. Значит ведет он себя как классический RAID1.
      Логика подсказывает, что в данном случае все остается по прежнему, конфигурация RAID1, меняется только наименование.
      При этом добавив диск до трех и выполнив reshape вы получите уже стандартную конфигурацию RAID5 с последовательной записью и блоком checksum.
        0
        На двух дисках может быть деградированный RAID5. Который ресинкается при подключении третьего.
          0
          именно в случае RAID5 на утилите mdadm у вас есть возможность указать при создании тип массива RAID5, а количество дисков — два. И в этом случае вам удастся создать массив, и он не будет в статусе degrade. Я согласен, что он будет не классическим RAID5, а простейшим RAID1, и тут кроется подвох терминологии. Создатель утилиты так ее сделал, что тип массива отображается в виде RAID5, а фактический тип массива будет RAID1.
            0
            А-а, вот вы про что. Да, это будет почти что RAID1, но в отличие от последнего на дисках будут не копии данных, а первый будет содержать негатив второго. Не забываем также про страйпинг: половина блоков первого диска будет содержать данные, половина — негативы, а на втором диске — данные где на первом негатив, и наоборот.
              0
              очень странно, ведь для подобных изменений нужно время. А смена типа массива с RAID1 на RAID5 происходит мгновенно даже на виртуальной машине, без всяческих reshape.
              Как такое может быть в случае, если оба диска наполовину преобразуются в негативы? На это же нужно время reshape?
                0
                Смена массива с точки зрения cat /proc/mdstat происходит мгновенно (точнее, за очень короткий критический период, во время которого переписываются метаданные на всех участвующих устройствах). Но если вы посмотрите на формат метаданных, то увидите, что там есть особые поля:
                — Какой был раньше формат массива
                — На каком этапе преобразование (сколько блоков уже преобразовано, номер первого непреобразованного блока).
                И вот это самое преобразование происходит в фоне и далеко не мгновенно — а как минимум, за время, необходимое, чтобы записать новый диск целиком (и эта нижняя временнАя граница, по-моему, совершенно очевидна).
                  0
                  Наврал: хранится не «какой был раньше», а «какой будет в итоге» формат массива.
                    0
                    И при этом он не показывает статистику и прогресс данного преобразования, делая его скрытым от пользователя, а так же во время этого преобразования можно выполнять прочие операции с массивом, я правильно понимаю?
                      0
                      Ну тогда наиболее вероятно, что я вас не понял. Можете конкретно описать, что именно вы делали, я повторю (как время будет) и разберусь, что именно он делает? (Ну если это отличается от статьи, разумеется. Так-то я что только не делал, экспериментируя с softraid в линуксах...)
                        0
                        Возможно это я вас не понял, т.к. я изменял тип RAID так, как описал это в статье, и при смене типа он не выполняет reshape для двух дисков, а так же прекрасно дает сразу же добавлять еще диск в массив, или удалять диск из массива, не теряя информации.
                        В какой момент он должен производить преобразование блоков при изменении типа массива?
                          0
                          Вообще сразу после grow.

                          А что покажет
                          mdadm --detail /dev/md0

                          сразу после вашего mdadm --grow /dev/md0 --level=5 --backup-file=/mnt/sdd1/backup1 (третья команда, в самом начале, до добавления третьего диска)?
                            0
                            root@u1:/home/alf# mdadm --detail /dev/md0
                            /dev/md0:
                                    Version : 1.2
                              Creation Time : Fri Nov  1 05:44:00 2013
                                 Raid Level : raid1
                                 Array Size : 20967352 (20.00 GiB 21.47 GB)
                              Used Dev Size : 20967352 (20.00 GiB 21.47 GB)
                               Raid Devices : 2
                              Total Devices : 2
                                Persistence : Superblock is persistent
                            
                                Update Time : Fri Nov  1 06:08:30 2013
                                      State : clean
                             Active Devices : 2
                            Working Devices : 2
                             Failed Devices : 0
                              Spare Devices : 0
                            
                                       Name : u1:0  (local to host u1)
                                       UUID : 63e24f74:2a1b03c1:4151c2a0:eb8ac91f
                                     Events : 19
                            
                                Number   Major   Minor   RaidDevice State
                                   0       8        2        0      active sync   /dev/sda2
                                   1       8       18        1      active sync   /dev/sdb2
                            root@u1:/home/alf# mdadm --grow /dev/md0 --level=5 --backup-file=/mnt/sdd1/backup1
                            mdadm: level of /dev/md0 changed to raid5
                            mdadm: failed to set chunk size
                            root@u1:/home/alf# cat /proc/mdstat
                            Personalities : [linear] [multipath] [raid0] [raid1] [raid6] [raid5] [raid4] [raid10]
                            md0 : active raid5 sdb2[1] sda2[0]
                                  20967352 blocks super 1.2 level 5, 8k chunk, algorithm 2 [2/2] [UU]
                            
                            unused devices: <none>
                            

                            времени не затрачено на reshape
                              0
                              Так я просил --detail сразу после --grow --level 5. Как он выглядит на работающем raid1 я и так знаю, интересно, как он выглядит сразу после конверсии.
                                0
                                root@u1:/home/alf# mdadm --detail /dev/md0
                                /dev/md0:
                                        Version : 1.2
                                  Creation Time : Fri Nov  1 12:23:49 2013
                                     Raid Level : raid1
                                     Array Size : 20967352 (20.00 GiB 21.47 GB)
                                  Used Dev Size : 20967352 (20.00 GiB 21.47 GB)
                                   Raid Devices : 2
                                  Total Devices : 2
                                    Persistence : Superblock is persistent
                                
                                    Update Time : Fri Nov  1 13:46:27 2013
                                          State : clean
                                 Active Devices : 2
                                Working Devices : 2
                                 Failed Devices : 0
                                  Spare Devices : 0
                                
                                           Name : u1:0  (local to host u1)
                                           UUID : 0138d79c:6a9bb1ab:c732b3ea:21f036c3
                                         Events : 21
                                
                                    Number   Major   Minor   RaidDevice State
                                       0       8        2        0      active sync   /dev/sda2
                                       1       8       18        1      active sync   /dev/sdb2
                                root@u1:/home/alf# mdadm --grow /dev/md0 --level=5 --backup-file=/mnt/sdd1/backup1
                                mdadm: level of /dev/md0 changed to raid5
                                mdadm: failed to set chunk size
                                root@u1:/home/alf# mdadm --detail /dev/md0
                                /dev/md0:
                                        Version : 1.2
                                  Creation Time : Fri Nov  1 12:23:49 2013
                                     Raid Level : raid5
                                     Array Size : 20967352 (20.00 GiB 21.47 GB)
                                  Used Dev Size : 20967352 (20.00 GiB 21.47 GB)
                                   Raid Devices : 2
                                  Total Devices : 2
                                    Persistence : Superblock is persistent
                                
                                    Update Time : Fri Nov  1 13:47:03 2013
                                          State : clean
                                 Active Devices : 2
                                Working Devices : 2
                                 Failed Devices : 0
                                  Spare Devices : 0
                                
                                         Layout : left-symmetric
                                     Chunk Size : 8K
                                
                                           Name : u1:0  (local to host u1)
                                           UUID : 0138d79c:6a9bb1ab:c732b3ea:21f036c3
                                         Events : 22
                                
                                    Number   Major   Minor   RaidDevice State
                                       0       8        2        0      active sync   /dev/sda2
                                       1       8       18        1      active sync   /dev/sdb2
                                
                                
                                  0
                                  Вот теперь я отчётливо вижу, что чего-то не понимаю :)

                                  Ну что же. Я залез в исходники, нашёл там интересующий меня момент. Для «raid5 из двух дисков» действительно в ядре есть special case, и в комментарии habrahabr.ru/post/200194/#comment_6930036 я заблуждаюсь сам и ввожу в заблуждение других.

                                  Файл linux-3.10.7-gentoo-r1/drivers/md/raid5.c, функция ops_run_compute5. Я выкинул всё, что не относится к рассчёту count, по остаткам можно понять, как count меняется:
                                          //...
                                          int count = 0;
                                          //...
                                          for (i = disks; i--; )
                                                  if (i != target)
                                                          xor_srcs[count++] = sh->dev[i].page;
                                          //...
                                          if (unlikely(count == 1))
                                                  tx = async_memcpy(xor_dest, xor_srcs[0], 0, 0, STRIPE_SIZE, &submit);
                                          else
                                                  tx = async_xor(xor_dest, xor_srcs, 0, count, STRIPE_SIZE, &submit);
                                          //...
                                  

                                  Для случая 2-х дисков будет вызван вариант memcpy, для остальных — xor. unlikely() здесь — это фишка ядра для ускорения работы, optimize very likely/unlikely branches, логика этого кода полностью совпадает со случаем когда никакого unlikely нет в помине и написано просто if (count==1).

                                  Так что я ошибся, «linux software RAID5 из двух дисков» устроен так же, как RAID1. (Как приятно, что это можно проверить, прочитав исходники.) Прошу прощения за то, что ввёл в заблуждение и заставил проверять.

                                  Но видно другое :) он поставил chunk size 8k. Это, кажется, неприлично мало. На raid1 этот размер не имеет значения и поэтому не был заполнен в метаданных, на raid5 он важен, но не был указан и поэтому при конверсии mdadm взял его с потолка. Как-то надо при изменении типа указывать размер чанка.

                                    +1
                                    не совсем с потолка. Данный размер chunk size вычисляется
                                    /* chunk size is meaningful, must divide component_size
                                     * evenly
                                    */
                                            if (info->component_size % (info->new_chunk/512)) {
                                                  unsigned long long shrink = info->component_size;
                                                  shrink &= ~(unsigned long long)(info->new_chunk/512-1);
                                                  pr_err("New chunk size (%dK) does not evenly divide device size (%lluk)\n",
                                                  info->new_chunk/1024, info->component_size/2);
                                                  pr_err("After shrinking any filesystem, \"mdadm --grow %s --size %llu\"\n",
                                                  devname, shrink/2);
                                                  pr_err("will shrink the array so the given chunk size would work.\n");
                                                  return "";
                                                  }
                                    

                                    не уверен, что исходники в генту не отличаются от этих, т.к. источник странный. fossies.org/dox/mdadm-3.3/Grow_8c_source.html

                                    Конкретно для моей тестовой ситуации я написал, что больше чем на 8 размер массива не делится.
                                      0
                                      Нет, исходники в этой части в генту не отличаются, я гарантирую это. Больше того, скорее всего этот файл (raid5.c) несколько нет не менялся и он такой вообще во всех современных дистрибутивах.
                                        0
                                        это участок из файла, отвечающего за операцию расширения массива --grow, и сверху над сорцами написано, что он для mdadm 3.3, а у меня стоит 3.2.5. Правда скорее всего именно этот кусок не менялся :)

                                        Ну и по поводу chunk size — на домашнем массиве в 2928180032К прекрасно выставился 64K автоматически, что подтверждает запись в сорцах о поиске наибольшего общего делителя.
                    0

          Only users with full accounts can post comments. Log in, please.