2013/01/04

RootFS on ZFS in FreeBSD 9.1 on KVM

前から気になっていた ZFS を使ってみるべく、FreeBSD 初心者が Linux KVM 上に FreeBSD 9.1 をインストールして RootFS として ZFS を利用できるまでの自分用インストールメモです。

ZFSはじめます

数年前、Solaris がオープンソースとなってしばらくした頃に OpenSolaris や ZFS の書籍をいくつか買ったものの、仕事場では ZFS はおろか Solaris を管理する機会がまったくないのでそのままでした。とはいえ zsh と同じく Z の名を冠するファイルシステムは気になって仕方ありません。

そんなある日、タイトルに惹かれて参加したイベントもありました。

途中、何かつぶやいていましたが、結局このあと読むことはありませんでした。。。 ちなみに書籍は『OpenSolarisスタートアップバイブル』と『ZFS 仮想化されたファイルシステムの徹底活用』です。

そんな ZFS 熱がくすぶり続けていた昨年のある日、ZFS がテーマととして取り上げられている FreeBSD 勉強会の存在を知り、何度か参加させていただきました。

とくに第13回では、書いてあるとおりやれば RootFS on ZFS ができる!という親切な手順が記されていましたので、急にやる気が出てきました。

ハードウェア

ということで FreeBSD/ZFS ストレージサーバとして評判の高い?HP ProLiant MicroServer N54L を用意しました。

  • HP ProLiant MicroServer N54L ディスクレスモデル+Remote Access Card
  • PC3-12800 UNBUFFERED ECC DIMM 8GB * 2
  • Intel 335 SSD 240GB
  • Hitachi HDS722020ALA330 2TB * 4
HDD は NAS のディスクを交換した余りを使います。

RootFS on ZFS in FreeBSD 9.1 on KVM

OS としての FreeBSD は、昔 Perl/CGI の学習環境の PC-UNIX として FreeBSD(98) を少し触った程度で、何となく操作を覚えた頃には GUI の構築が楽な Vine Linux を使い始めてからは Linux オンリーになってしまったので、それ以来の初心者です。

そのため直接 FreeBSD を入れるほど操作に慣れていないし、他にもいろいろ弄ってみたいのでベースとなる OS は Debian にして KVM 上で動かします。KVM の操作もあまり理解していないので virt-manager から操作します。ここでは Debian や KVM、virt-manager のインストールは省きます。

VM を作成しインストール用のメディア( FreeBSD-9.1-RELEASE-amd64-dvd1.iso )からブートして6を押してシングルユーザモードに入ります。

基本的に第13回 FreeBSD 勉強会の資料に記されている手順をそのまま実行しました。そのまま実行できなかった部分についてパスなどを一部修正しています。(下線で記します)

ZFS の管理方式をまだよく理解していませんが、この手順だとデバイスのミラーや L2ARC/ZIL の設定はありません。おいおい設定してゆこうと考えています。(root のパスワードとかも省かれていますのでおいおい)

パーティションの作成

gpart で GPT パーティションを作成します。virt-manager で作成した IDE デバイスだと ada0 になります。

# gpart create -s gpt ada0
ada0 created
起動パーティション「boot0」を作成します。
# gpart add -s 122 -t freebsd-boot -l boot0 ada0
ada0p1 added
スワップ領域「swap0」を作成します。
# gpart add -s 128m -t freebsd-swap -l swap0 ada0
ada0p2 added
ストレージプール領域「disk0」を作成します。
# gpart add -t freebsd-zfs -l disk0 ada0
ada0p3 added
起動ローダ(セカンダリ)を書き込みます。
# gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 ada0
bootcode written to ada0

ストレージプールとデータセットの作成

メディアブートしているため / 以下には書き込めないので、代替ルートディレクトリとして /media を指定してストレージプール、データセットを作成します。

# zpool create -o altroot=/media rpool /dev/gpt/disk0
# zfs create rpool/root
# zfs create rpool/root/tmp
# zfs create rpool/root/usr
# zfs create rpool/root/usr/local
# zfs create rpool/root/var

rc.confとloader.confを作成

zfs create と同時にマウントされていますので、そこにディレクトリを作成して、

# mkdir -p /media/root/boot/zfs
# mkdir -p /media/root/etc
echo コマンドの出力でファイルを作成します。
# echo 'zfs_enable="YES"' >> /media/root/etc/rc.conf
# echo 'zfs_load="YES" >> /media/root/boot/loader.conf
# echo 'vfs.root.mountfrom="zfs:rpool/root"' >> /media/root/boot/loader.conf
ZFS ブートする際の「鶏が先か、卵が先か」問題を解決するため、zpool.cache を ZFS 内に書き込みます。まず zfs create でマウント済みのファイルシステムを全てアンマウントして、ストレージプールをエクスポートして使用不可能状態にします。
# zfs unmount -a
# zpool export rpool
作業用ファイルの出力先として /tmp を書き込み可能にします。
# mount -t tmpfs tmpfs /tmp
zpool.cache の場所を指定しつつ、ストレージプールをインポートします。
# zpool import -o cachefile=/tmp/zpool.cache -o altroot=/media rpool
/tmp/zpool.cache を ZFS 内にコピーして作業に使用した領域を開放します。
# cp /tmp/zpool.cache /media/root/boot/zfs/
# zfs umount -a
# umount /tmp

ストレージプールの設定

ルートファイルシステムになるブート可能なデータセットを指定します。

# zpool set bootfs=rpool/root rpool
プール設定がキャッシュされる位置はデフォルト(=空文字列)を指定します。
# zpool set cachefile="" rpool

ファイルシステムの設定

管理し易くするために作成したレベル1の階層(rpool)は自動マウントしないようにします。

# zfs set mountpoint=none rpool
レベル2以下のマウントポイントを指定します。
# zfs set mountpoint=/ rpool/root
# zfs set mountpoint=/tmp rpool/root/tmp
# zfs set mountpoint=/usr rpool/root/usr
# zfs set mountpoint=/usr/local rpool/root/usr/local
# zfs set mountpoint=/var rpool/root/var
指定したマウントポイントを確認します。
# zfs get -r mountpoint rpool
NAME                  PROPERTY    VALUE             SOURCE
rpool                 mountpoint  none              local
rpool/root            mountpoint  /media            local
rpool/root/tmp        mountpoint  /media/tmp        local
rpool/root/usr        mountpoint  /media/usr        local
rpool/root/usr/local  mountpoint  /media/usr/local  local
rpool/root/var        mountpoint  /media/var        local

FreeBSDのインストール

xz 圧縮アーカイブを3つ展開するだけです。とても簡単で驚きました。(verbose オプションは外しています)

# tar xzpf /usr/freebsd-dist/base.txz -C /media
# tar xzpf /usr/freebsd-dist/src.txz -C /media
# tar xzpf /usr/freebsd-dist/kernel.txz -C /media
つぎにスワップ領域を指定します。この手順ではスワップは ZFS 外のパーティションを使うので fstab に記述します。資料では出力先が /etc/fstab とありますが、この時点では /media/etc/fstab になります。
# echo "swap0 none swap sw 0 0" > /media/etc/fstab
場合によっては swap は ZFS内のファイルでもよいかも知れませんね。

ZFSで起動できるか確認

FreeBSD 9.1 以降では zfsboottest というツールで確認できるようですので、それをインストールして確認します。

# cd /media/usr/src/tools/tools/zfsboottest
# make && make DESTDIR=/media install
# env PATH=$PATH:/media/usr/bin sh ./zfsboottest.sh rpool
The "mountpoint" property of dataset "rpool/root" should be set to "legacy".
警告にしたがって、ルートになるファイルシステムのマウントを手動管理(legacy)に変更します。いちど全てをアンマウントして操作します。アンマウントするために、zfsboottest ディレクトリから待避します。
# cd -
# zfs umount -a
# zfs set mountpoint=legacy rpool/root
リブートして ZFS からシステムが起動するか確認します。
# reboot
無事 ZFS からの起動が確認できたら、OS の基本的な設定を行います。

ネットワーク設定

ここは FreeBSD 管理に慣れていないのでハンドブックを見ながらの作業です。KVM のネットワークは NAT で作成しているのでそれをルータやネームサーバに指定します。

# echo 'hostname="your.host.name"' >> /etc/rc.conf.local
# echo 'ifconfig_ed0="inet 192.168.122.xxx/24"' >> /etc/rc.conf.local
# echo 'defaultrouter="192.168.122.1"' >> /etc/rc.conf.local
# /etc/rc.d/netif start
# route add -net 0/0 192.168.122.1
# echo 'nameserver 192.168.122.1' >> /etc/resolv.conf
sshd が無いと始まりません。
# echo 'sshd_enable="YES"' >> /etc/rc.conf
# /etc/rc.d/sshd start

Ports Collectionのインストール

FreeBSD でもバイナリパッケージがあるようですが、9.1 用のものが存在しているか分かりませんので Ports Collection を利用します。

Portsnap で Ports Collection のスナップショットを取得して展開します。
# portsnap fetch
# portsnap extract

必要なソフトウェアのインストール

まず自分にとって必要なソフトウェアをインストールします。ハブホストではないので GNU Screen は入れません。

# cd /usr/ports/misc/lv && make install clean
# cd /usr/ports/editors/vim && make install clean
# cd /usr/ports/shells/zsh && make install clean

virtioのインストール

KVM を使っているので virtio ドライバをインストールします。

# cd /usr/ports/emulators/virtio-kmod && make install clean
pkg-message の出力にしたがって、loader.conf にドライバを追記します。
# cat <<EOM >> /boot/loader.conf
virtio_load="YES"
virtio_pci_load="YES"
virtio_blk_load="YES"
if_vtnet_load="YES"
virtio_balloon_load="YES"
EOM
rc.conf に新たなネットワークデバイス名を追記します。ZFS ブートなので fstab のディスクデバイス名の書き換えは要りません。
# echo 'ifconfig_vtnet0_name="em0"' >> /etc/rc.conf
ですが IP アドレスの設定は書き換えておきます。
# sed -i.bak -Ee 's|ifconfig_ed0|ifconfig_em0|' /etc/rc.conf.local
ここで VM をシャットダウンして、KVM のドメイン設定ファイル(xml)のドライバ部分を virtio ドライバに変更します。
-      <target dev='hda' bus='ide'/>
-      <address type='drive' controller='0' bus='0' unit='0'/>
+      <target dev='vda' bus='virtio'/>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/>
...
-      <model type='e1000'/>
-      <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
+      <model type='virtio'/>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/>
これで VM をスタートして、virtio デバイスが認識されているか確認します。
# dmesg | grep virtio
virtio_pci0:  port 0xc040-0xc05f mem 0xf2020000-0xf2020fff irq 11 at device 3.0 on pci0
vtnet0:  on virtio_pci0
virtio_pci0: host features: 0x511f8020 
virtio_pci0: negotiated features: 0x110f8020 
virtio_pci1:  port 0xc900-0xc93f mem 0xf2030000-0xf2030fff irq 10 at device 5.0 on pci0
vtblk0:  on virtio_pci1
virtio_pci1: host features: 0x51000094 
virtio_pci1: negotiated features: 0x10000014 
virtio_pci2:  port 0xc940-0xc95f irq 10 at device 6.0 on pci0
vtballoon0:  on virtio_pci2
virtio_pci2: host features: 0x51000000 
virtio_pci2: negotiated features: 0x0

ホストOSのディスクを追加

無事に ZFS ブートの FreeBSD のインストールが完了したら、次に ZFS 用に用意したホスト OS の物理ディスクを virtio ディスクとして認識させます。一度 VM を停止して virsh edit でドメイン定義に追記します。

デバイスパスはデバイス ID で指定するのが無難そうなので、デバイス名をホスト OS のそれに合わせて sdb -> vdb となるようにしています。

# ls -l /dev/disk/by-id/scsi* | grep -v -- -part | sort -k 9 | cut -d' ' -f 9,11
/dev/disk/by-id/scsi-SATA_INTEL_SSDSC2CT2CVKI2463039A240DGN ../../sda
/dev/disk/by-id/scsi-SATA_Hitachi_HDS7220_JK1171YAHW4JMS ../../sdb
/dev/disk/by-id/scsi-SATA_Hitachi_HDS7220_JK1171YAHVULVS ../../sdc
/dev/disk/by-id/scsi-SATA_Hitachi_HDS7220_JK1171YAHWGBAS ../../sdd
/dev/disk/by-id/scsi-SATA_Hitachi_HDS7220_JK1171YAHVV5UN ../../sde
<disk type='block' device='disk'>
  <driver name='qemu' type='raw'/>
  <source dev='/dev/disk/by-id/scsi-SATA_Hitachi_HDS7220_JK1171YAHW4JMS'/>
  <target dev='vdb' bus='virtio'/>
</disk>
<disk type='block' device='disk'>
  <driver name='qemu' type='raw'/>
  <source dev='/dev/disk/by-id/scsi-SATA_Hitachi_HDS7220_JK1171YAHVULVS'/>
  <target dev='vdc' bus='virtio'/>
</disk>
<disk type='block' device='disk'>
  <driver name='qemu' type='raw'/>
  <source dev='/dev/disk/by-id/scsi-SATA_Hitachi_HDS7220_JK1171YAHWGBAS'/>
  <target dev='vdd' bus='virtio'/>
</disk>
<disk type='block' device='disk'>
  <driver name='qemu' type='raw'/>
  <source dev='/dev/disk/by-id/scsi-SATA_Hitachi_HDS7220_JK1171YAHVV5UN'/>
  <target dev='vde' bus='virtio'/>
</disk>
編集後に VM を起動して、ディスクパーティションが認識されているか確認。(QNAPで利用していたディスクをそのまま転用した状態です)
# gpart show
=>      34  41942973  vtbd0  GPT  (20G)
        34       122      1  freebsd-boot  (61k)
       156    262144      2  freebsd-swap  (128M)
    262300  41680707      3  freebsd-zfs  (19G)

=>        63  3907029105  vtbd1  MBR  (1.8T)
          63     1060227      1  linux-data  [active]  (517M)
     1060290     1060290      2  linux-swap  (517M)
     2120580  3903891390      3  linux-data  (1.8T)
  3906011970      996030      4  linux-data  (486M)
  3907008000       21168         - free -  (10M)

=>        63  3907029105  vtbd2  MBR  (1.8T)
          63     1060227      1  linux-data  [active]  (517M)
     1060290     1060290      2  linux-swap  (517M)
     2120580  3903891390      3  linux-data  (1.8T)
  3906011970      996030      4  linux-data  (486M)
  3907008000       21168         - free -  (10M)

=>        63  3907029105  vtbd3  MBR  (1.8T)
          63     1060227      1  linux-data  [active]  (517M)
     1060290     1060290      2  linux-swap  (517M)
     2120580  3903891390      3  linux-data  (1.8T)
  3906011970      996030      4  linux-data  (486M)
  3907008000       21168         - free -  (10M)

=>        63  3907029105  vtbd4  MBR  (1.8T)
          63     1060227      1  linux-data  [active]  (517M)
     1060290     1060290      2  linux-swap  (517M)
     2120580  3903891390      3  linux-data  (1.8T)
  3906011970      996030      4  linux-data  (486M)
  3907008000       21168         - free -  (10M)
ちなみにホスト OS からはように見えています。
# parted -l
Model: ATA INTEL SSDSC2CT24 (scsi)
Disk /dev/sda: 240GB
Sector size (logical/physical): 512B/512B
Partition Table: msdos

Number  Start   End    Size    Type      File system     Flags
 1      1049kB  230GB  230GB   primary   ext4            boot
 2      230GB   240GB  9755MB  extended
 5      230GB   240GB  9755MB  logical   linux-swap(v1)


Model: ATA Hitachi HDS72202 (scsi)
Disk /dev/sdb: 2000GB
Sector size (logical/physical): 512B/512B
Partition Table: msdos

Number  Start   End     Size    Type     File system     Flags
 1      32.3kB  543MB   543MB   primary  ext3            boot
 2      543MB   1086MB  543MB   primary  linux-swap(v1)
 3      1086MB  2000GB  1999GB  primary
 4      2000GB  2000GB  510MB   primary  ext3


Model: ATA Hitachi HDS72202 (scsi)
Disk /dev/sdc: 2000GB
Sector size (logical/physical): 512B/512B
Partition Table: msdos

Number  Start   End     Size    Type     File system  Flags
 1      32.3kB  543MB   543MB   primary  ext3         boot
 2      543MB   1086MB  543MB   primary
 3      1086MB  2000GB  1999GB  primary
 4      2000GB  2000GB  510MB   primary  ext3


Model: ATA Hitachi HDS72202 (scsi)
Disk /dev/sdd: 2000GB
Sector size (logical/physical): 512B/512B
Partition Table: msdos

Number  Start   End     Size    Type     File system     Flags
 1      32.3kB  543MB   543MB   primary  ext3            boot
 2      543MB   1086MB  543MB   primary  linux-swap(v1)
 3      1086MB  2000GB  1999GB  primary
 4      2000GB  2000GB  510MB   primary  ext3


Model: ATA Hitachi HDS72202 (scsi)
Disk /dev/sde: 2000GB
Sector size (logical/physical): 512B/512B
Partition Table: msdos

Number  Start   End     Size    Type     File system     Flags
 1      32.3kB  543MB   543MB   primary  ext3            boot
 2      543MB   1086MB  543MB   primary  linux-swap(v1)
 3      1086MB  2000GB  1999GB  primary
 4      2000GB  2000GB  510MB   primary  ext3

おわりに

まだ物理ディスクで RAIDZ を構成するところまではできませんでしたが、各種マニュアルや先達の設定を参考に、FreeBSD の操作方法とともに設定してゆこうと思います。

おまけ: FreeBSD 10-CURRENT on VirtualBox (1/6追記)

KVM 環境はまだ再構築したくなかったので VirtualBox 環境で試しましたが、同じ手順で 10-CURRENT の RootFS on ZFS が構築できました。( FreeBSD-10.0-CURRENT-amd64-20121230-r244854-release.iso )

せっかくなのでミラーにしてみました。(同じホスト上のファイルですが。。。)

root@freebsd10:~ # zpool status
  pool: rpool
 state: ONLINE
  scan: none requested
config:

        NAME           STATE     READ WRITE CKSUM
        rpool          ONLINE       0     0     0
          mirror-0     ONLINE       0     0     0
            gpt/disk0  ONLINE       0     0     0
            gpt/disk1  ONLINE       0     0     0

errors: No known data errors
ストレージプールに対するコマンド履歴も表示できるんですね。
root@freebsd10:~ # zpool history
History for 'rpool':
2013-01-05.23:31:34 zpool create -o altroot=/media rpool mirror /dev/gpt/disk0 /dev/gpt/disk1
2013-01-05.23:38:18 zfs create rpool/root
2013-01-05.23:38:20 zfs create rpool/root/tmp
2013-01-05.23:38:21 zfs create rpool/root/usr
2013-01-05.23:38:24 zfs create rpool/root/usr/local
2013-01-05.23:38:29 zfs create rpool/root/var
2013-01-05.23:40:35 zpool export rpool
2013-01-05.23:40:57 zpool import -o cachefile=/tmp/zpool.cache -o altroot=/media rpool
2013-01-05.23:41:40 zpool set bootfs=rpool/root rpool
2013-01-05.23:41:45 zpool set cachefile= rpool
2013-01-05.23:41:58 zfs set mountpoint=none rpool
2013-01-05.23:42:04 zfs set mountpoint=/ rpool/root
2013-01-05.23:42:09 zfs set mountpoint=/tmp rpool/root/tmp
2013-01-05.23:42:14 zfs set mountpoint=/usr rpool/root/usr
2013-01-05.23:42:19 zfs set mountpoint=/usr/local rpool/root/usr/local
2013-01-05.23:42:25 zfs set mountpoint=/var rpool/root/var
2013-01-05.23:47:43 zfs set mountpoint=legacy rpool/root

zfsboottest はコンパイルエラーでインストールできませんでしたが、手順通りに進めたのでとくに問題なくブートできました。構成を変えた後に確認するためのツールなので利用できないと困りますが、リリース時には利用できるはずです。

root@freebsd10:/usr/src/tools/tools/zfsboottest # make
Warning: Object directory not changed from original /usr/src/tools/tools/zfsboottest
ln -sf /usr/src/tools/tools/zfsboottest/../../../sys/i386/include machine
cc -O1  -I/usr/src/tools/tools/zfsboottest/../../../sys/boot/zfs  -I/usr/src/tools/tools/zfsboottest/../../../sys/cddl/boot/zfs  -I.  -fdiagnostics-show-option  -W -Wextra -Wno-sign-compare -Wno-unused-parameter  -Werror -std=gnu99 -Qunused-arguments -fstack-protector  -c zfsboottest.c
In file included from zfsboottest.c:55:
/usr/src/tools/tools/zfsboottest/../../../sys/boot/zfs/zfsimpl.c:817:21: error: use of undeclared identifier 'ZFS_MAXNAMELEN'
        static char bootfs[ZFS_MAXNAMELEN];
                           ^
/usr/src/tools/tools/zfsboottest/../../../sys/boot/zfs/zfsimpl.c:2077:19: error: array index 264 is past the end of the array (which contains 192 elements) [-Werror,-Warray-bounds]
                                memcpy(path, &dn.dn_bonus[sizeof(znode_phys_t)],
                                              ^           ~~~~~~~~~~~~~~~~~~~~
/usr/src/tools/tools/zfsboottest/../../../sys/cddl/boot/zfs/zfsimpl.h:788:2: note: array 'dn_bonus' declared here
        uint8_t dn_bonus[DN_MAX_BONUSLEN - sizeof (blkptr_t)];
        ^
2 errors generated.
*** [zfsboottest.o] Error code 1

Stop in /usr/src/tools/tools/zfsboottest.

あとは emulators/virtualbox-ose-additions を入れるために後から lib32.txz を展開した程度です。

root@freebsd10:~ # mount_cd9660 /dev/cd0 /mnt
root@freebsd10:~# tar xzpf /mnt/usr/freebsd-dist/lib32.txz -C /
root@freebsd10:~ # echo <<EOM >> /etc/rc.conf
vboxguest_enable="YES"
vboxservice_enable="YES"
EOM
それと sendmail からの /etc/mail/aliases.db が無いぞメッセージが多いので newaliases しました。

0 件のコメント:

コメントを投稿