После ряда успешных экспериментов по использованию ZFS во FreeBSD я решил создать эту страничку. Думаю, найдутся те, кому покажется это интересным.
Опишу процесс установки, которым я уже неоднократно пользовался для установки FreeBSD 8.0-CURRENT, используя в качестве корневой файловой системы (да и вообще, всех файловых систем) ZFS.
[править] Установочный Flash диск
Первой системой, куда я устанавливал FreeBSD подобным образом был мой EeePC. И установка происходила с USB Flash, так как USB CD у меня нет... Процесс подготовки флэшки имеет некоторые особенности, возможно я опишу их позже. Пока только замечу, что она представляет собой установленную систему в корень которой скопирован каталог с дистрибутивом из установочного ISO образа FreeBSD. Если взглянуть на содержимое корневой файловой системы этой флэшки, то можно увидеть вот что:
%ls -l /
total 55
-rw-r--r-- 2 root wheel 784 20 июл 16:17 .cshrc
-rw-r--r-- 2 root wheel 251 20 июл 16:17 .profile
drwxrwxr-x 2 root operator 512 25 май 12:22 .snap
drwxr-xr-x 14 root wheel 512 15 июл 21:58 8.0-BETA2-amd64
dr-xr-xr-x 13 root wheel 512 25 май 12:42 8.0-CURRENT-200905
-r--r--r-- 1 root wheel 6191 20 июл 16:17 COPYRIGHT
drwxr-xr-x 2 root wheel 1024 20 июл 14:40 bin
drwxr-xr-x 7 root wheel 512 20 июл 16:17 boot
dr-xr-xr-x 6 root wheel 512 29 июл 11:57 dev
-rw------- 1 root wheel 4096 28 июл 20:42 entropy
drwxr-xr-x 20 root wheel 2048 29 июл 12:11 etc
lrwxr-xr-x 1 root wheel 8 29 июл 12:11 home -> usr/home
drwxr-xr-x 3 root wheel 1536 20 июл 14:48 lib
drwxr-xr-x 2 root wheel 512 20 июл 14:39 libexec
drwxr-xr-x 2 root wheel 512 4 май 19:39 media
drwxr-xr-x 2 root wheel 512 4 май 19:39 mnt
dr-xr-xr-x 2 root wheel 512 4 май 19:39 proc
drwxr-xr-x 2 root wheel 2560 20 июл 14:47 rescue
drwxr-xr-x 2 root wheel 512 28 июл 20:39 root
drwxr-xr-x 2 root wheel 2560 20 июл 16:21 sbin
lrwxr-xr-x 1 root wheel 11 20 июл 16:16 sys -> usr/src/sys
drwxrwxrwt 7 root wheel 512 29 июл 11:59 tmp
drwxr-xr-x 13 root wheel 512 28 июл 20:30 usr
drwxr-xr-x 23 root wheel 512 29 июл 11:59 var
Здесь 8.0-BETA2-amd64 и 8.0-CURRENT-200905 - каталоги, скопированные с ISO образов.
%ls -l /8.0-BETA2-amd64/
total 26
drwxr-xr-x 2 root wheel 1024 15 июл 21:51 base
drwxr-xr-x 2 root wheel 512 15 июл 21:51 catpages
drwxr-xr-x 2 root wheel 512 15 июл 21:51 dict
drwxr-xr-x 2 root wheel 512 15 июл 21:51 doc
drwxr-xr-x 2 root wheel 512 15 июл 21:51 games
drwxr-xr-x 2 root wheel 512 15 июл 21:51 info
drwxr-xr-x 2 root wheel 1536 15 июл 21:54 kernels
drwxr-xr-x 2 root wheel 512 15 июл 21:51 lib32
drwxr-xr-x 2 root wheel 512 15 июл 21:51 manpages
drwxr-xr-x 2 root wheel 512 15 июл 21:55 ports
drwxr-xr-x 2 root wheel 512 15 июл 21:51 proflibs
drwxr-xr-x 2 root wheel 2560 15 июл 21:57 src
[править] Процесс установки
[править] Разметка диска
Итак. Устанавливаю я на обычный офисный компьютер, до этого на нём был FreeDOS. В качестве таблицы разделов я буду использовать GPT, поэтому предварительно нужно удалить текущую таблицу разделов.
# gpart show ad4
=> 63 312581745 ad4 MBR (149G)
63 11293632 1 !12 [active] (5.4G)
11293695 301288113 - free - (144G)
Удаляю все (в данном случае единственный) разделы:
# gpart delete -i 1 ad4
ad4s1 deleted
Уничтожаю таблицу разделов:
# gpart destroy ad4
ad4 destroyed
Теперь создаю таблицу GPT и 3 раздела - 1-ый для установки на него загрузчика, 2-ой для раздела подкачки (swap), 3-ий для ZFS пула, куда будет устанавливаться система.
# gpart create -s GPT ad4
ad4 created
# gpart show ad4
=> 34 312581741 ad4 GPT (149G)
34 312581741 - free - (149G)
Создаваемый раздел характеризуется тремя параметрами: смещение начального блока LBA, размер и тип. Доступный для использования блок LBA можно определить по выводу команды gpart show ad4. В первом столбце строки с записью "- free -" выводится номер блока, с которого начинается неиспользуемое пространство.
Загрузочный раздел начинается по смещению 34 блока от начала диска - сразу после таблицы GPT. Его размер я задаю в 256 блоков, это составляет 128кБайт. В принципе для моих целей достаточно и 32кБайт, но я сделал с запасом. Тип раздела "freebsd-boot" означает, что этот раздел выделен специально под загрузчик FreeBSD:
# gpart add -b 34 -s 256 -t freebsd-boot ad4
ad4p1 added
# gpart show ad4
=> 34 312581741 ad4 GPT (149G)
34 256 1 freebsd-boot (128K)
290 312581485 - free - (149G)
Параметр -b указывает смещение начального блока создаваемого раздела, а -s - его размер. Уже начиная с версии 8.0-BETA1 в параметрах утилиты gpart можно опускать эти параметры, а так же использовать суффиксы для указания размера создаваемого раздела. По-умолчанию, смещение начального блока берётся минимальным возможным. А размер, если не указан - всё оставшееся свободное пространство. Например, та же команда для создания загрузочного раздела выглядела бы вот так:
# gpart add -s 128k -t freebsd-boot ad4
Теперь создаю раздел для свопа. Цель создания отдельного раздела для свопа в том, чтобы была возможность записи в него дампа ядра при паниках. А подобная возможность для свопа, который находится на ZFS, вроде бы, ещё не реализована. Размер раздела будет 2ГБайта, в блоках это = 1024*1024*2*2 (в 1кБайте два блока). Тип раздела "freebsd-swap":
# gpart add -b 290 -s 4194304 -t freebsd-swap ad4
ad4p2 added
# gpart show ad4
=> 34 312581741 ad4 GPT (149G)
34 256 1 freebsd-boot (128K)
290 4194304 2 freebsd-swap (2.0G)
4194594 308387181 - free - (147G)
Теперь создаю раздел для ZFS пула, отведу под него 60ГБайт. Тип раздела "freebsd-zfs":
# gpart add -b 4194594 -s 125829120 -t freebsd-zfs ad4
ad4p3 added
# gpart show ad4
=> 34 312581741 ad4 GPT (149G)
34 256 1 freebsd-boot (128K)
290 4194304 2 freebsd-swap (2.0G)
4194594 125829120 3 freebsd-zfs (60G)
130023714 182558061 - free - (87G)
[править] Создание файловой системы
Разделы созданы, можно создавать файловые системы. Для этого нужно загрузить модуль ядра zfs.ko и создать пул на 3-ем разделе:
# kldload zfs
# ls -l /dev/ad4*
crw-r----- 1 root operator 0, 63 29 июл 11:57 /dev/ad4
crw-r----- 1 root operator 0, 79 29 июл 12:42 /dev/ad4p1
crw-r----- 1 root operator 0, 86 29 июл 13:00 /dev/ad4p2
crw-r----- 1 root operator 0, 88 29 июл 13:03 /dev/ad4p3
# zpool create -m /mnt amd64 /dev/ad4p3
# zpool set bootfs=amd64 amd64
После создания пула его корень будет смонтирован в /mnt и определён как загрузочный раздел (через свойство bootfs). Теперь можно создать дополнительные разделы. Предварительно я устанавливаю свойство atime=off для корневой системы, чтобы оно унаследовалось всеми вновь создаваемыми файловыми системами:
# zfs set atime=off amd64
# zfs create amd64/var
# zfs create amd64/usr
# zfs create amd64/tmp
# zfs create amd64/var/tmp
# zfs create -o compression=gzip amd64/var/crash
# zfs create -o compression=gzip -o mountpoint=/mnt/usr/src amd64/src
# zfs create -o compression=gzip -o mountpoint=/mnt/usr/ports amd64/ports
# zfs create -o mountpoint=/mnt/usr/ports/distfiles amd64/distfiles
# zfs create -o mountpoint=/mnt/usr/home amd64/home
# zfs create -o mountpoint=/mnt/usr/local amd64/local
# zfs create -o mountpoint=/mnt/usr/obj amd64/obj
# zfs create amd64/var/db
# chmod 1777 /mnt/tmp /mnt/var/tmp
# zfs list
NAME USED AVAIL REFER MOUNTPOINT
amd64 342K 58,6G 22K /mnt
amd64/tmp 18K 58,6G 18K /mnt/tmp
amd64/usr 95K 58,6G 22K /mnt/usr
amd64/home 18K 58,6G 18K /mnt/usr/home
amd64/local 18K 58,6G 18K /mnt/usr/local
amd64/obj 18K 58,6G 18K /mnt/usr/obj
amd64/ports 37K 58,6G 19K /mnt/usr/ports
amd64/distfiles 18K 58,6G 18K /mnt/usr/ports/distfiles
amd64/src 18K 58,6G 18K /mnt/usr/src
amd64/var 76K 58,6G 22K /mnt/var
amd64/var/crash 18K 58,6G 18K /mnt/var/crash
amd64/var/db 18K 58,6G 18K /mnt/var/db
amd64/var/tmp 18K 58,6G 18K /mnt/var/tmp
Поясню для чего создавать столько отдельных файловых систем:
* различные свойства для файловых систем, например, компрессия для /usr/src, /usr/ports и /var/crash;
* большая гибкость при планировании бэкапов, например, для /var/db, /usr/home и /usr/local можно создавать снэпшоты по отдельному расписанию;
* у меня иногда возникает необходимость смонтировать /usr/obj в другое место (например, в chroot другой системы).
[править] Установка системы
Устанавливать систему я буду традиционным способом - чере sysinstall. Для этого нужно его просто запустить
![Улыбается :)](./images/smilies/icon_e_smile.gif)
* Release Name = 8.0-BETA2-amd64
Это имя должно совпадать с именем каталога, в котором находятся файлы скопированные с ISO образа.
* Install Root = /mnt
Это путь, куда смонтирован корень файловой системы ZFS.
* Media Type = File System
После выбора File System оставляю поле ввода пустым.
После выхода из окна настройки "Options", я выбираю необходимые для установки компоненты "Distributions". Помимо всего прочего, обязательно нужно установить исходные тексты системы. В принципе, это всё. Жмём "Commit" и ждём пока всё скопируется.
[править] Первоначальные настройки и загрузчик
После установки системы переношу ядро с модулями в каталог /mnt/boot/kernel:
# cd /mnt/boot/
# rm -r kernel
# mv GENERIC kernel
Создаю /mnt/etc/fstab и добавляю туда swap раздел, только для именования я буду использовать GPT идентификатор:
# glabel list ad4p2
Geom name: ad4p2
Providers:
1. Name: gptid/bb1e61bd-7c3f-11de-8123-00215a749ae8
Mediasize: 2147483648 (2.0G)
Sectorsize: 512
Mode: r0w0e0
secoffset: 0
offset: 0
seclength: 4194304
length: 2147483648
index: 0
Consumers:
1. Name: ad4p2
Mediasize: 2147483648 (2.0G)
Sectorsize: 512
Mode: r0w0e0
# glabel list ad4p2 | grep gptid >> /mnt/etc/fstab
# vi /mnt/etc/fstab
# cat /mnt/etc/fstab
#Device Mountpoint FStype Options Dump Pass#
/dev/gptid/bb1e61bd-7c3f-11de-8123-00215a749ae8 none swap sw 0 0
Использование идентификатора GPT позволит в дальнейшем забыть про редактирование fstab при изменении именования диска, например, после включения диска в другой SATA порт или использовании эксперементального ahci(4) драйвера. Теперь добавлю загрузку модуля zfs в loader.conf и rc.conf:
# echo 'zfs_enable="YES"' >> /mnt/etc/rc.conf
# echo 'zfs_load="YES"' >> /mnt/boot/loader.conf
# echo 'vfs.root.mountfrom="zfs:amd64"' >> /mnt/boot/loader.conf
В опции загрузчика vfs.root.mountfrom указываю тип файловой системы zfs и имя пула amd64. Теперь нужно скомпилировать новый загрузчик. Нужен он для загрузки системы с ZFS, к сожалению, по умолчанию поддержка ZFS в загрузчике отключена. Для этого я и установливал исходники системы. Поддержка ZFS включается опцией LOADER_ZFS_SUPPORT, её я добавлю в /mnt/etc/src.conf для того, чтобы при дальнейших обновлениях системы случайно не забыть её.
# echo 'LOADER_ZFS_SUPPORT=YES' >> /mnt/etc/src.conf
На флэшке у меня установлена FreeBSD для i386, а сейчас я устанавливаю версию для amd64. Чтобы не "насиловать" флэшку, я создам символическую ссылку /usr/obj на /mnt/usr/obj.
# ln -s /mnt/usr/obj /usr/obj
# ls -l /usr/obj
lrwxr-xr-x 1 root wheel 12 30 июл 06:16 /usr/obj -> /mnt/usr/obj
Вообще, если бы я устанавливал не amd64 версию системы, то я бы смонтировал devfs в /mnt/dev, затем сделал chroot /mnt, собрал там загрузчик и установил его, но в данном случае это проблематично. Поэтому в /etc/src.conf моей флэшки тоже содержится нужная опция:
# cat /etc/src.conf
LOADER_ZFS_SUPPORT=YES
И так, скомпилирую и установлю новый загрузчик:
# cd /mnt/usr/src/sys/boot/
# make DESTDIR=/mnt TARGET=amd64 TARGET_ARCH=amd64 obj depend all
# cd i386/loader/
# make DESTDIR=/mnt TARGET=amd64 TARGET_ARCH=amd64 install
Для make важным параметром здесь является DESTDIR=/mnt. Благодаря ему loader будет установлен в /mnt/boot/.
[править] Финальные шаги
В завершение осталось сделать несколько действий:
* Записать защитный MBR перед таблицей GPT. Он служит для защиты GPT таблицы от операционок и программ, которые ничего не знают о GPT.
# gpart bootcode -b /mnt/boot/pmbr ad4
ad4 has bootcode
* Записать загрузочный код в созданный ранее раздел с типом "freebsd-boot". Этот код содержится в файле /mnt/boot/gptzfsboot.
# gpart bootcode -p /mnt/boot/gptzfsboot -i 1 ad4
* Скопировать zpool.cache, в котором содержится информация о созданном пуле ZFS. Он нужен для того, чтобы свежеустановленная система сразу нашла ZFS пул без предварительного его импорта командой zpool import.
# zpool export amd64 && zpool import amd64
# cp /boot/zfs/zpool.cache /mnt/boot/zfs/
* Изменить точки монтирования для файловых систем.
# zfs set mountpoint=legacy amd64
# zfs set mountpoint=/usr amd64/usr
# zfs set mountpoint=/usr/local amd64/local
# zfs set mountpoint=/usr/src amd64/src
# zfs set mountpoint=/usr/ports amd64/ports
# zfs set mountpoint=/usr/ports/distfiles amd64/distfiles
# zfs set mountpoint=/usr/obj amd64/obj
# zfs set mountpoint=/var amd64/var
# zfs set mountpoint=/tmp amd64/tmp
Для корневой файловой системы точка монтирования установлена в legacy. Т.е. ZFS не будет монтировать корневую файловую систему автоматически. Она будет смонтирована после того как ядро инициирует монтирование корневой файловой системы.
Вот и всё, перезагружаемся и работаем.