うちのサーバは gptboot にてGPTのUFSから起動した後、 ZFSをルート・ディレクトリにマウント(legacy)するという手法を使っています。しかし、先日 FreeBSD のインストーラで ZFS Root を構成してみると、gptzfsboot を用いて ZFS 内のカーネルを直接引っ張ってくるという方法で起動していました。こちらの方がスマートですので切り替えたいところですが、失敗すると悲惨なので、まずは仮想PCのテスト環境で実験してみます。
上図 左側が現状の構成、右側はこれから変更したい構成です。まず大前提として、このサーバはキーボードやディスプレイが繋がっていません。ですから可能ならネットワーク上で入って稼動状態でごにょごにょした後再起動したら右の構成になってる・・・というのが理想的だったのですが、結果的にはどうやったら良いか分かりませんでした。ada1のZFSがルートにlegacyでマウントされているのですが、稼動状態でこれをどうしても unmount できませんでした。ということで、下記の方法はサーバを手元に持ってきてデイスプレイとキーボードを接続、DVDからFixit 起動してメンテナンスするという条件になります。
まずは実験環境ですので、VirtualBoxでFreeBSDのインストールCDを挿入してCDから起動させます。
続いてShellを選択してコマンドラインに入ります。
Shellを起動すると、ルート・ディレクトリはDVDに入っているディスクイメージが ReadOnly で、 /var と /tmp にはメモリファイルシステムがマウントされます。
まずはなにはともあれ、 ZFS Pool をマウントします。-R オプションで 仮に /mnt にマウントするのがミソです。
# zpool import -f -R /mnt tank
cannot mount '/mnt/tank' : failed to create mountpoint
cannot mount '/mnt/usr' : failed to create mountpoint
cannot mount '/mnt/var' : failed to create mountpoint
tank/root という名称のファイルシステムが legacy のため、本来 /mnt にマウントされるべきなのですが、どうやら legacy はマウントされないために /mnt/tank, /mnt/usr, /mnt/var というディレクトリが作成できず(/mnt が Read Onlyのため)エラーが出ているようです。
ということで、ひとまず tank/root のmountpoint を legacy から /mnt に変更します。
# zfs set mountpoint=/ tank/root
最初は mountpoint=/mnt で実行してみたのですが、 cannot mount '/mnt/mnt': failed to create mountpoint というエラーになりました。どうやら -R は zpool import 時だけでなく、その後のファイルシステム操作を通して有効のようです。
legacyから /mnt に変更できたので、一旦 export して再度 import します。
# zpool export tank
# zpool import -R /mnt tank
今度は /mnt, /mnt/tank, /mnt/usr, /mnt/var が無事にマウントされました。
うちのサーバはこちらの手順の通りに ZFS Root を構成しています。FreeBSDのインストーラはこんな感じになっていますので、順に修正していきます。
/etc/fstab を編集して /bootdir をマウントしている所を消す
ada0p2に /boot の中身が入っているので、一旦マウントしてコピーする
# mount /dev/ada0p2 /mnt/mnt
# rm /mnt/boot (← ZFSの中のシンボリックリンクを消す)
# cd /mnt/mnt (← /dev/ada0p2 に移動)
# tar cf - boot | (cd /mnt ; tar xf - )
# cd /
# sync
# umount /mnt/mnt
上記の手順で UFS に入っていた /boot が ZFSの中に入りました。続いて /boot 下を変更します。
/mnt/boot/loader.conf の vfs.root.mountfrom="zfs:tank/root" を消す
起動するファイルシステムを指定
# zpool set bootfs=tank/root tank
gptzfsbootの書き込み
# gpart bootcode -p /mnt/boot/gptzfsboot -i 1 ada0
これにて全工程完了。再起動してCDを取り出し
下の画面まで到達すれば成功しています。
mount状況は下記の通り
ここまで確認できたら、ada0p2 の UFS は必要ないはずですので、newfs しても動作するはずです。
# newfs /dev/ada0p2
はい、ちゃんと再起動できました。めでたしめでたし。ということで、実験環境では無事に完全ZFS Rootにすることが出来ました。後は本番で上の手順を見ながら間違えないように実行するのみですね(^_^)。
ちなみに、今回の手順では UFS が不要になりましたので、いっそのこと swap も zvol にしちゃえば起動ドライブは gptzfsboot とpmbr が収納できればOKですので、USBメモリや SATA 端子に差し込むような半導体ドライブでも問題無いかもしれませんね。或いは プチフリしまくりで実用的でないSSDとか。このドライブには一切書き込みは行われないはずなので、レベルウェアリングが起こることも 無ければ書き込み回数を気にする必要も無いでしょう。