FreeBSD/ZFS

ZFS boot の設定方法

  • 参考 http://wiki.freebsd.org/RootOnZFS
    • 以下に書いてあることはほとんど同じなので、こっち見たほうが早いかもしれない。
    • FreeBSD 8.x までの内容。FreeBSD 9.x 以降は作成予定。理屈は同じ。
  • ここでは GPT ディスクを使う。
    • GPT では OS のデュアルブート不可。どうしてもやりたい場合は GPT 対応のブートローダが必要。(Grub2 とか)
  • Swap は GPT パーティションとする。
    • ZFS では Swap 領域をカーネルダンプに使うことができない。
  • zfs set mountpoint は原則使わない。/etc/fstab を使用する。
    • 自動マウントにしていると、いつマウントされるのか制御できず余計な時にマウントされて非常に厄介なため。
    • ただし、ファイルシステム階層で自動マウントしたい場合は zfs set mountpoint を使う。(/usr/home/* 配下とか。)
  • telnetd を一時的に動かして、外部の端末からコマンドを投入するのが得策かと思う。
    • Fixit 環境で sshd を動かす手順は検討中。ホスト鍵作成あたりが厄介。

下準備

  • CDROM/DVD か USB にて起動。
  • 以下、自分の環境に合わせて変更する。
    • Country Selection
      • 110 Japan を選択する。
    • System Console Keymap
      • Japanese 106 を選択する。
  • sysinstall Main Menu
    • Fixit を選択する。
  • Plese choose a fixit option
    • 起動したメディアに合わせて CDROM/DVD か USB を選択。
  • dmesg から接続したディスクを検索する。
    # dmesg | grep "MB <"
    ad0: 20480MB <VBOX HARDDISK 1.0> at ata0-master UDMA33

パーティションを作成し、ZFS プールを作成する。

シングルディスク構成の場合

  • パーティションテーブルを初期化する。(これは必要に応じて。メディアの認識の都合で zfs.ko の読み込み前であるべき。)
    # dd if=/dev/zero of=/dev/ad0 bs=1m count=1
  • GPT パーティションテーブルを作成する
    # gpart create -s gpt ad0
  • ブートパーティションを作成する。
    # gpart add -s 64K -t freebsd-boot ad0
    • 4KBセクタのHDDの場合は、-b 40 をつけておく。(-b 1024 とかの方が良い?)
    • -b 40 である根拠は、先頭34セクタは GPT が予約。次の4KBの区切りは40セクタ目であるため。(5ブロック目)
    • GPT の場合はシリンダは気にしなくても良い。MBR だと、ツールによっては区切りをシリンダ単位でしか設定できないことがある。
  • Swap パーティションを作成する。(容量はRAMの2~4倍程度取っておく。後から拡張困難なので注意。)
    # gpart add -s 4G -t freebsd-swap -l swap0 ad0
  • 残りを ZFS パーティションとして作成する。
    # gpart add -t freebsd-zfs -l disk0 ad0
    • 4KBにならない最後の端数を切り落としたほうがいいかもしれない。セクタ数を8で割って、あまりを求める。
    • 終端33セクタはGPTが予約済みで、ここは最初から分割対象から外れているので、気にせず、最後まで使って良い。
    • RAID などだと生ディスクの終端セクタが管理用に使用されていることがあるが、RAID化されたディスク上では見えない位置になるので、気にせず最後まで使って良い。
  • Protected MBR(pmbr) と gptzfsboot ローダを入れる。
    # gpart bootcode -b /mnt2/boot/pmbr -p /mnt2/boot/gptzfsboot -i 1 ad0
    ad0 has bootcode
    • -i 1 は 1番目のパーティション(freebsd-boot)を指す。
  • ZFS カーネルモジュールを読み込む
    # kldload /mnt2/boot/kernel/opensolaris.ko
    # kldload /mnt2/boot/kernel/zfs.ko
  • /boot/zfs/zfs.cache を残すために、/boot/zfs ディレクトリを作る。
    # mkdir /boot/zfs
  • ZFS プールを作成する。
    # zpool create zroot /dev/gpt/disk0
    • zroot という名前は好きなように。
    • パーティションを切り直した時に、前のプール情報が残っていてエラーになってしまう場合がある。その時は破棄して作り直す。
      # zpool list
      # zpool destroy zroot
    • 以下のエラーの場合は、zpool create -f で強制的に作り直す。
      invalid vdev specification
      use '-f' to override the following errors:
      /dev/gpt/disk0 is part of potentially active pool 'zroot'

ミラー構成の場合

  • 2つのディスクでまったく同じことをやる。(ad0 で実行した後、ad1 で置き換えて実行する)
    • パーティションテーブルを初期化する。(これは必要に応じて。メディアの認識の都合で zfs.ko の読み込み前であるべき。)
      # dd if=/dev/zero of=/dev/ad0 bs=1m count=1
      # dd if=/dev/zero of=/dev/ad1 bs=1m count=1
    • GPT パーティションテーブルを作成する
      # gpart create -s gpt ad0
      # gpart create -s gpt ad1
    • ブートパーティションを作成する。
      # gpart add -s 64K -t freebsd-boot ad0
      # gpart add -s 64K -t freebsd-boot ad1
    • Swap パーティションを作成する。(容量はRAMの2~4倍程度取っておく。後から拡張困難なので注意。)
      # gpart add -s 4G -t freebsd-swap -l swap0 ad0
      # gpart add -s 4G -t freebsd-swap -l swap1 ad1
    • 残りを ZFS パーティションとして作成する。
      # gpart add -t freebsd-zfs -l disk0 ad0
      # gpart add -t freebsd-zfs -l disk1 ad1
    • Protected MBR(pmbr) と gptzfsboot ローダを入れる。
      # gpart bootcode -b /mnt2/boot/pmbr -p /mnt2/boot/gptzfsboot -i 1 ad0
      # gpart bootcode -b /mnt2/boot/pmbr -p /mnt2/boot/gptzfsboot -i 1 ad1
      • -i 1 は 1番目のパーティション(freebsd-boot)を指す。
  • ZFS カーネルモジュールを読み込む
    # kldload /mnt2/boot/kernel/opensolaris.ko
    # kldload /mnt2/boot/kernel/zfs.ko
  • /boot/zfs/zfs.cache を残すために、/boot/zfs ディレクトリを作る。
    # mkdir /boot/zfs
  • ZFS プールを作成する。
    # zpool create zroot mirror /dev/gpt/disk0 /dev/gpt/disk1
    • zroot という名前は好きなように。
    • パーティションを切り直した時に、前のプール情報が残っていてエラーになってしまう場合がある。その時は破棄して作り直す。
      # zpool list
      # zpool destroy zroot

ZFS でファイルシステムを作成する。

方針

  • /tmp は tmpfs を使う。
  • /var/run は tmpfs を使う。 一部のアプリが永続的なディレクトリ構成をここに置くため、tmpfs はダメ。
  • ZFS はスナップショットをまとめて取りたい集合で切っていく。
  • zroot/system 配下に OS のファイルシステム /, /usr, /var を配置する。
  • / は zroot/system/sysroot, /usr は zroot/system/usr で割り当てる。こう分離しないと / の差し替えが非常に困難になる。
  • zroot/home としてユーザーのホームディレクトリを作成する。

手順

  • チェックサムは fletcher4 を使う。(デフォルトは fletcher2。スピードより安全を取るなら sha256。)
    # zfs set checksum=fletcher4 zroot
  • スナップショットにごみがたまるだけなので atime は設定しない。(ごく稀にこれがダメなアプリがある模様なので要注意)
    # zfs set atime=off zroot
  • zroot のマウントポイントを legacy にする。(ZFS の自動マウントでひどい目に遭ったので ZFS のマウントは当てにしない。)
    # zfs set mountpoint=legacy zroot
  • 各ファイルシステムを切る。
    # zfs create                                               zroot/system
    # zfs create                                               zroot/system/sysroot
    # zfs create                                               zroot/system/usr
    # zfs create                                               zroot/system/var
    # zfs create -o compression=lzjb -o exec=off -o setuid=off zroot/system/var/crash
    # zfs create                     -o exec=off -o setuid=off zroot/system/var/db
    # zfs create -o compression=lzjb -o exec=on  -o setuid=off zroot/system/var/db/pkg
    # zfs create                     -o exec=off -o setuid=off zroot/system/var/empty
    # zfs create -o compression=lzjb -o exec=off -o setuid=off zroot/system/var/log
    # zfs create -o compression=lzjb -o exec=off -o setuid=off zroot/system/var/mail
    # zfs create                                               zroot/system/var/run
    # zfs create -o compression=lzjb -o exec=on  -o setuid=off zroot/system/var/tmp
    # zfs create -o compression=lzjb -o exec=on  -o setuid=off zroot/ports
    # zfs create                     -o exec=off -o setuid=off zroot/ports/distfiles
    # zfs create                     -o exec=off -o setuid=off zroot/ports/packages
    # zfs create -o compression=lzjb -o exec=off -o setuid=off zroot/src
    # zfs create                                               zroot/home
  • ブートするファイルシステムを設定する。(/boot のありか)
    # zpool set bootfs=zroot/system/sysroot zroot
  • /tmproot 配下に仮のファイルシステムを作成する。
    # mkdir /tmproot
    # mount -t zfs zroot/system/sysroot /tmproot
    # mkdir /tmproot/tmp
    # chmod 1777 /tmp
    # mkdir /tmproot/usr
    # mount -t zfs zroot/system/usr /tmproot/usr
    # mkdir /tmproot/usr/home
    # mount -t zfs zroot/home /tmproot/usr/home
    # ln -s /usr/home /tmproot/home
    # mkdir /tmproot/usr/ports
    # mount -t zfs zroot/ports /tmproot/usr/ports
    # mkdir /tmproot/usr/ports/distfiles
    # mount -t zfs zroot/ports/distfiles /tmproot/usr/ports/distfiles
    # mkdir /tmproot/usr/ports/packages
    # mount -t zfs zroot/ports/packages /tmproot/usr/ports/packages
    # mkdir /tmproot/usr/src
    # mount -t zfs zroot/src /tmproot/usr/src
    # mkdir /tmproot/var
    # mount -t zfs zroot/system/var /tmproot/var
    # mkdir /tmproot/var/crash
    # mount -t zfs zroot/system/var/crash /tmproot/var/crash
    # mkdir /tmproot/var/db
    # mount -t zfs zroot/system/var/db /tmproot/var/db
    # mkdir /tmproot/var/db/pkg
    # mount -t zfs zroot/system/var/db/pkg /tmproot/var/db/pkg
    # mkdir /tmproot/var/empty
    # mount -t zfs zroot/system/var/empty /tmproot/var/empty
    # mkdir /tmproot/var/log
    # mount -t zfs zroot/system/var/log /tmproot/var/log
    # mkdir /tmproot/var/mail
    # mount -t zfs zroot/system/var/mail /tmproot/var/mail
    # mkdir /tmproot/var/run
    # mount -t zfs zroot/system/var/run /tmproot/var/run
    # mkdir /tmproot/var/tmp
    # mount -t zfs zroot/system/var/tmp /tmproot/var/tmp
    # chmod 1777 /tmproot/var/tmp
  • FreeBSD の各種ファイルを入れる
    # cd /dist/8.0-*
    # export DESTDIR=/tmproot
    # for dir in base catpages dict doc games info lib32 manpages ports
    # do
    #     (cd $dir ; ./install.sh) ;
    # done
    # cd src ; ./install.sh all
    # cd ../kernels ; ./install.sh generic
    # cd /tmproot/boot ; cp -Rlp GENERIC/* /tmproot/boot/kernel/
  • /var/empty を read only にする。
    # zfs set readonly=on zroot/system/var/empty
  • chroot する。
    # chroot /tmproot
  • /etc/fstab に以下を入れる
    # Device                Mountpoint      FStype  Options         Dump    Pass#
    /dev/gpt/swap0          none            swap    sw              0       0
    zroot/system/usr        /usr            zfs     rw              0       0
    zroot/system/var        /var            zfs     rw              0       0
    zroot/system/var/crash  /var/crash      zfs     rw              0       0
    zroot/system/var/db     /var/db         zfs     rw              0       0
    zroot/system/var/db/pkg /var/db/pkg     zfs     rw              0       0
    zroot/system/var/empty  /var/empty      zfs     ro              0       0
    zroot/system/var/log    /var/log        zfs     rw              0       0
    zroot/system/var/mail   /var/mail       zfs     rw              0       0
    zroot/system/var/run    /var/run        zfs     rw              0       0
    zroot/system/var/tmp    /var/tmp        zfs     rw              0       0
    tmpfs                   /tmp            tmpfs   rw,mode=1777,size=1073741824 0 0
    tmpfs                   /ports/tmp      tmpfs   rw,size=1073741824 0 0
    zroot/ports             /usr/ports      zfs     rw              0       0
    zroot/ports/distfiles   /usr/ports/distfiles    zfs     rw              0      0
    zroot/ports/packages    /usr/ports/packages     zfs     rw              0      0
    zroot/src               /usr/src        zfs     rw              0       0
    zroot/mydata            /usr/mydata     zfs     rw              0       0
  • /etc/rc.conf を設定する。(hostname とか ifconfig はシステムに応じて変更を。)
    echo 'zfs_enable="YES"' >> /etc/rc.conf
    echo 'hostname="zfsroot.localdomain"' >> /etc/rc.conf
    echo 'ifconfig_re0="DHCP"' >> /etc/rc.conf
  • /boot/loader.conf を設定する。
    echo 'zfs_load="YES"' >> /boot/loader.conf
    echo 'vfs.root.mountfrom="zfs:zroot/system/sysroot"' >> /boot/loader.conf
  • 7.0~7.2R,8.0R では以下の手順でブートローダの再構築が必要
    # echo 'LOADER_ZFS_SUPPORT=YES' >> /etc/src.conf
    # mount -t devfs devfs /dev
    # export DESTDIR=""
    # cd /usr/src/sys/boot
    # make obj
    # make depend
    # make
    # cd i386/loader
    # make install
  • aliases を再作成。(必要?)
    # cd /etc/mail
    # make aliases
  • /dev はもう不要なのでアンマウント
    # umount /dev
  • chroot 環境を脱出
    # exit
  • ZFS の情報をブートローダ用にコピー
    # cp /boot/zfs/zpool.cache /tmproot/boot/zfs/zpool.cache
    • mkdir /boot/zfs を忘れているとできない。その場合は以下で作り直し。
      # mkdir /boot/zfs; zfs export zroot; zfs import zroot
  • Fixit 環境を出る。
    # exit
  • 再起動する。
  • シングルユーザーでログインする。
  • /usr/home を自動マウントにする。
    # zfs set mountpoint=/usr/home zroot/home
  • ユーザーを追加するときには、先にファイルシステムを切り、ユーザー単位でのスナップショット権限を与える。
    # zfs create zroot/home/alice
    # adduser
    ...
    # zfs allow alice mount,create,snapshot,rename,destroy,clone,promote,send,receive zroot/home/alice

謎のスクリプト

動作保証なし。 Use at your own risk.

#!/bin/sh

if [ $# -ne 4 ]; then
    echo "usage: create_ZFS_root_single.sh DISK0 SWAP_SIZE GPT_DISK0_NAME POOL_NAME"
    echo "ex. ./create_ZFS_root_single.sh ad0 2g disk0 zroot"
    exit 1
fi

DISK0=$1
SWAP_SIZE=$2
GPT_DISK0_NAME=$3
POOL_NAME=$4

echo "ERASE ALL DATA ON $DISK0. OK? enter 'yes'"
read ANSWER
if [ "$ANSWER" != "yes" ]; then
    echo "bye!"
    exit 2
fi

echo Delete partition info.
dd if=/dev/zero of=/dev/$DISK0 bs=1m count=1

echo Create partition.
gpart create -s gpt $DISK0
gpart add -s 64K -t freebsd-boot $DISK0
gpart add -s $SWAP_SIZE -t freebsd-boot $DISK0
gpart add -t freebsd-zfs -l $GPT_DISK0_NAME $DISK0
gpart bootcode -b /mnt2/boot/pmbr -p /mnt2/boot/gptzfsboot -i 1 $DISK0

echo Load ZFS module
kldload /mnt2/boot/kernel/opensolaris.ko
kldload /mnt2/boot/kernel/zfs.ko

echo ZFS check
zpool import
echo "NO POOL CHECK OK? enter 'yes'"
read ANSWER
if [ "$ANSWER" != "yes" ]; then
    echo "bye!"
    exit 2
fi

echo create ZFS pool
mkdir /boot/zfs
zpool create $POOL_NAME /dev/gpt/$GPT_DISK0_NAME

echo create ZFS filesystem
mkdir /tmproot
zfs set checksum=fletcher4 $POOL_NAME
zfs set atime=off $POOL_NAME
zfs set mountpoint=legacy $POOL_NAME

zfs create                                               ${POOL_NAME}/system
zfs create                                               ${POOL_NAME}/system/sysroot
zfs create                                               ${POOL_NAME}/system/usr
zfs create                                               ${POOL_NAME}/system/var
zfs create -o compression=lzjb -o exec=off -o setuid=off ${POOL_NAME}/system/var/crash
zfs create                     -o exec=off -o setuid=off ${POOL_NAME}/system/var/db
zfs create -o compression=lzjb -o exec=on  -o setuid=off ${POOL_NAME}/system/var/db/pkg
zfs create                     -o exec=off -o setuid=off ${POOL_NAME}/system/var/empty
zfs create -o compression=lzjb -o exec=off -o setuid=off ${POOL_NAME}/system/var/log
zfs create -o compression=lzjb -o exec=off -o setuid=off ${POOL_NAME}/system/var/mail
zfs create -o compression=lzjb -o exec=on  -o setuid=off ${POOL_NAME}/system/var/tmp
zfs create -o compression=lzjb -o exec=on  -o setuid=off ${POOL_NAME}/ports
zfs create                     -o exec=off -o setuid=off ${POOL_NAME}/ports/distfiles
zfs create                     -o exec=off -o setuid=off ${POOL_NAME}/ports/packages
zfs create -o compression=lzjb -o exec=off -o setuid=off ${POOL_NAME}/src
zfs create                                               ${POOL_NAME}/home

zpool set bootfs=${POOL_NAME}/system/sysroot ${POOL_NAME}

echo mount ZFS filesystem
mount -t zfs ${POOL_NAME}/system/sysroot /tmproot
mkdir /tmproot/tmp
chmod 1777 /tmp
mkdir /tmproot/usr
mount -t zfs ${POOL_NAME}/system/usr /tmproot/usr
mkdir /tmproot/usr/home
mount -t zfs ${POOL_NAME}/home /tmproot/usr/home
ln -s /usr/home /tmproot/home
mkdir /tmproot/usr/ports
mount -t zfs ${POOL_NAME}/ports /tmproot/usr/ports
mkdir /tmproot/usr/ports/distfiles
mount -t zfs ${POOL_NAME}/ports/distfiles /tmproot/usr/ports/distfiles
mkdir /tmproot/usr/ports/packages
mount -t zfs ${POOL_NAME}/ports/packages /tmproot/usr/ports/packages

mkdir /tmproot/usr/src
mount -t zfs ${POOL_NAME}/src /tmproot/usr/src

mkdir /tmproot/var
mount -t zfs ${POOL_NAME}/system/var /tmproot/var
mkdir /tmproot/var/crash
mount -t zfs ${POOL_NAME}/system/var/crash /tmproot/var/crash
mkdir /tmproot/var/db
mount -t zfs ${POOL_NAME}/system/var/db /tmproot/var/db
mkdir /tmproot/var/db/pkg
mount -t zfs ${POOL_NAME}/system/var/db/pkg /tmproot/var/db/pkg
mkdir /tmproot/var/empty
mount -t zfs ${POOL_NAME}/system/var/empty /tmproot/var/empty
mkdir /tmproot/var/log
mount -t zfs ${POOL_NAME}/system/var/log /tmproot/var/log
mkdir /tmproot/var/mail
mount -t zfs ${POOL_NAME}/system/var/mail /tmproot/var/mail
mkdir /tmproot/var/tmp
mount -t zfs ${POOL_NAME}/system/var/tmp /tmproot/var/tmp
chmod 1777 /tmproot/var/tmp

echo "Extract FreeBSD distribution. OK? enter 'yes'"
read ANSWER
if [ "$ANSWER" != "yes" ]; then
    echo "bye!"
    exit 2
fi

echo extract FreeBSD distribution
cd /dist/8.0-*
export DESTDIR=/tmproot
for dir in base catpages dict doc games info lib32 manpages ports
do
    (cd $dir ; ./install.sh) ;
done

cd src ; ./install.sh all

cd ../kernels ; ./install.sh generic

cd /tmproot/boot ; cp -Rlp GENERIC/* /tmproot/boot/kernel/

echo set configuration

zfs set readonly=on ${POOL_NAME}/system/var/empty
#exit 1

cat <<CHROOTSCRIPT_EOT >/tmproot/zfssinglechroot.sh
#!/bin/sh
cat <<EOT >> /etc/fstab
# Device                Mountpoint      FStype  Options         Dump    Pass#
/dev/gpt/swap0          none            swap    sw              0       0
zroot/system/sysroot    /               zfs     rw              0       0
zroot/system/usr        /usr            zfs     rw              0       0
zroot/ports             /usr/ports      zfs     rw              0       0
zroot/ports/distfiles   /usr/ports/distfiles    zfs     rw              0      0
zroot/ports/packages    /usr/ports/packages     zfs     rw              0      0
zroot/src               /usr/src        zfs     rw              0       0
zroot/system/var        /var            zfs     rw              0       0
zroot/system/var/crash  /var/crash      zfs     rw              0       0
zroot/system/var/db     /var/db         zfs     rw              0       0
zroot/system/var/db/pkg /var/db/pkg     zfs     rw              0       0
zroot/system/var/empty  /var/empty      zfs     rw              0       0
zroot/system/var/log    /var/log        zfs     rw              0       0
zroot/system/var/mail   /var/mail       zfs     rw              0       0
tmpfs                   /var/run        tmpfs   rw,size=10000000 0 0
zroot/system/var/tmp    /var/tmp        zfs     rw              0       0
tmpfs                   /tmp            tmpfs   rw,mode=1777,size=1073741824 0 0
tmpfs                   /ports/tmp      tmpfs   rw,size=1073741824 0 0
EOT

echo 'zfs_enable="YES"' >> /etc/rc.conf
echo 'hostname="zfsroot.localdomain"' >> /etc/rc.conf
echo 'ifconfig_re0="DHCP"' >> /etc/rc.conf

echo 'zfs_load="YES"' >> /boot/loader.conf
echo 'vfs.root.mountfrom="zfs:zroot/system/sysroot"' >> /boot/loader.conf

echo reinstall boot loader

echo 'LOADER_ZFS_SUPPORT=YES' >> /etc/src.conf

mount -t devfs devfs /dev
export DESTDIR=""
cd /usr/src/sys/boot
make obj
make depend
make
cd i386/loader
make install

cd /etc/mail
make aliases

umount /dev
exit
CHROOTSCRIPT_EOT

chmod +x /tmproot/zfssinglechroot.sh

chroot /tmproot /zfssinglechroot.sh
rm /tmproot/zfssinglechroot.sh

cp /boot/zfs/zpool.cache /zroot/boot/zfs/zpool.cache

echo Exit Fixit and reboot, then enter single mode.
echo and then enter follow command.
echo # zfs set mountpoint=/usr/home zroot/home
echo # exit

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2012-04-17 (火) 23:16:14 (2350d)