FreeBSD 7.0 и ZFS

Алексей Федорчук
30 октября 2007 г

Долгожданное событие — выход первой бета-версии FreeBSD 7.0 в виде ISO-образов компакт-дисков, — наконец, свершилось. Конечно, получить ее можно было и раньше — установив нынешнюю стабильную версию (6.2), обновив ее исходники через cvs-up до текущей и пересобрав ядро и «мир». Однако появление образов упростило процесс — в том числе и для тех, кто не имеет в данный момент установленной FreeBSD. Получив тем самым доступ ко всем новшествам текущей ветки, иглавное из которых — поддержка файловой системы ZFS. Изучением которой мы со временем и займёмся. Но сначала —

Немного истории

Долгая и славная история FreeBSD, как и ее не менее захватывающая предыстория, описана достаточно подробно (например, здесь и здесь). Однако, начиная с расщепления 4-й и 5-й веток (весна 2002 года, на стадии стабильной версии 4.4, если меня не подводит эклер), она, история эта, приобрела несколько странный характер.

С одной стороны, 5-я ветка получила статус стабильной (stable) примерно через полгода после появления первых пре-релизных ее дисков. С другой стороны, резонные люди настоятельно не рекомендовали ее для серьезного применения — то есть в масштабах чуть больших, чем личный десктоп и сопряженная с ним домашняя сеть (хотя должен отметить, что с масштабами десктопа она вполне справлялась). Более того, в число этих резонных людей входили и сами ее разработчики. Наконец, отщепление 5-й ветки породило раскол в стане коренных гусар (то есть FreeBSD Core Team). В результате чего один из коренных, Мэтт Диллон, создал собственный форк 4-й ветки — DragonFly BSD. Правда, значение его вышло далеко за рамки обычного форка — но это отдельная история).

А собственно в стане FreeBSD сложилась такая ситуация. Апгрейды старой, четвертой, ветки выходили регулярно — последняя из ее версий, 4.11, датируется январем 2005. Наверное, это была самая долгоживущая и активно обновляемая ветка любого дистрибутива в истории операционных систем FOSS — напомню, что версия 4.0 появилась в 2000 году. Никаких особенных новшеств в ней не появлялось, но все выявленные ошибки оперативно устранялись. И потому версии этой ветки интенсивно использовались на промышленных серверах (и используются по сей день).

А параллельно с ней развивалась условно стабильная пятая ветка, последняя версия которой датируется маем 2006 года. Она содержала ряд нововведений, делающих ее более пригодной для использования на десктопе (в частности, файловую систему устройств — devfs), но, по многочисленным отзывам, стабильностью в качестве не блистала. И одновременно велась интенсивная работа над следующей, шестой, веткой, в которой новшества «пятерки» доводились до ума (и появлялись свои собственные). Статус стабильности она обрела в конце 2005 года, и с тех пор было выпущено всего два ее обновления (последнее, в виде версии 6.3, обещано в декабре этого года).

То есть «пятерка» выполняла, в сущности, функции бета-версии «шестерки». Жизненный цикл которой тоже оказался не очень длинным — стабилизация седьмой ветки в виде релиза 7.0 также приурочен к декабрю 2007 года. От которой есть все основания ожидать долгой и продуктивной жизни.

Собственно о «семерке»

Первая бета-версия «семерки» появилась, как любит говорить ЛОРентий Палыч (он же — коллективный разум ЛОРа), тихо и незаметно, 22 октября 2007 года. Никакого официального объявления где бы то ни было места не имело. Просто на ftp.freebsd.org и его зеркалах в каталогах pub/FreeBSD/ISO-IMAGES-[arch] вдруг волшебным образом материализовался подкаталог 7.0, содержащий четыре ISO-образа:

  • 7.0-BETA1.5-i386-bootonly.iso
  • 7.0-BETA1.5-i386-disc1.iso
  • 7.0-BETA1.5-i386-disc2.iso
  • 7.0-BETA1.5-i386-docs.iso

Первый (bootonly) — это большая (от примерно ста мегабайт с копейками до без малого двухсот, в зависимости от целевой архитектуры) загрузочная дискета, предназначенная для установки по ftp. Использовать его можно только в том случае, если есть твердая уверенность, что с настройкой сети под FreeBSD все будет нормально уже на стадии инсталляции. Что, должен заметить, вовсе не гарантировано, если сеть с установленной «фряхой» работает нормально. У меня, например, так оно и есть, но на стадии установки ни один ftp-сервер не цепляется (хотя сама по себе сеть конфигурируется правильно, и после окончания установки и перезагрузки пашет, как волы на колхидском поле).

Второй диск (disc1), объемом 550-650 Мбайт, — собственно и есть вожделенный установочный. Качается и болванится в обязательном порядке — именно с ним мы и будем иметь дело в дальнейшем.

Третий диск (disc2) — сразу вызывает подозрение своим объемом в пару-тройку сотен килобайт. И действительно, ничего на нем нет, кроме cdrom.inf. Следует ожидать, что в релизе на нем будут всякие дополнительные пакеты.

Ну а диск с документацией — штука очень полезная, но необходима только тем, у кого проблемы со связью: это — содержимое http://www.freebsd.org/docs.html на всех языках, на который переведена официальная документация проекта (на русский, благодаря участникам проекта http://www.freebsd.org.ua/ — переведена).

Надо отметить, что буквально несколько дней спустя 1-я бета версия сменилась полуторной (1.5), каковая ныне и доступна (в виде того же набора дисков). Бета версия за номером 2 обещана 31 октября, так что, когда вы будете читать эти строки, до ее появления останется совсем не много.

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

Особенности установки

Собственно установка новой версии ничем не отличается от того, что я видел последний раз (это была бета 6-й ветки). Разве что теперь инсталляция начинается с выбора страны (например, России) и раскладки клавиатуры (русский вариант предполагает единственно KOI8-R).

Единственно, на чем стоит остановить внимание, это на стратегии дисковой разметки. Ведь мы предполагаем использовать в новой FreeBSD столь же новую файловую систему ZFS, не так ли? Однако, хотя она и поддерживается в «семерке», что называется, почти «из коробки», но именно что почти: с помощью sysinstall задействовать ее не удастся (ведь sysinstall писался во времена, когда ни о какой ZFS еще и слыхом не слыхивали, и серьезных модификаций с тех пор не претерпевал). Так что главная наша задача — установить базовую систему таким образом, чтобы потом большую ее часть перенести на ZFS с минимальными затратами сил и времени. Рассказывать буду на примере своих действий — каждый сможет внести коррективы в соответсвие с наличной конфигурацией и пожеланиями.

Система устанавливалась внутрь все того же прозрачного корпуса (описанного здесь). То есть на машину с AMD64-2, чипсетом Nforce, 2 Гбайт памяти, двумя дисками SATA — 160 и 120 Гбайт. На первом диске 10 Гбайт было занято под Kubuntu, второй я освободил полностью, предназначив на растерзание ZFS. Устанавливал я 64-битную версию — 7.0-BETA1.5-amd64-disc1.iso — поскольку именно такая архитектура рекомендуется разработчиками этой файловой системы, ввиду ее большего адресного пространства.

Начинаем с разметки диска. Корневую файловую систему можно разместить на ZFS только с очень большими ухищрениями. Да и смысла большого в том я не вижу — если вынести из корня все ветви, относимые, по классификации HFS, к разделяемым и (или) изменяемым (а по моей — также к трудновосстановимым), то изменяться его содержимое будет только при пересборках ядра и «мира», а это, согласитесь, бывает не так часто. Так что, фактически, то, на какой файловой системе лежит корень файловой иерархии, волнует весьма мало.

Исходя из этого, создаем на первом диске слайс минимального размера. Какого — в данном конкретном случае он будет 4400 Мбайт. Почему? Потому что 400 Мбайт за глаза хватает на базовую установку (380 Мбайт примерно). А все остальное — предназначено под swap, каковой, в расчете на ZFS, должен быть максимально возможного размера, и это есть рекомендация разработчиков.

В принципе, пространство подкачки можно разнести на два раздела на разных дисках — по два гигабайта на каждом: теоретически это должно увеличить производительность при операциях своппирования.

Да, забыл сказать: оставшееся дисковое пространство на обоих дисках определяем как BSD-слайсы — они-то и составят со временем пул ZFS.

Собственно, это уже следующий пункт меню — Label, в котором BSD-слайс делится на партиции. Именно таким образом — на корневой раздел в 400 Мбайт и swap-раздел, равный удвоенному объему оперативной памяти. Никаких разделов под ветви /tmp, /var, /usr и прочие делать не будем — со временем все они будут вынесены на ZFS. Не будем также трогать и слайсы, созданные под ZFS — со временем руки дойдут и до них.

Далее отправляемся в пункт Distributions — и там заказываем минимальную установку — то есть установить базовую систему и ядро (ну без этого никак). А потом, зайдя в пункт Custom, дополнительно просим еще и man pages — без них будет очень скучно при разборках с ZFS.

Далее все происходит обычным, многократно описанным порядком: сами собой происходят разметка диска, устанавливаются заказанный компоненты. После чего переходим в пункт Configuration, где задаем пароль root’а, определяем часовой пояс и настраиваем консоль для кириллицы. От создания аккаунта обычного пользователя воздерживаемся — его домашний каталог будет вынесен на ZFS, и во избежание лишних телодвижений сделаем это позднее. А вот сетевые интерфейсы — пожалуй, что и настроим, при использовании DHCP это делов на пять секунд (при отсутствии оного — секунд на 10, а проблемы с VPN я обсуждать отказываюсь категоритчески, ибо провайдеры, его использующие, подлежат товарищескому суду Линча).

Не будем также устанавливать никаких дополнительных пакетов — да на диске для архитектуры amd64 их (в бета-версии) и нет. Потом, после создания ZFS-разделов, мы все это проделаем гуртом.

Теперь остается только перезагрузиться и выполнить

Первоначальные настройки

Количество коих нынче сведено к минимуму — ведь система у нас корректно русифицирована, правда, не в UTF-8, а KOI8-R, но тут уж ничего не поделаешь: драйвер консоли FreeBSD, syscons имеет восьмибитное внутреннее представление файлов. Что, впрочем, не помешает нам использовать юникод в Иксах, как будет показано ниже.

Поскольку мы ставили систему на «тачку», уже обремененную Linux’ом, где в качестве загрузчика выступает GRUB, для начала надо обеспечить старт новой операционки. Для чего монтируем соответствующий Linux’овый каталог (в моем случае — корневой)

$ mount -t ext2fs /dev/ad4s1 /mnt

после чего берем в руки любимый (и пока единственно доступный, если не считать Vim в ипостаси чистого vi) текстовый редактор ee, и вызываем на редактирование файл /mnt/boot/grub/menu.lst. Что характерно, замечу в скобках, монтирование Linux’овых разделов на чтение/запись (как и собственно запись) проходят без малейших проблем, чего нельзя сказать об обратной процедуре — например, ядро Kubuntu по умолчанию UFS не поддерживает — ни в первой, ни во второй реинкарнации.

Итак, в файл конфигурации GRUB’а вписываем строки вроде таких:

# FreeBSD
title  FreeBSD 7.0
root   (hd4,1a)
kernel (hd4,1a)/boot/loader

Разумеется, имена устройств и номера разделов следует скорректировать в соответствии с реалиями собственной системы.

Вот и все. Разве что подключаем поддержку звука — пока слушать его неоткуда и нечем, но со временем мы же не будем отказывать от такой роскошества (без которого, как известно, прожить нельзя — в отличие от необходимого). Для чего в файл /boot/loader.conf вписываем строку

sound_load="YES"

А за ней — строки, соответствующие наличному аудио-чипсету. В моем случае ими будут

snd_hda_load="YES"
snd_ich_load="YES"

Ибо встроенное аудио от Nforce определяется системой не иначе как обычное Intel’овское аудио, памятное со времен чипсета i810.

А еще надо выполнить одну процедуру — организацию монтирования файловой системы в оперативной памяти — mfs — в каталог /tmp. Почему это нужно? Как вы помните, мы на стадии установки отказались от выделения отдельных ветвей файловой иерархии на самостоятельные дисковые разделы. А под корень файлового древа отвели самый минимум-миниморум. Что чревато последствиями — в частности, переполнением корня, каковой приводит систему в ступор. Так что первый кандидат на выделение из общего древа — каталог /tmp.

Почему резонно монтировать в него mfs? Ну хотя бы потому, что это гарантирует его очистку при перезапуске системы. Есть и другие резоны, на которых я не буду задерживаться — о них говорилось ранее.

Итак открываем файл /etc/fstab и дописываем в него вот такую строку:

md /tmp mfs rw,noatime,async,-s32m 2 0

Почему именно такую? Обоснование ищите по указанной выше ссылке. По поводу параметра -s, указывающего на ограничение пространства под эту файловую систему, можно и поспорить, но на счет всех остальных — просто поверьте, так лучше (© Лёня Голубков).

Проверяем, не сделали ли мы ачипяток к нашем конфиге, командой

$ mount -a

И если она не дала сообщений об ошибках — то переходим к главному пункту нашей программы, организации дискового пространства по модели

Собственно ZFS

Отдельный разговор о том, что такое ZFS, как она устроена и зачем нужна — еще предстоит (и не в этой заметке). Пока замечу только, что ZFS — не только (а может быть, и не столько) собственно файловая система, но и менеджер разделов, исполняющий функции средств создания и управления программными RAID-массивами и (или) логическими томами (LVM). Только гораздо проще как в создании, так и в употреблении. Собственно говоря, одной из главных целей разработчиков ZFS было — сделать обращение с файловыми системами столь же простым, как с обычными каталогами. И скоро мы увидим, что цель эта была ими достигнута.

Для начала, чтобы не забыть, обеспечиваем поддержку ZFS при старте системы. Для чего вписываем в файл /boot/loader.conf строку

zfs_load="YES"

А в файл /etc/rc.conf —

zfs_enable="YES"

Теперь для организации ZFS на свободном дисковом пространстве (как мы помним, в рассматриваемом случае оно составляет 150 и 120 Гбайт) нам потребуется две команды — zpool и zfs (ну и соответствующие им сведения от тёти Мани почитать тоже не грех).

Первая из указанных команд создает пул накопителей следующим образом:

$ zpool create [имя_пула] [уровень_избыточности] ad4s3c ad6s1c

Имя пула — традиционно tank (хотя никакого рояля это не играет). Имена объединяемых в пул накопителей я дал по собственному примеру (скорректировать в соответствие со своими реалиями). Уровни избыточности — mirror (полное зеркалирование), raidz (примерно соответствует программному RAID-5), raidz1 (то же, что raidz) и raidz2 (с двойным паритетом). Если избыточность не нужна (а в десктопной сфере она не нужна точно), то соответствующий параметр можно просто опустить — при этом мы получим нечто вроде программного RAID в линейном режиме, но, судя по косвенным признакам, все-таки с распараллеливанием процессов чтения/записи. Иными словами, нечто среднее между Linear RAID и RAID-0. То есть то, что доктор прописал для десктопа.

Теперь, дабы душу потешить, посредством команды

$ zpool list

посмотрим, что получилось. В моем случае это будет выглядеть так:

NAME                    SIZE    USED   AVAIL    CAP  HEALTH     ALTROOT
tank                    244G   37,6G    206G    15%  ONLINE     -

При использовании любого уровня избыточности объем пула, на тех же носителях, будет, естественно, существенно меньше: при mirror’е — примерно 120 Гбайт, при raidz — почему-то вообще 109 Гбайт (raidz2 не пробовал за заведомой неактуальностью).

А вот теперь начинается самый охмурёж — собственно создание файловых систем, для чего обращаемся к команде zfs. Помнится, ветвь /tmp файловой иерархии мы уже вынесли на mfs. Теперь, чтобы гарантировать себя от переполнения корневой файловой системы, надо разобраться с ветвями /var и /usr.

С первой все предельно просто: создаем под нее файловую систему командой

$ zfs create tank/var

и до поры, до времени забываем о ее существовании.

С ветвью /usr — чуть сложнее, она содержит множество различных подкаталогов, части из которых не помешали бы специальные параметры. Ну, поехали по порядку. Посредством

$ zfs create tank/usr

создаем исходную точку отсчета. Затем —

$ zfs create tank/usr/ports

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

$ zfs create -b 512 tank/usr/ports

Однако на подкаталог /usr/ports/distfiles, содержащий исходники для собираемых посредством портов программ, это не распространяется, Так что выделяем и его в отдельную файловую систему:

$ zfs create tank/usr/ports/distfiles

Есть резон выделить в отдельные файловые системы и ветви /usr/local, /usr/src и /usr/obj — ведь это так просто (особенно учитывая, что отныне мы не связаны схемой BSD-разметки — 8 разделов на один слайс; а почему — это тема отдельного разговора):

$ zfs create tank/usr/local
$ zfs create tank/usr/src
$ zfs create tank/usr/obj

И напоследок — домашние каталоги пользователей (которых у нас пока еще нет). По умолчанию во Free BSD они располагаются в /usr/home (просто /home — символическая ссылка на него). Отказываться от этого нет резона Шпочему — вскоре станет ясно), так что:

$ zfs create tank/usr/home
$ zfs create tank/usr/home/user1

и так далее.

Предпоследний штрих — ускорения файловых операций для отменяем для всех новообразованных файловых систем атрибут atime (обновление времени доступа, каковое и на фиг не нужно):

$ zfs set atime-off tank

что автоматически распространяется на все вложенные файловые системы (потому и резонно было сделать usr/home).

Вот и все — почти. Перемещаем все содержимое /var и /usr в /tank/var и /tank/usr, соответственно:

$ mv /var/* /tank/var/
$ mv /usr/* /tank/usr/

На сообщение о невозможности переместить кое-что из каталога /var внимания не обращаем.

Вот теперь — уже самое последнее: монтирование подкаталогов tank в реальную файловую иерархию:

$ zfs set mountpoint=/var tank/var
$ zfs set mountpoint=/usr tank/usr

После чего начинаем обычную работу. Ни перезагрузок, ни каких-либо записей в /etc/fstab не требуется. Впрочем, чтобы в этом убедиться, можно и выполнить рестарт машины. А потом командой типа df поглядеть, что у нас делается со свободным местом на дисках. И увидеть, что каждая из файловых систем ZFS потенциально располагает 240 примерно шишабайтами дискового пространства. Что, по мере его расходования, будет убывать пропорционально — опять же для всех. Действительно все ничуть не сложнее, чем создавать каталоги командой mkdir.