Потихоньку созрел и для таких экспериментов. :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. Просматриваем, что есть на жёстком диске:
Fixit# gpart show ipsd0
=> 63 312581745 ipsd0 MBR (149G)
63 11293632 1 !12 [active] (5 .4G)
11293695 301288113 - free - (144G)
1.2. Удаляем раздел[ы]:
Fixit# gpart delete -i 1 ipsd0
ipsd0s1 deleted
1.3. Уничтожаем существующую таблицу разделов (в данном случае - MBR ):
Fixit# gpart destroy ipsd0
ipsd0 destroyed
1.4. Создаём таблицу GPT:
Fixit# gpart create -s GPT ipsd0
ad4 created
Fixit# gpart show ipsd0
=> 34 312581741 ipsd0 GPT (149G)
34 312581741 - free — (149G)
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:
Fixit# gpart add -b 34 -s 256 -t freebsd-boot ipsd0
ipsd0p1 added
Параметр -b указывает смещение начального блока создаваемого раздела, а -s - его размер (дополнения к цифрам k , m , g означают, что размер задан не в блоках, а в кило-, мега-, гигабайтах). Уже начиная с версии 8.0-BETA1 в параметрах утилиты gpart можно опускать эти параметры, а так же использовать суффиксы для указания размера создаваемого раздела. По-умолчанию, смещение начального блока берётся минимальным возможным. И если в случае жёсткого диска с 512 Б секторами в этом случае можно не указывать «-b 34 », то в случае 4кБ секторов необходимо указать в обязательном порядке «-b 40 ». При создании остальных разделов тоже надо помнить о выравнивании. Здесь же в дальнейшем будет всё приводиться для обычных (пока ещё) жёстких дисков с 512Б секторами. Размер, если не указан - всё оставшееся свободное пространство. Например, та же команда для создания загрузочного раздела выглядела бы вот так:
Fixit# gpart add -s 128k -t freebsd-boot -l partb ipsd0
Где «partb » - фиксированная «метка» GPT -раздела, по которой он так же будет доступен, как и по обычному идентификатору (в моём случае /dev/ipsd0p1 ). Такая же метка может быть дана любым другим разделам. Доступен данный идентификатор будет после перезагрузки в каталоге /dev/gpt :
1.5.б. Создаём раздел для swap -а. Можно создать swap и на ZFS , но тогда не будет возможности записи дампа ядра при kernel panic . Размер раздела будет 4 ГБ, в блоках это = 1024*1024*2*4 (в 1кБ два блока). Тип раздела — freebsd-swap :
Fixit# gpart add -b 290 -s 8388608 -t freebsd-swap -l parts ipsd0
ipsd0p2 added
1.5.в. Создаём раздел для ZFS пула, отведя ему остатки. Тип раздела — freebsd-zfs . Начало и конец раздела можно не указывать, если под него выделяется всё оставшееся место на жёстких дисках, как в моём случае.
Fixit# gpart add -t freebsd-zfs -l partz ipsd0
ipsd0p3 added
Итоговая таблица GPT будет такой:
Fixit# gpart show ipsd0
=> 34 312581741 ipsd0 GPT (68G)
34 256 1 freebsd-boot (128K)
290 8388608 2 freebsd-swap (4 .0G)
8388608 134983357 3 freebsd-zfs (64G)
Можно вывести и по указанным идентификаторам:
Fixit# gpart show ipsd0 -l
=> 34 312581741 ipsd0 GPT (68G)
34 256 1 partb (128K)
290 8388608 2 parts (4 .0G)
8388608 134983357 3 partz (64G)
Недавно в утилиту gpart была добавлена новая функциональность : возможность резервного копирования и восстановления таблицы разделов: gpart backup/restore .
2. Создание файловых систем Сразу отмечу, что «файловой системой » и «dataset -ом» в контексте ZFS в разных источниках называют одно и тоже.2.1. Для работы с разделали с ZFS необходимо подгрузить соответствующие модули ядра.
Fixit# kldload /mnt2/boot/kernel/opensolaris.ko
Fixit# kldload /mnt2/boot/kernel/zfs.ko
2.2. Созданные на этапе "Разметка диска " разделы для системы представляются следующим образом:
Fixit# ls -l /dev/ipsd0*
crw-r----- 1 root operator 0 , 63 29 июл 11 :57 /dev/ipsd0
crw-r----- 1 root operator 0 , 79 29 июл 12 :42 /dev/ipsd0p1
crw-r----- 1 root operator 0 , 86 29 июл 13 :00 /dev/ipsd0p2
crw-r----- 1 root operator 0 , 88 29 июл 13 :03 /dev/ipsd0p3
Третий раздел - созданный нами freebsd-zfs . На нём и создадим пул:
Fixit# zpool create -m /mnt systor /dev/ipsd0p3
Fixit# zpool set bootfs=systor systor
2.3. После создания пула его корень будет смонтирован в /mnt и определён как загрузочный раздел (через свойство bootfs ).
Если ранее на этом разделе был ZFS -пул и его надо пересоздать, то предварительно удалим. Если пул был root -овым, то простой импорт или принудительные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 для корневой системы, чтобы оно унаследовалось всеми вновь создаваемыми файловыми системами:
Fixit# zfs set atime=off systor
Fixit# zfs create systor/var
Fixit# zfs create systor/usr
Fixit# zfs create systor/tmp
Fixit# zfs create systor/var/tmp
Fixit# zfs create -o compression=gzip systor/var/crash
Fixit# zfs create -o compression=gzip -o mountpoint=/mnt/usr/src systor/src
Fixit# zfs create -o compression=gzip -o mountpoint=/mnt/usr/ports systor/ports
Fixit# zfs create -o mountpoint=/mnt/usr/ports/distfiles systor/distfiles
Fixit# zfs create -o mountpoint=/mnt/usr/home systor/home
Fixit# zfs create -o mountpoint=/mnt/usr/local systor/local
Fixit# zfs create -o mountpoint=/mnt/usr/obj systor/obj
Fixit# zfs create systor/var/db
Fixit# chmod 1777 /mnt/tmp /mnt/var/tmp
Для информации: a) сжатие может быть установлено в состояние on , off , lzjb , gzip , gzip-N (где N представляет целое от 1 (быстрое сжатие) до 9 (лучшее сжатие, по умолчанию gzip значитgzip-6 ); b) сжатие вызывает некоторую задержку при доступе к файлам (как при записи, так и при чтении), поэтому режим сжатия рекомендуется использовать для файловых систем нечастого использования. Посмотрим результат:Fixit# zfs list
NAME USED AVAIL REFER MOUNTPOINT
systor 342K 62 .0G 22K /mnt
systor/distfiles 18K 62 .0G 18K /mnt/usr/ports/distfiles
systor/home 18K 62 .0G 18K /mnt/usr/home
systor/local 18K 62 .0G 18K /mnt/usr/local
systor/obj 18K 62 .0G 18K /mnt/usr/obj
systor/ports 37K 62 .0G 19K /mnt/usr/ports
systor/src 18K 62 .0G 18K /mnt/usr/src
systor/tmp 18K 62 .0G 18K /mnt/tmp
systor/usr 95K 62 .0G 22K /mnt/usr
systor/var 76K 62 .0G 22K /mnt/var
systor/var/crash 18K 62 .0G 18K /mnt/var/crash
systor/var/db 18K 62 .0G 18K /mnt/var/db
systor/var/tmp 18K 62 .0G 18K /mnt/var/tmp
Для чего создано так много отдельных файловых систем: различные свойства для файловых систем, например, компрессия для /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 :
Fixit# gpart bootcode -b /mnt2/boot/pmbr -p /mnt2/boot/gptzfsboot -i 1 ad0
Эта операция может завершиться с ошибкой "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.6. Создадим /etc/rc.conf :
Fixit# echo 'zfs_enable="YES"' > /etc/rc.conf
Fixit# echo 'hostname="stalker.mydomain.local"' >> /etc/rc.conf
Fixit# echo 'ifconfig_re0="10.87.1.24 netmask 0xffffff00"' >> /etc/rc.conf
Fixit# echo 'ifconfig_re1="DHCP"' >> /etc/rc.conf
В данном примере re0 , re1 — сетевые интерфейсы в новой системе.3.7. Создадим /boot/loader.conf :
Fixit# echo 'zfs_load="YES"' > /boot/loader.conf
Fixit# echo 'vfs.root.mountfrom="zfs:systor"' >> /boot/loader.conf
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.9. Зададим пароль root -а:Fixit# passwd 3.10. Установим локальную временную зону:
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# zpool export amd64 && zpool import amd64
Fixit# cp /boot/zfs/zpool.cache /mnt/boot/zfs/
4. Завершение установки 4.1. Создадим файл /etc/fstab :
Fixit# cat << EOF > /zroot/etc/fstab
# Device Mountpoint FStype Options Dump Pass#
proc /proc procfs rw 0 0
/dev/gpt/parts none swap sw 0 0
EOF
Fixit# mkdir /proc
Fixit# export LD_LIBRARY_PATH=/mnt2/lib
4.2. Отмонтирум все ZFS файловые системы:
Fixit# cd /
Fixit# zfs unmount -a
4.3. Сменим точки монтирования файловых систем:
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 ГБ памяти:vm.kmem_size="1024M"
vm.kmem_size_max="1024M"
vfs.zfs.arc="512M"
vfs.zfs.arc_max="512M"
vfs.zfs.vdev.cache.size ="10M"
vfs.zfs.prefetch_disable=0
Если всё таки устанавливается версия i386, то для более правильной настройки стоит получше изучить ZFS , в особенности в части тюнинга .
6. Решение мелких проблем При загрузке с диска (LiveFS или установочного) возможно появление ошибки на этапе загрузки ядра (у меня проявилось на сервере IBM x346 , когда к нему подключил DVD-дисковод):
SMP : AP CPU#1 Launched!
acd0: TIMEOUT - READ_BIG retrying (1 retry left)
acd0: TIMEOUT - READ_BIG retrying (0 retries left)
acd0: FAILURE - READ_BIG timed out
Данная проблема может быть решена установкой параметра DMA в загрузчике (loader prompt ):
set hw.ata.atapi_dma=0
boot