USBメモリを用いた zfs root 環境の作り方

FreeBSD 7.0 以降の環境では新しいファイルシステムとして zfs が利用できるようになりました。
ただし、インストールの際はインストーラーからは ufs しか使えません。zfs の耐障害性は非常に
魅力的ですので、USBメモリを用いた zfs root な環境を作るための手順を残しておきます。

2009-04-21 追記
7の手順で | が抜けていたため修正しました。

前提
FreeBSD のインストールがある程度分かっていること。
失敗しても泣かないこと。

環境
amd64 が動くマシン
ブート可能な USB メモリ(1GB程度)
メモリ(最低1GB、できれば4GB以上)
HDD(つめるだけ。raidzを使うのであれば最低3台、raidz2であれば最低4台から)

手順
1.USBメモリに FreeBSD 7.1RC1 をMinimalでインストール

この際に、最終的にこのメモリは /boot のみになることを考えてできる限り
パーテーションを切らないでおいたほうが無難です。ここでは仮に swap のために
100Mだけ切りました。

2.シングルユーザーモードでブートする。

ここで、zpool を構築するために、シングルユーザーモードでブートします。
また / に書き込みが出きるように
#mount -w /
しておきます。

3.zpool を作成する。

zpという名前のプールを作成する場合は
#zpool create zp ad4
ここで、mirror の場合は
#zpool create zp mirror ad4 ad6
また、raidz の場合は
#zpool create zp raidz ad4 ad6 ad8
などとします。
#zpool status zp
で出来たプールを確認しましょう。

4.ファイルシステムを作成する。

できたプールにファイルシステムを作成しましょう。
とりあえず、/usr /var /tmp /home あたりを作ります。
必要であればさらに細かく分けても良いでしょう。

#zfs create zp/usr
#zfs create zp/usr/ports
#zfs create zp/usr/local
#zfs create zp/var
#zfs create zp/var/log
#zfs create zp/tmp
#zfs create zp/home

ここまでで、ひとまず確認してみます。
#zfs list

5.ファイルシステム個別の設定をする。

/var/log を別に切ったのにはわけがあります。zfs は
それぞれ個別に圧縮をかけることができます。テキストログを
保存することが多い /var/log は圧縮をかけておきます。
#zfs set compress=gzip zp/var/log
また、適当にquota をかけます。
#zfs set quota=2G zp/var/log

個の他にも最低限利用する領域を予約したりすることも可能です。

6.rc.conf の設定

起動時にzfs を有効にするように、rc.conf を設定します。
#echo 'zfs_enable="YES"' >> /etc/rc.conf

7.システムをコピー

ブートした /dev/da0s1a 上のシステムを zfs 上にコピーします。
#find -x / | cpio -pmd /zp

8./boot の修正

zp 上の /boot を削除して、/boot を /zp/bootdir/boot に
相対パスでシンボリックリンクを作成します。
#rm -rf /zp/boot
#mkdir /zp/bootdir
#cd /zp
#ln -s bootdir/boot boot

9.loader.conf を設定する

#echo 'zfs_load="YES"' >> /boot/loader.conf
#echo 'vfs.root.mountfrom="zfs:zp"' >> /boot/loader.conf
#echo 'vm.kem_size="1024M"' >> /boot/loader.conf

10.fstab の修正

/bootdir に今までのUSBドライブがマウントされるように修正します。
特にシステムの更新をかけるとき以外は変更する必要もないと思うので
ro でマウントしています。
#vi /zp/etc/fstab
/dev/da0s1a /bootdir ufs ro 1 1

11.zfs のマウントポイントを設定

/zp 以下にマウントされているパーテーションを / にマウントされるように
設定します。

#zfs set mountpoint=/usr zp/usr
#zfs set mountpoint=/usr/local zp/usr/local
#zfs set mountpoint=/usr/ports zp/usr/ports
#zfs set mountpoint=/home zp/home
#zfs set mountpoint=/var zp/var
#zfs set mountpoint=/var/log zp/var/log
#zfs set mountpoint=/tmp zp/tmp
#zfs set mountpoint=legacy zp

12.一旦exportしてimportする

このおまじないをしないとリブートした際に、zpoolが見つからないことがありました。
しなくても大丈夫な場合もありますが、念のためやっておきます。
#zpool export zp
#zpool import zp

13.リブートする。

あとは
#shutdown -r now
とかして、リブートします。
何も問題が無ければ、zfs root な環境であがってきます。

14.SWAPファイルを作成する

USBメモリ上にswap をとっていると、あっという間に書き換え限界がきて壊れるので
スワップも zfs 上にとります。ただしこの方法だとカーネルがクラッシュした際に、
core dump できませんので開発者の方は注意してください。

#zfs create -V 1GB zp/swap
#swapon -a /dev/zvol/zp/swap

スワップがきちんととれたかの確認は
#swapinfo
で確認出来ます。このままだと毎回ブートした際にやらなければいけないので、自動で
出来るように設定します。
#zfs set org.freebsd:swap=on zp/swap
これでリブートしてもスワップが自動的に登録されます。

15.nfs で共有するには

作った領域をnfs で共有するにはsharnfs という変数を設定します。
たとえば、/usr/ports を nfs でき共有できるようにするには
#zfs set sharenfs="-alldir -network 192.168.0.0 -mask 255.255.255.0 -maproot=0" zp/usr/ports
sharenfs の値は on, マウントオプション ,off のいずれかです。マウントオプションは
今までの nfs の exports ファイルのオプションと同様に書きます。
これで自動的に nfs で共有可能になりますので
#showmount -e
などで確認してください。

16.問題が起きたら。

あわてず焦らずマシンをシャットダウンして、USBメモリを抜き、別のマシンにつないで
編集しましょう。