RFC (Request for Comments, Запрос на комментарии) - серия документов, публикуемая сообществом исследователей и разработчиков, руководствующихся практическими интересами, в которой описывается набор протоколов и обобщается опыт функционирования Интернет.
Установка FreeBSD с использованием ZFS в качестве основной [2010]
Потихоньку созрел и для таких экспериментов. :D Много тонкостей, которые постарался охватить в этом описании. Задача: установить систему целиком (в том числе и root) на раздел с ZFS используя для разбивки не MBR, а GPT. Согласно рекомендациям, если планируется использовать ZFS, то 64-битная версия системы предпочтительней, поэтому в качестве установочного диска использован официальный DVDFreeBSD-8.1-RELEASE-amd64-dvd1.iso. Для выхода в консоль выбран пункт "Fixit..." в менюsysinstal-а с монтированием CD/DVD. Без метки "Fixit#", "#" или "$" будет представляться результат работы команды, выводимый на консоль. И так, приступим...
1. Разметка диска
На сервере, куда будет устанавливать FreeBSD 8.1-RELEASE установлено 2 SCSI жёстких диска по 72Гб, объединённых в "зеркало" на RAID-контроллере. В системе RAID виден, как устройство /dev/ipsd0. Если до этого момента на жёстком диске были созданы разделы - необходимо их удалить. В первую очередь это, скорее всего была таблица разделов на основе MBR, а во вторых мы будем со всем разбираться с самого начала. Для работы с разбивкой GPT используется утилита gpart. Её же можно использовать и для работы с MBR. 1.1. Просматриваем, что есть на жёстком диске:
1.5. Создаём разделы. Создаваемый раздел характеризуется тремя параметрами: смещение начального блока LBA, размер и тип. Доступный для использования блок LBA можно определить по выводу команды gpart show ad4. В первом столбце строки с записью "- free -" выводится номер блока, с которого начинается неиспользуемое пространство. Для упрощения манипулирования разделами стоит присваивать GPT разделам метки. Например, если в дальнейшем будет необходимость создавать RAID-массивы средствами ZFS (RAIDZ). Так же обращаю внимание, что с появлением новых жёстких дисков, имеющих размер кластера 4кБ необходимо следить, чтобы начальный и конечный сектора (блоки) были выравнены по 4кБ. При этом не стоит забывать, что для внешних (относительно жёсткого диска) систем контроллер последнего эмулирует размер сектора всё таким же 512 байтным. В случае не выравненности разделов возникает проблема сильного снижения скорости передачи данных с активным использованием жёсткого диска в процессе работы. 1.5.а. Создаём раздел для загрузчика. Тут есть несколько тонкостей. Первое: размер раздела для загрузчика не должен быть больше 545 кБ, иначе при загрузке появится сообщение "Boot loader too large" и загрузка остановится. Второе: по умолчанию началом первого раздела за GPT является 34 блок, но если в качестве целевого жёсткого диска будет использоваться жёсткий диск с 4кБ секторами, то в качестве первого блока для раздела freebsd-boot необходимо использовать не 34, а 40 блок (т.е. сделать необходимое выравнивание). Загрузочный раздел начинается по смещению 34 блока от начала диска - сразу после таблицы GPT. Его размер задаём в 256 блоков, это составляет 128кБайт (). В принципе для моих целей достаточно и 32кБайт, но я сделал с запасом. Тип раздела "freebsd-boot" означает, что этот раздел выделен специально под загрузчик FreeBSD:
Параметр -b указывает смещение начального блока создаваемого раздела, а -s - его размер (дополнения к цифрам k, m, g означают, что размер задан не в блоках, а в кило-, мега-, гигабайтах). Уже начиная с версии 8.0-BETA1 в параметрах утилиты gpart можно опускать эти параметры, а так же использовать суффиксы для указания размера создаваемого раздела. По-умолчанию, смещение начального блока берётся минимальным возможным. И если в случае жёсткого диска с 512 Б секторами в этом случае можно не указывать «-b 34», то в случае 4кБ секторов необходимо указать в обязательном порядке «-b 40». При создании остальных разделов тоже надо помнить о выравнивании. Здесь же в дальнейшем будет всё приводиться для обычных (пока ещё) жёстких дисков с 512Б секторами. Размер, если не указан - всё оставшееся свободное пространство. Например, та же команда для создания загрузочного раздела выглядела бы вот так:
Где «partb» - фиксированная «метка» GPT-раздела, по которой он так же будет доступен, как и по обычному идентификатору (в моём случае /dev/ipsd0p1). Такая же метка может быть дана любым другим разделам. Доступен данный идентификатор будет после перезагрузки в каталоге /dev/gpt:
Fixit# ls /dev/gpt
partb
1.5.б. Создаём раздел для swap-а. Можно создать swap и на ZFS, но тогда не будет возможности записи дампа ядра при kernel panic. Размер раздела будет 4 ГБ, в блоках это = 1024*1024*2*4 (в 1кБ два блока). Тип раздела — freebsd-swap:
1.5.в. Создаём раздел для ZFS пула, отведя ему остатки. Тип раздела — freebsd-zfs. Начало и конец раздела можно не указывать, если под него выделяется всё оставшееся место на жёстких дисках, как в моём случае.
Fixit# gpart show ipsd0 -l
=> 34312581741 ipsd0 GPT (68G)
342561 partb (128K)
29083886082 parts (4.0G)
83886081349833573 partz (64G)
Недавно в утилиту gpart была добавлена новая функциональность: возможность резервного копирования и восстановления таблицы разделов: gpart backup/restore.
2. Создание файловых систем
Сразу отмечу, что «файловой системой» и «dataset-ом» в контексте ZFS в разных источниках называют одно и тоже. 2.1. Для работы с разделали с ZFS необходимо подгрузить соответствующие модули ядра.
2.3. После создания пула его корень будет смонтирован в /mnt и определён как загрузочный раздел (через свойство bootfs).
Если ранее на этом разделе был ZFS-пул и его надо пересоздать, то предварительно удалим. Если пул был root-овым, то простой импорт
Fixit# zpool import
или принудительные
Fixit# zpool import -f oldzpool
приведёт к «поломке» загруженной системы. В этом случае на ввод любой команды выведется следующее (в общем виде):
---//--- Shared object ---//--- not found, required by ---//---
В этом случае необходимо монтировать принудительно в отдельную директорию, например, в/mnt/:
Fixit# zpool import –R /mnt/ -f oldzpool
Остаётся удалить пул:
Fixit# zpool destroy -f oldzpool
Определённые в пуле файловые системы будут так же утеряны (удалены).
2.4. Укажем алгоритм подсчёта контрольных сумм:
Fixit# zfs set checksum=fletcher4 systor
2.5. Теперь можно создать дополнительные разделы. Предварительно я устанавливаю свойство atime=off для корневой системы, чтобы оно унаследовалось всеми вновь создаваемыми файловыми системами:
Для информации: a) сжатие может быть установлено в состояние on, off, lzjb, gzip, gzip-N (где Nпредставляет целое от 1 (быстрое сжатие) до 9 (лучшее сжатие, по умолчанию gzip значитgzip-6); b) сжатие вызывает некоторую задержку при доступе к файлам (как при записи, так и при чтении), поэтому режим сжатия рекомендуется использовать для файловых систем нечастого использования. Посмотрим результат:
Для чего создано так много отдельных файловых систем: различные свойства для файловых систем, например, компрессия для /usr/src, /usr/ports и/var/crash; большая гибкость при планировании резервного копирования, например, для /var/db,/usr/home и /usr/local можно создавать снэпшоты по отдельному расписанию; иногда возникает необходимость смонтировать /usr/obj в другое место (например, в chrootдругой системы). Для просмотра свойств созданных файловых систем можно воспользоваться командой:
Fixit# zfs get -r -s local all
А если необходимо глянуть все свойства, в том числе и наследуемые:
Fixit# zfs get -r -s local,inherited all
Свойства dataset-а (например, compression), наследуются вложенными dataset-ами. Свойства можно посмотреть и по другому:
Fixit# zfs list -o name,mountpoint,exec,compression -r zdata
3. Установка системы
3.1. Устанавливаем защитный Protected MBR (pmbr) от программ, не знающих GPT, и GPARTзагрузчик gptzfsboot:
Эта операция может завершиться с ошибкой "Operation not permitted (Операция не допустима)", т.к. в ядре заложена защита критически важных мест жёсткого диска. В этом случае необходимо выполнить:
Fixit# sysctl kern.geom.debugflags=0x10
3.2. Для /usr/home создадим символическую ссылку в /:
Fixit# cd /systor ; ln -s /usr/home home
3.3. Установим систему в созданный пул systor:
Fixit# cd /dist/8.1-RELEASE
Fixit# export DESTDIR=/mnt
Fixit# for dir in base catpages dict doc games info lib32 manpages ports; \
do (cd $dir ; ./install.sh) ; done
Fixit# cd src ; ./install.sh all
Fixit# cd ../kernels ; ./install.sh generic
Fixit# cd /systor/boot ; cp -Rlp GENERIC/* /systor/boot/kernel/
3.4. Для датасета systor/var/empty установим режим "только чтение":
Fixit# zfs set readonly=on systor/var/empty
3.5. Переключимся в режим (chroot) для ZFS-пула /systor:
3.8. Установим системный загрузчик с поддержкой ZFS. "В состав базовой системы добавлен zfsloader, который позволяет загружать систему с ZFS-разделов (для использования загрузчика zfsloader необходимо установить загрузочный код zfsboot или gptzfsboot);" (выдержка из описания к 8.1-RELEASE). Т.е. загрузчик в комплекте 8.1-RELEASE уже поддерживает ZFS в полном объёме. В для более старых версий системы необходимо скомпилировать загрузчик с поддержкой ZFS:
Fixit# echo 'LOADER_ZFS_SUPPORT=YES' > /etc/src.conf
Fixit# mount -t devfs devfs /dev
Fixit# export DESTDIR=""
Fixit# cd /usr/src/sys/boot/
Fixit# make obj
Fixit# make depend
Fixit# make
Fixit# cd i386/loader
Fixit# make install
3.11. Создадим бинарную базу почтовых алиасов /etc/mail/aliases.db:
Fixit# cd /etc/mail
Fixit# make aliases
3.12. Выйдем из режима chroot:
Fixit# umount /dev
Fixit# exit
3.13. Скопируем zpool.cache, в котором содержится информация о созданном пуле ZFS. Он нужен для того, чтобы свежеустановленная система сразу нашла ZFS пул без предварительного его импорта командой zpool import:
Fixit# zfs set mountpoint=legacy systor
Fixit# zfs set mountpoint=/var systor/var
Fixit# zfs set mountpoint=/var/db systor/var/db
Fixit# zfs set mountpoint=/var/tmp systor/var/tmp
Fixit# zfs set mountpoint=/var/crash systor/var/crash
Fixit# zfs set mountpoint=/usr systor/usr
Fixit# zfs set mountpoint=/usr/src systor/src
Fixit# zfs set mountpoint=/usr/ports systor/ports
Fixit# zfs set mountpoint=/usr/ports/distfiles systor/distfiles
Fixit# zfs set mountpoint=/usr/home systor/home
Fixit# zfs set mountpoint=/usr/local systor/local
Fixit# zfs set mountpoint=/usr/obj systor/obj
Fixit# zfs set mountpoint=/tmp systor/tmp
4.4. Выйдем из Fixit режима, возвратившись в sysinstall. Удалим установочный DVD с FreeBSD и произведём загрузку установленной системы.
5. Настройки параметров ядра в плане выделения памяти для ZFS
При загрузке ядро будет выводить предупреждения, что необходимо сконфигурировать переменными ядра распределение памяти для работы ZFS.
Мои настройки /boot/loader.conf для машины с 2 ГБ памяти:
Если всё таки устанавливается версия i386, то для более правильной настройки стоит получше изучить ZFS, в особенности в части тюнинга.
6. Решение мелких проблем
При загрузке с диска (LiveFS или установочного) возможно появление ошибки на этапе загрузки ядра (у меня проявилось на сервере IBM x346, когда к нему подключил DVD-дисковод):