LXF167:ZFS on Linux
|
|
|
Содержание |
ZFS on Linux:
Применим на деле
Алексей Федорчук дорвался-таки наконец до внедрения ZFS on Linux на настольной машине.
В предыдущей статье, освоив основные понятия, мы научились понимать ZFS. Для обратной же задачи – чтобы ZFS понимала нас – нужно ознакомиться с ее командами.
Создаем простой пул
Главных команд – две: zpool для создания и управления пулами и zfs для создания и управления наборами данных. Не много, правда? Впрочем, каждая из этих команд включает множество субкоманд, в которых мы со временем разберемся.
Очевидно, что работу с ZFS следует начинать с создания пула хранения. Начнем с этого и мы. В простейшем случае однодисковой конфигурации это делается так:
# zpool create tank dev_name
Здесь create – субкоманда очевидного назначня, tank – имя создаваемого пула (оно обычно дается в примерах, но на самом деле может быть любым – с учетом соглашений ZFS), а dev_name – имя устройства, включаемого в пул. Каковое может строиться по любой из описанных ранее моделей. И, чтобы далее не повторяться, напомню: все команды по манипуляции с пулами и наборами данных в них выполняются от лица администратора.
В случае, если в состав пула включается один диск, а второго не предвидится, можно использовать имя устройства верхнего уровня – например, sda для цельного устройства (обратим внимание, что путь к файлу устройства указывать не нужно). Однако реально такая ситуация маловероятна: загрузка с ZFS проблематична, так что как минимум потребуется раздел с традиционной файловой системой под /boot (и/или под корень файловой иерархии), так что команда примет вид
# zpool create mypool sda2
Однако если можно ожидать в дальнейшем подсоединения новых накопителей и их включения в существующий пул, то лучше воспользоваться именем по модели by-id, например:
# zpool create mypool ata-ata-ST3500410AS_5VM0BVYR-part2
Очевидно, что в случае однодискового пула ни о какой избыточности говорить не приходится. Однако уже при двух дисках возможны варианты. Первый – создание пула без избыточности:
# zpool create mypool dev_name1 dev_name2
где dev_name1 и dev_name1 – имена устройств в принятой модели именования.
В приведенном случае будет создано нечто вроде RAID’а нулевого уровня, с расщеплением [stripping] данных на оба устройства. Каковыми могут быть как дисковые разделы, так и диски целиком. Причем, в отличие от RAID0, диски (или разделы) не обязаны быть одинакового размера:
# zpool create mypool sdd sdf
После чего никаких сообщений не последует. No news – good news, говорят англичане; в данном случае это означает, что пул был благополучно создан. В чем можно немедленно убедиться двумя способами. Во-первых, в корневом каталоге появляется точка его монтирования /mypool. А во-вторых, этой цели послужит субкоманда status:
# zpool status mypool
которая выведет нечто вроде такого:
pool: mypool
state: ONLINE
scan: none requested
config:
NAME STATE READ WRITE CKSUM
mypool ONLINE 0 0 0
sdd ONLINE 0 0 0
sdf ONLINE 0 0 0
errors: No known data errors
А с помощью субкоманды list можно узнать объем новообразованного пула:
# zpool list mypool
NAME SIZE ALLOC FREE CAP DEDUP HEALTH ALTROOT
mypool 18,9G 93K 18,9G 0% 1.00x ONLINE -
Легко видеть, что он равен сумме объемов обеих флэшек, если «маркетинговые» гигабайты пересчитать в «настоящие».
К слову сказать, если дать субкоманду list без указания аргумента – имени пула, то она выведет информацию обо всех пулах, задействованных в системе. В моем случае это выглядит так:
# zpool list
NAME SIZE ALLOC FREE CAP DEDUP HEALTH ALTROOT
mypool 18,9G 93K 18,9G 0% 1.00x ONLINE -
tank 199G 20,8G 178G 10% 1.00x ONLINE -
Обращаю внимание, что даже чисто информационные субкоманды вроде list и status требуют прав администратора.
Разумеется, два пула в одной, да еще и настольной, машине – излишняя роскошь. Так что пул, созданный в экспериментальных целях, подлежит уничтожению, что делается с помощью субкоманды destroy:
# zpool destroy mypool
После этого он пропадет из списка пулов. А что можно сделать с пулом до его уничтожения, увидим со временем.
«Избыточные» пулы
Избавившись от ставшего ненужным пула, рассмотрим второй вариант – создание пула с зеркальным устройством. Создаем его из двух накопителей одинакового объема:
# zpool create -f mypool mirror sdf sdg
Проверка показывает, что итоговый пул, как и следовало ожидать, равен объему одного накопителя:
# zpool list mypool
NAME SIZE ALLOC FREE CAP DEDUP HEALTH ALTROOT
mypool 3,72G 91,5K 3,72G 0% 1.00x ONLINE -
При различии объемов больший диск будет «обрезан» до объема меньшего.
Полное зеркалирование любыми средствами, по моему мнению, в настольных условиях – роскошь непозволительная: банальные бэкапы данных проще и надежнее. Тем не менее, не исключаю, что некоторая избыточность на уровне проверки контрольных сумм может оказаться отнюдь не лишней, да не столь и накладна. Так что давайте посмотрим и на третий вариант пула из более чем одного устройства – RAID-Z.
Теоретически виртуальное устройство с одиночным контролем четности, как уже говорилось, можно создать при наличии двух устройств физических. Однако практически это оказывается накладно, особенно если устройства не одинакового размера. Поэтому задействуем под него три накопителя:
# zpool create mypool raidz sdd sdf sdg
что даст нам следующую картину:
# zpool list mypool
NAME SIZE ALLOC FREE CAP DEDUP HEALTH ALTROOT
mypool 11,1G 205K 11,1G 0% 1.00x ONLINE -
Впрочем, как мне кажется, в настольных условиях не стоит выделки и эта овчинка.
Пул кэшируемый
И, наконец, последний вариант организации пула из более чем одного устройства – создание пула с кэшированием. Для чего создаем из двух устройств простой пул без избыточности и подсоединяем к нему устройство для кэша:
# zpool create mypool sdd sdf cache sdg
Очевидно, что устройство для кэширования не должно входить в пул любого рода – ни в простой, ни в избыточный. Что мы и видим в выводе субкоманды list:
# zpool list mypool
NAME SIZE ALLOC FREE CAP DEDUP HEALTH ALTROOT
mypool 18,9G 82K 18,9G 0% 1.00x ONLINE -
где никаких следов его обнаружить не удается. Если же появляются сомнения, а подключилось ли оно на самом деле, обращаемся к субкоманде status, которая покажет беспочвенность наших опасений.
Как я уже говорил в обзоре возможностей ZFS (LXF165/166), подключение устройства кэширования имеет смысл при наличии большого традиционного винчестера (или винчестеров) и относительно небольшого SSD, которое и играет роль дискового кэша.
Об опциях команды zpool
Команда zpool поддерживает еще множество субкоманд, предназначенных для экспорта и импорта пула, добавления к нему устройств и изъятия оных, и так далее. Но сейчас я расскажу о некоторых опциях, которые могут оказаться необходимыми при создании пула.
Одна из важный опций – -f: она предписывает принудительное выполнение данной операции и требуется, например, при создании пула из неразмеченных устройств.
Полезной может оказаться опция -n. Она определяет тестовый режим выполнения определенной субкоманды, то есть выводит результат, например, субкоманды zpool create без фактического создания пула. И. соответственно, сообщает об ошибках, если таковые имеются.
Интересна также опция -m mountpoint. Как уже говорилось, при создании пула по умолчанию в корне файловой иерархии создается каталог /pool_name, который в дальнейшем будет точкой монтирования файловых систем ZFS. Возможно, что это окажется не самым лучшим местом для их размещения, и, как мы увидим в дальнейшем, это несложно будет изменить. Но можно задать каталог для пула сразу – например, /home/data: это и будет значением опции -m. Никто не запрещает определить в качестве такового и какой-либо из существующих каталогов – если он пуст: иначе автоматическое монтирование файловых систем пула в него окажется невозможным.
Наконец, нынче важное значение приобретает опция ashift=#, значением которой является размер блока файловой системы в виде степеней двойки. По умолчанию при создании пула размер блока определяется автоматически, и до некоторого времени это было оптимально. Однако затем, с одной стороны, появились диски так называемого Advanced Format, с другой – получили распространение SSD-накопители. И в тех, и в других размер блока равен 4 КБ, хотя в целях совместимости по-прежнему эмулируется блок в 512 байт. В этих условиях автоматика ZFS может работать некорректно, что приводит к падению производительности пула.
Для предотвращения означенного безобразия и была придумана опция ashift. Значение ее по умолчанию – 0, что соответствует автоматическому определению размера блока. Прочие же возможные значения лежат в диапазоне от 9 для блока в 512 байт (29 = 512) до 16 для 64-килобайтного блока (216 = 65536). В интересующем нас случае четырехкилобайтного блока оно составляет 12 (212 = 4096). Именно последнее значение и следует указать явным образом при создании пула из винчестеров AF или SSD-накопителей.
Создание файловых систем
Пулы хранения представляют собой вместилища для наборов данных, для манипуляции которыми предназначена вторая из главнейших команд – zfs. Самыми важными наборами данных являются файловые системы, к рассмотрению которых мы и переходим.
Для создания файловых систем предназначена субкоманда create команды zfs, которая требует единственного аргумента – имени создаваемой ФС и обычно не нуждается ни в каких опциях:
# zfs create pool_name/fs_name
Внутри пула можно создавать сколь угодно сложную иерархию файловых систем. Единственное условие – родительская файловая система для системы более глубокого уровня вложенности должна быть создана заблаговременно. Ниже я покажу это на конкретном примере создания файловых систем внутри каталога /home – это наиболее оправданное место для размещения наборов данных ZFS.
Начну я немножечко издалека. При стандартной установке openSUSE не обойтись без создания учетной записи обычного пользователя, и, следовательно, в каталоге /home будет присутствовать по крайней мере один подкаталог – /home/username. Смонтировать же файловую систему ZFS в непустой каталог невозможно, и, значит, мы не можем сразу прибегнуть к опции -m для определения «постоянной прописки» создаваемого пула.
Поэтому для начала делаем для пула «прописку» во временной точке – пусть это будет традиционный /tank:
# zpool create -o ashift=12 tank ata-SanDisk_SDSSDX120GG25_120823400863-part3 ata-SanDisk_SDSSDX120GG25_120823402786-part3
Теперь создаем файловую систему для будущего домашнего каталога:
# zfs create tank/home
А внутри же нее – необходимые дочерние ветви, как то:
=# zfs create tank/home/alv
которая потом заменит мой домашний каталог – в нем я не держу ничего, кроме конфигурационных файлов;
# zfs create tank/home/proj
– это файловая система для моих текущих проектов, и так далее.
Как и было обещано разработчиками ZFS, процедура ничуть не сложнее, чем создание обычных каталогов. Благодаря этому файловые системы можно легко создавать по мере надобности, для решения какой-либо частной задачи. И столь же легко уничтожать их, когда задача эта выполнена. Что делается таким образом:
# zfs destroy pool_name/fs_name
Использовать субкоманду destroy следует аккуратно: никакого запроса на подтверждение при этом не будет. Правда, и уничтожить файловую систему, занятую в каком-либо текущем процессе, можно только с указанием опции -f, а файловую систему, содержащую системы дочерние, не получится убить и таким образом.
Ни в какой специальной операции монтирования новообразованные файловые системы не нуждаются – оно происходит автоматически в момент их создания, о чем свидетельствует следующая команда:
$ mount | grep tank
tank/home on /tank/home type zfs (rw,atime,xattr)
tank/home/alv on /tank/home/alv type zfs (rw,atime,xattr)
tank/home/proj on /tank/home/proj type zfs (rw,atime,xattr)
...
Для обеспечения монтирования файловых систем ZFS при рестарте машины не требуется и никаких записей в файле /etc/fstab: это также происходит само собой, совершенно нечувствительно для пользователя. Правда, если для файловой системы ZFS определить свойство mountpoint=legacy, то с ней можно управляться и традиционным способом.
Как и для обычного каталога, объем каждой файловой системы ничем не лимитирован, и в момент создания для любой из них потенциально доступно все пространство пула, которое равномерно уменьшается по мере разрастания файловых систем. На данный момент в моей системе это выглядит так.
Казалось бы, для тех же целей можно ограничиться обычными каталогами. Однако в наборах данных ZFS мы имеем дело с полноценными файловыми системами, для которых могут быть установлены индивидуальные свойства, аналогичные опциям монтирования файловых систем традиционных. Чем мы сейчас и займемся.
Файловые системы: свойства
При создании файловая система ZFS получает по умолчанию определенный набор свойств, во многом сходный с атрибутами традиционных файловых систем, определяемыми опциями их монтирования. Полный их список можно получить командой
# zfs get all fs_name
Свойств этих очень много, однако далеко не все они представляют для нас интерес. Важно только помнить, что любое из свойств каждой файловой системы можно поменять с помощью субкоманды set и ее параметра вида свойство=значение. Причем изменение свойств для материнской системы рекурсивно распространяется на все дочерние. Однако для любой последней свойства можно изменить в индивидуальном порядке. Что я сейчас и проиллюстрирую на примерах.
Скажем, абсолютно лишним представляется свойство atime, то есть обновление времени последнего доступа к файлам. Оно, с одной стороны, снижает быстродействие, с другой – способствует износу SSD-накопителей (правда, нынче и то, и другое явление чисто символичны). Так что отключаем это свойство для всех файловых систем:
# zfs set atime=off tank/home
Аналогичным образом расправляемся и со свойством xattr:
# zfs set xattr=off tank/home
А вот дальше можно заняться и индивидуализацией. Как я уже говорил, в момент создания файловые системы ZFS «безразмерны». Если это не подходит, для них можно установить квоты. Однако я этого делать не буду – в моем случае это приводит к потере половины смысла ZFS. А вот зарезервировать место для критически важных каталогов, дабы его не отъела, скажем, мультимедиа, известная своей прожорливостью, будет не лишним. И потому я для файловых систем tank/home/proj и tank/home/alv устанавливаю свойство reservation. Для файловой системы проектов оно будет максимальным:
# zfs set reservation=10G tank/home/proj
Для остальных ограничусь более скромным гигабайтом резерва.
Далее, поскольку данные в файловой системе tank/home/proj для меня действительно важны, и шутить с ними я склонен даже гораздо меньше, чем с дамами, предпринимаю дополнительные меры по их сохранности путем удвоения числа копий (по умолчанию оно равно 1):
# zfs set copies=2 tank/home/proj
А для данных не столь важных – тех, что часто проще скачать заново, нежели отыскать на локальной машине, можно выполнить и обратную операцию – отказаться от подсчета контрольных сумм:
# zfs set checksum=off tank/home/media
Для файловых систем, содержащих хорошо сжимаемые данные (например, для моего домашнего каталога, где лежат одни dot-файлы), можно включить компрессию:
# zfs set compression=on tank/home/alv
Я этого не делал: экономия места получается грошовая, а нагрузка на процессор и расход памяти, как говорят, очень приличные. Однако это свойство целесообразно включать в системах с огромными логами, если выделить под них файловую систему в пуле ZFS.
При желании для некоторых файловых систем (например, того же домашнего каталога) можно отключить такие свойства, как exec, setuid, devices – легко догадаться, что результат будет аналогичен указанию опций монтирования noexec, nosuid, nodev для традиционных файловых файловых систем. И, разумеется, файловым системам, изменение которых нежелательно, можно придать свойство readonly.
Все необходимые свойства файловых систем желательно установить до их наполнения контентом, ибо многие из них (например, компрессия) обратной силы не имеют.
О перемонтировании
После создания файловых систем и задания всех необходимых их свойств наступает психологический момент для перемонтирования их по месту «постоянной прописки» – то есть в каталог /home. Что потребует от нас некоторых подготовительных действий.
Поскольку предполагается, что все новообразованные файловые системы должны быть полностью доступны обычному пользователю (то есть мне, любимому), перво-наперво следует изменить атрибуты из принадлежности – ведь создавались они от имени администратора и принадлежат юзеру по имени root. Для чего даю команду:
# chown -R alv:users /tank/home/*
Теперь нужно скопировать конфиги из каталога /home/alv в /tank/home/alv:
# cp -Rp /home/alv/.* /tank/home/alv/
не забыв про опцию -p для сохранения атрибутов.
Все предыдущие операции можно было выполнять, получив права администратора с помощью команды su (или, при желании, sudo). Причем где угодно – в текстовом виртуальном терминале или в терминальном окне Иксового сеанса (например, в konsole KDE). Теперь же потребуется переавторизоваться в «голой» консоли.
Монтирование файловых систем ZFS в каталог с любым содержимым невозможно, так что требуется очистить каталог /home от следов прежней жизнедеятельности пользователя таким образом:
# rm -Rf /home/alv
При хотя бы одном активном пользовательском процессе в ответ на это последует сообщение об ошибке. Так что, возможно, предварительно придется убить все реликтовые процессы, запущенные в Иксах от имени пользователя. Сначала выявляем их командой
# ps aux | grep alv
обращая внимание на идентификаторы процессов (PID). А затем последовательно «мочим их в сортире»:
# kill -9 ####
Выполнив все указанные действия, определяем для набора данных tank/home свойство mountpoint, что и осуществит перемонтирование:
# zfs set mountpoint=/home tank/home
Теперь остается только с помощью команды ls убедиться, что в /home появились новые подкаталоги с нужными атрибутами:
drwxr-xr-x 26 alv users 48 Sep 23 14:27 alv/
drwxr-xr-x 18 alv users 18 Sep 22 02:28 proj/
...
А команда
# mount | grep /home
покажет нам новые точки монтирования файловых систем:
tank/home on /home type zfs (rw,noatime,noxattr)
tank/home/alv on /home/alv type zfs (rw,noatime,noxattr)
tank/home/proj on /home/proj type zfs (rw,noatime,noxattr)
...
Как я уже говорил выше, при использовании пакетов из репозитория munix9 на этом дело с подготовкой файловых систем ZFS к практической работе можно считать законченным: при перезагрузке машины все они будут благополучно смонтированы в автоматическом режиме. Пакеты же из ghaskins потребуют еще одного деяния – создания в каталогах /etc/init.d/rc3.d и /etc/init.d/rc5.d символических ссылок на файл /etc/init.d/zfs.
Вместо заключения
За чертой статьи остались многие вопросы применения ZFS, в частности, экспорта и импорта пулов, совместного использования наборов данных в разных дистрибутивах Linux’а (и, возможно, не только его), создания снапшотов и клонов, восстановления после сбоев. Очень интересно изучить проблему размещения на ZFS корня файловой иерархии и возможность загрузки с нее. Однако надеюсь, что рассказанное на предыдущих страницах позволит читателю оценить достоинства ZFS как универсальной комплексной системы размещения данных. Полагаю, что приведенных сведений будет достаточно и для начала практической работы с ней. |