ESXi上のFreeBSDで,2台までならどのディスクが壊れても起動できる環境を作る

やりたい事

ブートローダ及びファイルシステムを冗長構成にして構築する.障害を想定してディスクを抜き,この状態でも正常に起動することを確認することで,冗長構成が機能することを確認する.

実機でやる環境が無いので ESXi 上の環境でお試しでやる.

8.1-RELEASE でやってみたが失敗

下記のような手順でインストールしたが,任意のディスクを抜くと起動に失敗した.この問題は 9.0-current では解決されているようなので,それで再度行った. (または8.1-RELEASEのp?でも解決しているらしい,パッチなしだと失敗する)

9.0-CURRENT 環境を作りつつ zfs の準備をする

まずは普通に 8.1-RELEASE をインストール.その上で 9.0-CURRENT 環境を作る.以下は 8.1-RELEASE環境での9.0-CURRENT のインストール方法.
/etc/src.conf を作成する

SUP_UPDATE?=    yes
SUP=            /usr/bin/csup
SUPFLAGS?=      -g -L 2
SUPHOST?=       cvsup.jp.FreeBSD.org
SUPFILE= /usr/share/examples/cvsup/standard-supfile

/usr/share/example/cvsup/standard-supfile を書き換える

 *default release=cvs tag=.

current のソースコードを取得し,環境/カーネルを構築する

cd /usr/src
make update
make buildworld
make buildkernel

この間に HDD の準備をする.HDD を初期化し,GPT 領域にし,ブート用パーティションzfsパーティションに分ける.(ブートローダは,環境/カーネルを構築後にインストールする)
下記のシェルスクリプトを実行する(今回は zfs 用の HDD を6つ用意したので下記となった)

#!/bin/sh
for i in 1 2 3 4 5 6; do
  dd if=/dev/zero of=/dev/da${i} count=1 bs=512
  gpart create -s GPT da${i}
  gpart add -b 34 -s 128 -t freebsd-boot da${i}
  gpart add -t freebsd-zfs -l disk${i} da${i}
done

プールの作成.プール名は zpool とし,raidz2 で作成した.

zpool create zpool raidz2 /dev/gpt/disk[123456]

ブートプールの設定

zpool set bootfs=zpool zpool

ファイルシステムの設定

zfs set checksum=fletcher4 zpool
zfs create -o compression=on    -o exec=on      -o setuid=off   zpool/tmp
chmod 1777 /zpool/tmp/
zfs create zpool/usr
zfs create zpool/home
zfs create -o compression=lzjb  -o setuid=off                   zpool/usr/ports
zfs create -o compression=off   -o exec=off     -o setuid=off   zpool/usr/ports/distfiles
zfs create -o compression=off   -o exec=off     -o setuid=off   zpool/usr/ports/packages
zfs create -o compression=lzjb  -o exec=off     -o setuid=off   zpool/usr/src
zfs create                                                      zpool/var
zfs create -o compression=lzjb  -o exec=off     -o setuid=off   zpool/var/crash
zfs create                      -o exec=off     -o setuid=off   zpool/var/db
zfs create -o compression=lzjb  -o exec=on      -o setuid=off   zpool/var/db/pkg
zfs create                      -o exec=off     -o setuid=off   zpool/var/empty
zfs create -o compression=lzjb  -o exec=off     -o setuid=off   zpool/var/log
zfs create -o compression=gzip  -o exec=off     -o setuid=off   zpool/var/mail
zfs create                      -o exec=off     -o setuid=off   zpool/var/run
zfs create -o compression=lzjb  -o exec=on      -o setuid=off   zpool/var/tmp
chmod 1777 /zpool/var/tmp

この先は buildworld/buildkernel が終わるまで待つ.終わったら環境/カーネルをインストールする

make installworld DESTDIR=/zpool
make installkernel DESTDIR=/zpool

gptzfsboot を全ディスクに書き込む.これでどのディスクが壊れても他のディスクの gptzfsboot で起動するようになるはずだ.

#!/bin/sh
for i in 1 2 3 4 5; do
  gpart bootcode -b /zpool/boot/pmbr da${i}
  gpart bootcode -p /zpool/boot/gptzfsboot -i 1 da${i}
done

loader が zfs を読むように設定する.

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

起動時に zfs mount -a するように /etc/rc.conf に設定する.

echo 'zfs_enable="YES"' > /zpool/etc/rc.conf

今は仮で /zpool にマウントしているので,次回起動時には / にマウントするように設定する.

zfs umount -f -a
zfs set mountpoint=legacy zpool
zfs set mountpoint=/tmp zpool/tmp
zfs set mountpoint=/usr zpool/usr
zfs set mountpoint=/var zpool/var

zpoolのキャッシュ情報をコピーする

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

ブートローダ及び zfs の冗長構成が機能していることを確認する

まずは正常状態で起動することを確認する

ESXi4.0 上で gptzfsboot から起動するととても時間がかかるが,なぜか分からないのでしばらく待つ.
起動したらバージョンを確認する.9.0-CURRENT で上がっている.

zfs# uname -a
FreeBSD zfs 9.0-CURRENT FreeBSD 9.0-CURRENT #0: Sun Oct 10 15:40:58 UTC 2010     root@zfs:/usr/obj/usr/src/sys/GENERIC  amd64

zpool の状態を確認する.zpool status コマンドだ.全ディスクが正常に動作している.

zfs# zpool status
  pool: zpool
 state: ONLINE
 scrub: none requested
config:

	NAME           STATE     READ WRITE CKSUM
	zpool          ONLINE     0     0     0
	  raidz2       ONLINE     0     0     0
	    gpt/disk1  ONLINE       0     0     0
	    gpt/disk2  ONLINE       0     0     0
	    gpt/disk3  ONLINE       0     0     0
	    gpt/disk4  ONLINE       0     0     0
	    gpt/disk5  ONLINE       0     0     0
	    gpt/disk6  ONLINE       0     0     0
ブートに関係ない1台を抜いて正常に起動することを確認する

ESXi の設定を変更して,ディスクを1台取り外してみる.この場合では HDD の起動順は disk1 が第一優先だったので,関係ない disk6 を取り外すことにする.
結果は正常に起動した.zpool の状態を確認しよう.zpool status コマンドの結果は以下の通りで,1台見つかっていない.

zfs# zpool status
  pool: zpool
 state: DEGRADED
status: One or more devices could not be opened.  Sufficient replicas exist for
	the pool to continue functioning in a degraded state.
action: Attach the missing device and online it using 'zpool online'.
   see: http://www.sun.com/msg/ZFS-8000-2Q
 scrub: none requested
config:

	NAME           STATE     READ WRITE CKSUM
	zpool          DEGRADED     0     0     0
	  raidz2       DEGRADED     0     0     0
	    gpt/disk1  ONLINE       0     0     0
	    gpt/disk2  ONLINE       0     0     0
	    gpt/disk3  ONLINE       0     0     0
	    gpt/disk4  ONLINE       0     0     0
	    gpt/disk5  ONLINE       0     0     0
	    gpt/disk6  UNAVAIL      0     0     0  cannot open
ブートするのに使うディスクを変更しても&2台目を抜いても,正常に起動することを確認する

ディスクの2台目を取り外してみる.HDD の起動順で第一優先な disk1 を取り外す.
この場合の結果も正常に起動した.zpool の状態は以下のとおり,2台見つからない.raidz2 なので2台のディスクがなくても動作している.

zfs# zpool status
  pool: zpool
 state: DEGRADED
status: One or more devices could not be opened.  Sufficient replicas exist for
	the pool to continue functioning in a degraded state.
action: Attach the missing device and online it using 'zpool online'.
   see: http://www.sun.com/msg/ZFS-8000-2Q
 scrub: none requested
config:

	NAME           STATE     READ WRITE CKSUM
	zpool          DEGRADED     0     0     0
	  raidz2       DEGRADED     0     0     0
	    gpt/disk1  UNAVAIL      0     0     0  cannot open
	    gpt/disk2  ONLINE       0     0     0
	    gpt/disk3  ONLINE       0     0     0
	    gpt/disk4  ONLINE       0     0     0
	    gpt/disk5  ONLINE       0     0     0
	    gpt/disk6  UNAVAIL      0     0     0  cannot open

errors: No known data errors

外したり接続したりする際の注意点

disk[123456] で raidz2 を組んでいたが,disk1,6 を外した状態で書き込みをした後に disk2 を外して disk1 を接続しても disk1 は古い情報なので raidz2 としては壊れている.単に N-2 台が接続されていれば大丈夫というわけではない.

まとめ

ブートローダファイルシステムの両方を冗長構成にし,障害を想定してディスクを抜き,この状態で起動することで,冗長構成が機能していることを確認した.
冗長構成にするために以下の2点を行った.