Так как я довольно давно использую ZFS (ещё со времён OpenSolaris), и очень доволен данной ФС в Linux, несмотря на её «неправославную» лицензию, то естественно прочитал свежую статью об установке данной ФС на CentOS.

Заметив в руководстве к свершению подвига несколько ошибок, решил не пройти мимо, как я это делаю обычно. К сожалению, в комментариях отвечать не могу, по совершенно очевидной причине.

Работа над ошибками, и некоторые полезные советы под катом.

1. Устанавливать ZFS поверх mdadm массива — это излишнее расточительство ресурсов ЦПУ и излишний дисковый ввод-вывод. ZFS сама прекрасно создаст RAID-0/1/5/6(z2)/z3.

2. При использовании GRUB2 совершенно нет никакого смысла в отдельном разделе для /boot. GRUB2, с указанным в статье фиксом, прекрасно грузит ОС, расположенную на ZFS, а также без всяких проблем может прочитать содержимое директории /boot, расположенной в корневой файловой системе.

О том, как это делается

На дисках (предположим, что их два) вам потребуется всего две партиции: одна для GRUB2, одна для дискового пула. Пример разбивки дисков (GPT без UEFI, если будете использовать UEFI, то тип партиции выставляйте соответственно):

Диск 1:

/dev/sda1    2048     206847     204800   100M BIOS boot
/dev/sda2  206848 1953525134 1953318287 931,4G FreeBSD ZFS

Диск 2:

/dev/sdb1    2048     206847     204800   100M BIOS boot
/dev/sdb2  206848 1953525134 1953318287 931,4G FreeBSD ZFS

Создание пула (зеркало):

$ zpool create -o ashift=12 diskpool mirror /dev/sda2 /dev/sdb2

Где diskpool — имя пула, естественно название можно выбрать по вкусу/схеме именования пулов.

Проверяем созданный pool так:

$ zpool status disкpool

Увидим среди прочего:

	NAME        STATE     READ WRITE CKSUM
	diskpool       ONLINE       0     0     0
	  mirror-0  ONLINE       0     0     0
	    sda2    ONLINE       0     0     0
	    sdb2    ONLINE       0     0     0


Если дисков много (например 4-е), и Вам важна производительность, можно создать RAID-10:

$ zpool create -o ashift=12 diskpool mirror /dev/sda2 /dev/sdb2 mirror /dev/sdc2 /dev/sdd2

При проверке статуса пула увидим:

	NAME        STATE     READ WRITE CKSUM
	diskpool       ONLINE       0     0     0
	  mirror-0  ONLINE       0     0     0
	    sda2    ONLINE       0     0     0
	    sdb2    ONLINE       0     0     0
	  mirror-1  ONLINE       0     0     0
	    sdc2    ONLINE       0     0     0
	    sdd2    ONLINE       0     0     0

Если у вас много дисков и вам нужен более ёмкий RAID:

Примечание

raidz — RAID-5. Oдна P-сумма — по xor

raidz2 — RAID-6. Oдна P-сумма — по xor, одна Q-сумма — код рида-соломона на GF(2^8). GF не честное, оптимизировано для производительности, поэтому содержит 0 и не имеет право называться RAID-6, однако raidz2 рассчитывает Q сумму в 8 раз быстрее, чем RAID-6.

raidz3 — с тройной чётностью (ни разу не заглянул в исходники, чтобы проверить, что используется для создания 3-й суммы)

Создадим RAID5 на 4-х дисках:

$ zpool create -o ashift=12 diskpool raidz /dev/sda2 /dev/sdb2 /dev/sdc2 /dev/sdd2 


При проверке пула увидим:

	NAME        STATE     READ WRITE CKSUM
	diskpool       ONLINE       0     0     0
	  raidz1-0  ONLINE       0     0     0
	    sda2     ONLINE       0     0     0
	    sdb2     ONLINE       0     0     0
	    sdc2    ONLINE       0     0     0
	    sdd2    ONLINE       0     0     0

Создадим RAID6 на 5-ти дисках:

$ zpool create -o ashift=12 diskpool raidz2 /dev/sda2 /dev/sdb2 /dev/sdc2 /dev/sdd2 /dev/sde2 

Создадим RAID-50 на 12-ти дисках:

$ zpool create -o ashift=12 diskpool raidz /dev/sda2 /dev/sdb2 /dev/sdc2 /dev/sdd2 /dev/sde2 /dev/sdf2  raidz /dev/sdh2 /dev/sdi2 /dev/sdj2 /dev/sdk2 /dev/sdl2 /dev/sdm2

Принцип очевиден — любые комбинации доступны. Можете в одном пуле комбинировать разные типы RAID, но никакого смысла в этом естественно нет, a есть ограничения:

1. ARC2 SSD cashe недоступен для пулов, в которых есть зеркало.
2. Смешение разного типа RAID-ов в одном пуле гарантирует непредсказуемость производительности пула (в самом худшем смысле — бутербродом вниз).

Раз уж я упомянул о SSD ARC2 cache:

#/dev/sdf - SSD диск
$ zpool create -o ashift=12 diskpool raidz1 /dev/sda2 /dev/sdb2 /dev/sdc2 /dev/sdd2 /dev/sde2 cache /dev/sdf

При проверке пула увидим:

	NAME        STATE     READ WRITE CKSUM
	diskpool       ONLINE       0     0     0
	  raidz1-0  ONLINE       0     0     0
	    sda2     ONLINE       0     0     0
	    sdb2     ONLINE       0     0     0
	    sdc2    ONLINE       0     0     0
	    sdd2    ONLINE       0     0     0
	cache
	  sdf       ONLINE       0     0     0

При создании пула можно указать дополнительные опции так:

$ zpool create -o ashift=12 -o listsnapshots=on diskpool raidz /dev/sda2 /dev/sdb2 /dev/sdc2 /dev/sdd2 

Все опции кроме ashift и некоторых feature@ вы сможете поменять уже после создания пула.

Внимание! Если вы используете zfs версии 0.6.5 и выше, то обязательно при создании пула отключите следующие фичи:

feature@spacemap_histogram feature@enabled_txg feature@hole_birth feature@extensible_dataset feature@embedded_data feature@bookmarks feature@filesystem_limits feature@large_blocks

Если они будут включены, то GRUB2 загрузиться с такой ФС пока не сможет. Это новые плюшки, о которых GRUB2 пока ничего не известно.

Итак, создадим пул со всеми нужными нам параметрами:

$ zpool create -o ashift=12 -o listsnapshots=on   -о feature@spacemap_histogram=disabled  -о feature@enabled_txg=disabled  -о feature@hole_birth=disabled  -о feature@extensible_dataset=disabled  -о feature@embedded_data=disabled  -о feature@bookmarks=disabled  -о feature@filesystem_limits=disabled  -о feature@large_blocks=disabled diskpool raidz /dev/sda2 /dev/sdb2 /dev/sdc2 /dev/sdd2 

Также можно указать сразу опции для создаваемых в последствии файловых систем с ключом -O (о них позже).

Теперь необходимо:

1. Создать файловые системы правильно
2. Указать пулу основную корневую систему и при желании альтернативную (очень удобная штука)
3. Установить GRUB2 на все диски пула
4. Прочее

После создания пула у вас по умолчанию есть файловая система, ассоциированная с пулом:

$ zfs list 

NAME                          USED  AVAIL  REFER  MOUNTPOINT
diskpool                       471G   442G   136K  legacy


Если команда zfs list в колонке MOUNTPOINT для этой ФС содержит не «legacy», то это нужно немедленно исправить:

$ zfs set mountpoint=legacy diskpool

Вообще это и есть корневая файловая система, но использовать её мы не будем, а создадим отдельную виртуально-корневую ФС так:

$ zfs create -o utf8only=on -o compression=lz4 -o atime=off -o relatime=on -o acltype=posixacl -o mountpoint=legacy -o xattr=on diskpool/ROOT

Эта ФС тоже не имеет точки монтирования, а также содержит ряд полезных опций, которые будут унаследованы всеми созданными в последствии ФС (если вы не укажете других опций).

Используемые опции
Опции atime=off и relatime=on значительно повысят производительность ФС, соответственно пожертвовав метками времени доступа к файлам.

Опция compression=lz4 включит на ФС «очень производительную» версию алгоритма сжатия lzjb. Где-то даже есть тесты, и, помнится, меня они впечатлили. Включать компрессию или нет — дело не только вкуса, но и комфорта в работе, а также очень сильно зависит от назначения ФС. Об этом, возможно, напишу в последующей статье.

Хотите поддержки utf8 в именах файлов и отсутствие неприятностей с мултиязычHblми наименованиями? Лучший выбор — опция utf8only=on.

Ну и поддержка xattr нужна однозначно (xattr=on). Появление поддержки POSIX ACL (опция acltype=posixacl) в ZFSonLinux я лично встретил как праздник (убейте, но не помню в какой версии добавили эту фичу).

Далее укажем пулу, что это и есть наша загрузочная ФС:

$ zpool set bootfs=diskpool/ROOT

Далее следуем инструкциям оригинальной статьи, в разделе инсталляции OS, со следующими отличиями:

1. Не создаём отдельную ФС /boot и ничего в каталог /boot не монтируем
2. Никаких /etc/fstab пока не используем
3. Выполнение установки GRUB2 на диски стоит изменить следующим образом:

$ grub2-install --modules=zfs  --boot-directory=/boot /dev/sda
$ grub2-install --modules=zfs  --boot-directory=/boot /dev/sdb
$ grub2-mkconfig -o /boot/grub/grub.cfg

4. Перед тем как начнёте пересобирать initramfs, обязательно удалите /mnt/etc/zfs/zpool.cache.

Далее опять всё по инструкции.

Примечания

Использовать алиасы дисковых устройств из каталогов /dev/disk/by-* вовсе не обязательно (каждый диск знает состав пула по wwn). Вы также можете отредактировать /etc/zfs/vdev_id.conf и дать дискам собственные названия с помощью опции alias:

alias disk1      wwn-0x5000c50045957af3-part2
alias disk2      wwn-0x50004cf20b0d7fa0-part2

Если используете multipath, в том же файле добавьте следующие опции:

multipath yes

#       PCI_ID  HBA PORT  CHANNEL NAME
channel 85:00.0 1         A
channel 85:00.0 0         B
channel 86:00.0 1         A
channel 86:00.0 0         B


Естественно, заменив PCI ID для HBA на свой собственный.

Если честно, то установку ZFS на enterprise-дистрибутивы никогда не делал. Причины очевидны. Подвиг kvaps в этом деле также очевиден. Респект.

Комментарии (21)


  1. kiltum
    14.10.2015 16:25
    -1

    Создадим RAID-50 на 12-ти дисках: и можно создать RAID-10

    Самая распространенная ошибка. Команда типа

    zpool create -o ashift=12 diskpool raidz /dev/sda2 /dev/sdb2 /dev/sdc2 /dev/sdd2 /dev/sde2 /dev/sdf2 raidz /dev/sdh2 /dev/sdi2 /dev/sdj2 /dev/sdk2 /dev/sdl2 /dev/sdm2


    Создает RAID-05. За подробностями, если не верите — в официальный гайд.

    PS. Да, RAID10 она тоже не умеет. Только RAID01


    1. kiltum
      14.10.2015 16:30

      Подробности тут: docs.oracle.com/cd/E23823_01/html/819-5461/gaypw.html Скопирую сюда


      zpool create tank mirror c1d0 c2d0 mirror c3d0 c4d0
      The second mirror keyword indicates that a new top-level virtual device is being specified. Data is dynamically striped across both mirrors, with data being redundant between each disk appropriately.

      Выделение — мое


      1. DLag
        14.10.2015 16:42

        Как я понимаю по производительности будет лучше и без потери надежности


        1. kiltum
          14.10.2015 16:46

          Ну с производительностью все сложнее. Все зависит от того, какую именно надо. IOPS вроде должны подрасти, а линейная — упасть. Но я таких тестов не делал. Я сторонник RAIDZ3 на максимум возможного.


        1. thatsme
          14.10.2015 17:14

          Это именно RAID-10. А не 0+1 в варианте 3-х дисков. И не в варианте 0+1, где два страйпа зазеркалены (производительность и надёжность в этом варианте еквиваленты RAID10).

          Преимущество RAID10 над RAID0+1 второго варианта в том, что в RAID 0+1 Вы уже никогда не сможете добавить устройств в онлайн режиме. Я не видел вариантов второго типа RAID 0+1, в которые можно добавить пару дисков, каждый к своему страйпу, что-бы они легко и просто отзеркалились. В RAID10, Вы просто добавляете зеркало из двух дисков к общему страйпу, и всё это доступно в онлайн режиме.


          1. kiltum
            14.10.2015 17:18
            -1

            Вы немного неправы. Что бы не разводить дискуссию с перепечатками, поищите zfs internals — там описано, как с помощью zdb узнать 100%, где и как какие данные хранятся.


      1. thatsme
        14.10.2015 16:55

        Data is dynamically striped across both mirrors, with data being redundant between each disk appropriately.

        Выделение — мое


        Да, именно эту часть Вы перевели неверно. См. мой коментарий ниже.


        1. kiltum
          14.10.2015 17:15

          Опять же ниже ответил. Если кратко, то как раз в этой фразе и скрыто краткое описание того, почему zfs не тормозит в случае потери одного из дисков.

          Просто примите, что в случае более чем одного vdev в пуле, данные между ними объединяются аналогично raid0 (и только им). Или говоря языком перевода, данные размазываются по всем vdev в пуле равномерно (более-менее, если варианты, когда будет перекос). А из чего состоит каждый vdev — это уже дело админа. И данные между vdev никак не мигрируют.

          На пальцах и грубо (очень грубо). Если я решил записать на пул из 4 дисков в «зеркале» два байта 00 и ff.

          В случае с zfs на первых двух дисках будет записано 00, на вторых — ff.
          В случае c raid10, на первых двух дисках будет записано 00ff, и на вторых — 00ff.

          В этом и состоит принципиальная разница между raid01 и raid10.


          1. thatsme
            14.10.2015 17:32

            В случае c raid10, на первых двух дисках будет записано 00ff, и на вторых — 00ff.


            Вы описали зеркало зеркал N+N, что не имеет никакого отношения к RAID-10.

            RAID 10 — массив RAID 0, построенный из массивов RAID 1;

            RAID 50 — массив RAID 0, построенный из массивов RAID 5;

            RAID 05 — массив RAID 5, построенный из массивов RAID 0;

            Для построения RAID 05, Вам потребуется как минимум 3 страйпа (concat). Эта конфигурация в ZFS никогда не поддерживалась.

            В ZFS on Linux, это можно иcxитриться сделать, создав 3 пула в каждом по 2 диска в страйп конфигурации, и далее создав на в каждом пуле zvol, а уже после этого, из этих zvol состряпать пул raidz. Вот это будет RAID 05. Но этого даже врагу не пожеласешь.


            1. kiltum
              14.10.2015 17:41
              -1

              Кажется, мы говорим друг другу об одном и том же, только используя пересекающуюся терминологию, которая по сути не совпадает.

              В смысле если использовать только ту терминологию (да, она более правильная, более распространенная и теде), то да. Я снимаю свои возражения. Да, ТЕ команды делают RAID10 и RAID50.

              PS Я учился давно, когда «RAID50 означало массив RAID5, собранный из как минимум трех RAID0»


              1. ufm
                17.10.2015 00:55
                +3

                По всей видимости Вы учились не только давно, но и плохо. RAID50 всю жизнь был массив RAID 0, собранный из массивов RAID 5;


    1. thatsme
      14.10.2015 16:48
      +1

      Самая распространенная ошибка. Команда типа


      Позволю себе с Вами не согласиться, приведя в качестве аргумента ссылку на документацию, а заодно и цитату.
      Creating a Mirrored Storage Pool

      The second mirror keyword indicates that a new top-level virtual device is being specified. Data is dynamically striped across both mirrors, with data being redundant between each disk appropriately.


      Перевод: Второе ключевое слово mirror, означает, что указано новое вируальное устройство верхнего уровня. Данные динамически «страйпятся» на оба зеркала, при этом данные отказоустойчивы между соответствующими дисками.



      Прошу прощения за «страйпятся», не смог перевести это адекватно (к примеру как «полосатятся»), термин в СХД устоявийся.

      Итак, если это крякает как утка, выглядит как утка, — то это и есть утка. В данном случае RAID10 (страйп зеркал).

      Абсолютно тоже самое произойдёт и со страпингом vdev типа raidz (RAID5), raidz2(RAID6), raidz3 (RAID с тройной чётностью).

      И есть один немаловажный момент, который мог ввести Вас в заблуждение: В документации сказано о том, что Solaris не поддерживает страйп-конфигурации пулов для корневой ФС.


      1. kiltum
        14.10.2015 17:06

        Пойду с конца. Про страйп для корневой. Давно поддерживает.

          pool: rpool
         state: ONLINE
          scan: resilvered 120G in 2h5m with 0 errors on Mon Dec 29 13:37:16 2014
        config:
        
                NAME                         STATE     READ WRITE CKSUM
                rpool                        ONLINE       0     0     0
                  mirror-0                   ONLINE       0     0     0
                    c1t5000C5003BAFCFF3d0s0  ONLINE       0     0     0
                    c1t5000C5003BA4C02Bd0s0  ONLINE       0     0     0
        


        Живая солярка грузится с зеркала. И omniOS тоже умеет.

        Про raid 10/01. Да, я немного педант. Ибо данные все-таки ходят немного по другому.

        Опять же, что согласно Вашей логике должно получиться после команды create pool mirror disk1 disk2 raidz1 disk3 disk4 disk5? :) Да, извращение но ведь сработает и сделает raid0(1/5), а не raid(5/1)0

        Что касается перевода, то он полностью соответствует тому, что я раньше написал. Говоря другими словами, данные страйпятся между vdev, в каждом из которых данные защищены реданданси (да, тяжело с англицизмами)

        Именно сама технология страйпинга между vdev и является основной фишкой zfs, благодаря которой она не впадает в дикие тормоза при выходе одного из дисков.


        1. thatsme
          14.10.2015 17:19
          +1

          Простите, но Вы неправы. Прошу смотреть мои другие комментарии, выше.
          RAID-10 — страйп одного или нескольких зеркал (пар дисков)
          RAID-50 — страйп одного или нескольких RAID5 массивов
          И.т.д.

          RAID-0+1 — имеет два варианта:
          а) 3-х дисковый вариант, где блоки страйпятся на два диска из трёх в раунд робине
          б) Одно зеркало двух страйпов, — о недостатках было в комментарии выше.


          1. kiltum
            14.10.2015 17:24

            Правильно, не верьте мне. Но родной утилите-то поверите? zdb -d{ddd — по вкусу, но чем больше, тем точнее и дольше, на живых разделах будет ОЧЕНЬ долго}. Она покажет, как и что и где хранится.


        1. thatsme
          14.10.2015 17:21
          +2

          Пойду с конца. Про страйп для корневой. Давно поддерживает.

          pool: rpool
          state: ONLINE
          scan: resilvered 120G in 2h5m with 0 errors on Mon Dec 29 13:37:16 2014
          config:

          NAME STATE READ WRITE CKSUM
          rpool ONLINE 0 0 0
          mirror-0 ONLINE 0 0 0
          c1t5000C5003BAFCFF3d0s0 ONLINE 0 0 0
          c1t5000C5003BA4C02Bd0s0 ONLINE 0 0 0


          Это не страйп, это зеркало (RAID-1), оно поддерживалось всегда.


          1. kiltum
            14.10.2015 17:27

            Прошу пардону. В пылу не то скопипастил. Солярки официальной нет. Есть омни

            rpool               ONLINE       0     0     0
                      raidz2-0                 ONLINE       0     0     0
                        c1t5000C50033D82E43d0  ONLINE       0     0     0
                        c1t5000C50033D88717d0  ONLINE       0     0     0
                        c1t5000C50033FB94E3d0  ONLINE       0     0     0
                        c1t5000C5003404A3A7d0  ONLINE       0     0     0
                        c1t5000C5003404B613d0  ONLINE       0     0     0
                        c1t5000C5003404D837d0  ONLINE       0     0     0
            


            Скажу сразу: зачем так было сделано, я не понимаю пока. Ибо было сделано до меня и давно и вообще неправда.


            1. thatsme
              14.10.2015 17:37

              Я за Solaris, года два как следить перестал. Поэтому всё может быть. Ветки ZFS тоже сильно разошлись у сообщества и Oracle. В Oracle версии ZFS например даже зачатки поддержки кластеризации, ~полтора года назад добавили.


              1. kiltum
                14.10.2015 17:48

                Да, разошлись сильно. Но меня пока спасает, что zfs send/receive не поломали и благодаря этому я потихоньку мигрирую на линуксы


  1. heathen
    14.10.2015 19:19
    +1

    После года борьбы с ZOL при boot и root на zfs никому не посоветую пользоваться этим на Linux. Периодическое нежелание грузиться в целом или, скажем, импортировать pool с рутовым разделом при старте отбило всякое желание. Причём судя по багтрекеру, как минимум одной проблеме далеко не первый год. И постоянно переживать «а поднимется ли при очередном рестарте/после очередного upgrade сервер сам или нужно будет лезть в консоль, чтобы сделать всё руками» — зачем оно?

    Допилят btrfs — можно будет пользоваться. А хотите zfs — используйте солярку/FreeBSD, как, например, делаю я :)


  1. thatsme
    14.10.2015 20:40
    +1

    Да порт ZFS on Linux, пока ещё рановато запускать в суровый «enterprise».

    «а поднимется ли при очередном рестарте/после очередного upgrade сервер сам или нужно будет лезть в консоль, чтобы сделать всё руками»


    Но по моим наблюдениям, большинство проблем с ZFS on Linux, — сводится к ошибкам администратора.

    Причинами тех пробем, что Вы описали, могли быть следующие из списка:

    1. Версия пула не поддерживается загрузчиком GRUB2. Ошибка администратора, — обновление версии пула без чтеня changelogs и проверки зависимостей;
    2. Несоответствие параметров ядра, рекомендованным для работы с ZFS;
    3. Не прописанная или прописанная неверно опция bootfs пула (При этом GRUB грузит ОС либо через раз, либо раз из 10, либо ручного импорта пула);
    4. До определённых версий ZFS, GRUB2 не поддерживал её загрузку с не GPT партиций;
    5. Недостаточно памяти, либо zfs_arc_max выставлен в слишком маленькое значение;
    6. Также была ошибка, при которой трудно было загрузиться, в версии 0.6.3 (починили в 6.4), я всё время про эту ошибку забывал: Попытка удаления ФС или zvol приводила к дедлоку в одном из демонов zfs, после, чего он дампился. Комп продолжал работать, однако административные функции zfs, переставали работать. После перезагрузки пул не мог быть импортирован. Потерь или порчи данных не было.

    Шестая проблема лечилась так:

    1. Загрузка с LiveCD FreeBSD
    2. zpool import
    3. zpool export
    4. Грузимся с самого пула
    5. Откатываемся на 0.6.2 (если позволяют фичи), если нет, то не удаляем никакие ФС, до тех пор пока не забываем.

    А btrfs, по моему, ещё дальше от продуктивного использования, чем zfs. И эта оценка, абсолютно субъективна.

    В целом, я портом ZFS on Linux, очень доволен. Он очень сильно облегчает жизнь.