Автоматическая установка FreeBSD 8.2-RELEASE на ZFS

Все мы знаем что время от времени очень редко, практически никогда, но возникает ситуация, при которой внеплановый 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). Вот и он:

  1. #!/bin/sh
  2. # Vars
  3. dev=da0
  4. tank=tank
  5. iface=em0
  6. hostname=core.domain.com
  7. tz=«Europe/Kiev»
  8. # gpart
  9. gpart create -s GPT $dev
  10. gpart add -s 64K -t freebsd-boot $dev
  11. gpart add -s 2G -t freebsd-swap -l swap0 $dev
  12. gpart add -t freebsd-zfs -l disk0 $dev
  13. gpart bootcode -b /mnt2/boot/pmbr -p /mnt2/boot/gptzfsboot -i 1 $dev
  14. sysctl kern.geom.debugflags=0x10
  15. # install ZFS
  16. kldload /mnt2/boot/kernel/opensolaris.ko
  17. kldload /mnt2/boot/kernel/zfs.ko
  18. mkdir /boot/zfs
  19. # сreate ZFS pool
  20. zpool create -f $tank /dev/gpt/disk0
  21. zfs set mountpoint=none $tank
  22. zfs set atime=off $tank
  23. zfs set checksum=fletcher4 $tank
  24. zfs create -o compression=off -o exec=on $tank/root
  25. zfs set mountpoint=/$tank $tank/root
  26. zpool set bootfs=$tank/root $tank
  27. zfs create -o compression=on -o exec=on -o setuid=off $tank/tmp
  28. zfs set mountpoint=/$tank/tmp $tank/tmp
  29. zfs create $tank/usr
  30. zfs set mountpoint=/$tank/usr $tank/usr
  31. zfs create $tank/var
  32. zfs set mountpoint=/$tank/var $tank/var
  33. zfs create -o compression=off -o setuid=off $tank/opt
  34. zfs set mountpoint=/$tank/opt $tank/opt
  35. cd /$tank ; ln -s /usr/home home && cd —
  36. mkdir /$tank/var/tmp
  37. chmod 1777 /$tank/var/tmp /$tank/tmp
  38. # install base system
  39. cd /dist/8.2*
  40. export DESTDIR=/$tank
  41. for dir in base catpages dict doc info lib32 manpages; do (cd $dir ; echo «y» | ./install.sh) ; done
  42. cd src; ./install.sh all
  43. cd ../kernels ; ./install.sh generic
  44. cd /$tank/boot ; cp -Rlp GENERIC/* /$tank/boot/kernel/
  45. # install base configs
  46. cat << EOF > /$tank/etc/rc.conf
  47. zfs_enable=«YES»
  48. hostname=«$hostname«
  49. ifconfig_$iface=«DHCP»
  50. sshd_enable=«YES»
  51. ntpd_enable=«YES»
  52. ntpd_program=«/usr/sbin/ntpd»
  53. ntpd_flags=«-p /var/run/ntpd.pid -f /var/db/ntpd.drift»
  54. EOF
  55. cat << EOF > /$tank/etc/ntp.conf
  56. server 82.207.71.6 iburst maxpoll 9
  57. server 91.198.10.4 iburst maxpoll 9
  58. server 79.142.192.4 iburst maxpoll 9
  59. server 193.193.193.107 iburst maxpoll 9
  60. EOF
  61. echo ‘zfs_load=»YES»‘ > /$tank/boot/loader.conf
  62. echo «vfs.root.mountfrom=zfs:$tank/root« >> /$tank/boot/loader.conf
  63. cp /mnt2/usr/share/zoneinfo/$tz /$tank/etc/localtime
  64. cp /boot/zfs/zpool.cache /$tank/boot/zfs/zpool.cache
  65. cat << EOF > /$tank/etc/fstab
  66. # Device          Mountpoint     FStype  Options         Dump    Pass#
  67. /dev/gpt/swap0    none           swap    sw              0       0
  68. procfs            /proc          procfs  rw              0       0
  69. EOF
  70. export LD_LIBRARY_PATH=/mnt2/lib
  71. cd /
  72. # correct ZFS mount points and quotas
  73. zfs unmount -a
  74. zfs set mountpoint=/opt $tank/opt
  75. zfs set quota=1G   $tank/tmp   && zfs set mountpoint=/tmp   $tank/tmp
  76. zfs set quota=5G   $tank/usr   && zfs set mountpoint=/usr   $tank/usr
  77. zfs set quota=10G  $tank/var   && zfs set mountpoint=/var   $tank/var
  78. zfs set quota=512m $tank/root  && zfs set mountpoint=legacy $tank/root

Во время работы скрипта клавиатуру трогать не надо, после окончания просто перегрузите сервер, и войдите в систему юзером root без пароля.

Материалы по теме: RootOnZFS/GPTZFSBootУстановка FreeBSD с использованием ZFS в качестве основной.

Удачи