Все мы знаем что время от времени очень редко, практически никогда, но возникает ситуация, при которой внеплановый reset или сбой питания сервера FreeBSD приводит к остановке загрузки с настойчивым требованием запустить fsck от руки. Бывает, сервер соскучился, админ давно его не навещал, а может полнолуние какое, но данное явление в природе встречается. Пришла пора, думаю, переезжать на ZFS — народ рекомендует, стадию бета теста давно прошла, дисковое пространство зря не пропадает, и… в ZFS отсутствует потребность в утилите fsck для проверки целостности файловой системы(!). Проштудировав маны, wiki, лиссяру, пришел к выводу что надо кое-где рашпилем проточить, причесать, лакирнуть и пойдет в массы. Действительно, процесс, по сравнению со стандартным sysinstall, несколько затруднен, но зато быстр как никогда — 2 минуты и сервер с корневым разделом на ZFS готов.
Да, разумеется мы не будем запускать руками всю ту пачку команд, которую рекомендуют запускать, и не будем возиться с sysinstall, а сделаем скрипт автоматической установки, который запустим из режима Fixit. Для этого понадобится DVD или USBstick вариант инсталяции, сервер где хранится скрипт (доступный по ssh).
Процесс инсталяции выглядит так: загружаемся, выбираем режим Fixit — CD/DVD, вешаем IP на сетевуху и запускаем скрипт:
Fixit# ifconfig em0 192.168.1.100/24
Fixit# ssh user@192.168.1.1 'cat /opt/script/zfs-init' | sh
Теперь обратимся к содержимому скрипта, он должен сделать следующее:
1. Разметить диск (GPT — boot, swap0, disk0)
2. Создать ZFS pool (/root, /tmp, /usr, /var, /opt) — раздел /root сделал отдельно, его можно тоже ограничивать в размере
3. Закинуть на ZFS фряху с минимальными конфигами для старта
Скрипт на шелле, просто перечень команд в определенной последовательности. В начале скрипта измените переменные dev (диск), iface (сетевуха), tank (название пула ZFS), hostname (имя хоста), tz (timezone). Вот и он:
#!/bin/sh
# Vars
dev=da0
tank=tank
iface=em0
hostname=core.domain.com
tz="Europe/Kiev"
# gpart
gpart create -s GPT $dev
gpart add -s 64K -t freebsd-boot $dev
gpart add -s 2G -t freebsd-swap -l swap0 $dev
gpart add -t freebsd-zfs -l disk0 $dev
gpart bootcode -b /mnt2/boot/pmbr -p /mnt2/boot/gptzfsboot -i 1 $dev
sysctl kern.geom.debugflags=0x10
# install ZFS
kldload /mnt2/boot/kernel/opensolaris.ko
kldload /mnt2/boot/kernel/zfs.ko
mkdir /boot/zfs
# сreate ZFS pool
zpool create -f $tank /dev/gpt/disk0
zfs set mountpoint=none $tank
zfs set atime=off $tank
zfs set checksum=fletcher4 $tank
zfs create -o compression=off -o exec=on $tank/root
zfs set mountpoint=/$tank $tank/root
zpool set bootfs=$tank/root $tank
zfs create -o compression=on -o exec=on -o setuid=off $tank/tmp
zfs set mountpoint=/$tank/tmp $tank/tmp
zfs create $tank/usr
zfs set mountpoint=/$tank/usr $tank/usr
zfs create $tank/var
zfs set mountpoint=/$tank/var $tank/var
zfs create -o compression=off -o setuid=off $tank/opt
zfs set mountpoint=/$tank/opt $tank/opt
cd /$tank ; ln -s /usr/home home && cd -
mkdir /$tank/var/tmp
chmod 1777 /$tank/var/tmp /$tank/tmp
# install base system
cd /dist/8.2-*
export DESTDIR=/$tank
for dir in base catpages dict doc info lib32 manpages; do (cd $dir ; echo "y" | ./install.sh) ; done
cd src; ./install.sh all
cd ../kernels ; ./install.sh generic
cd /$tank/boot ; cp -Rlp GENERIC/* /$tank/boot/kernel/
# install base configs
cat << EOF > /$tank/etc/rc.conf
zfs_enable="YES"
hostname="$hostname"
ifconfig_$iface="DHCP"
sshd_enable="YES"
ntpd_enable="YES"
ntpd_program="/usr/sbin/ntpd"
ntpd_flags="-p /var/run/ntpd.pid -f /var/db/ntpd.drift"
EOF
cat << EOF > /$tank/etc/ntp.conf
server 82.207.71.6 iburst maxpoll 9
server 91.198.10.4 iburst maxpoll 9
server 79.142.192.4 iburst maxpoll 9
server 193.193.193.107 iburst maxpoll 9
EOF
echo 'zfs_load="YES"' > /$tank/boot/loader.conf
echo "vfs.root.mountfrom=\"zfs:$tank/root\"" >> /$tank/boot/loader.conf
cp /mnt2/usr/share/zoneinfo/$tz /$tank/etc/localtime
cp /boot/zfs/zpool.cache /$tank/boot/zfs/zpool.cache
cat << EOF > /$tank/etc/fstab
# Device Mountpoint FStype Options Dump Pass#
/dev/gpt/swap0 none swap sw 0 0
procfs /proc procfs rw 0 0
EOF
export LD_LIBRARY_PATH=/mnt2/lib
cd /
# correct ZFS mount points and quotas
zfs unmount -a
zfs set mountpoint=/opt $tank/opt
zfs set quota=1G $tank/tmp && zfs set mountpoint=/tmp $tank/tmp
zfs set quota=5G $tank/usr && zfs set mountpoint=/usr $tank/usr
zfs set quota=10G $tank/var && zfs set mountpoint=/var $tank/var
zfs set quota=512m $tank/root && zfs set mountpoint=legacy $tank/root
Во время работы скрипта клавиатуру трогать не надо, после окончания просто перегрузите сервер, и войдите в систему юзером root без пароля.