ここでは、Express5800/110GeのSATAに接続した6台の500GBドライブを
ZFSに用い、3-way(3重)ミラーリングもしくはダブルパリティ(RAID6相当)の領域を作ります。
3-wayミラーリングには3台、ダブルパリティには3台以上のドライブが必要です。
ZFSの利点はデバイス管理とファイルシステムが統合されている事にあります。
物理デバイスの使用領域はファイルシステムが存在する場所だけなので、
ZFSは常に把握することができ、リビルドでも必要部分のみ同期するだけで完了します。
たとえば1TBの容量があるHDDのミラーリングでも10GBしか利用していなければ、
たった10GBだけコピーすれば1TBのミラーリングのリビルドが完了します。
もちろん新規ドライブに構築する場合はデータコピーがないので瞬時に完了します。
この特徴は一般的なHW-RAIDともSW-RAIDとも違うものです。
(実際はより高度にトランザクションとかトップダウン同期とかあるらしいです)
ZFSではボリュームやファイルシステムの論理切り出しを行う為に
ストレージプールという領域を利用します。
ストレージプールにはOSが認識できるデバイスなら何でも利用できます。
デバイスの接続されたコントローラにもCPUにも依存しません。
別のマザーに交換してもハードディスクが無事ならば瞬時に移動できます。
(SATAポートが足らないと増設カードは必須でしょうが)
前置きはこれぐらいにして実際に作ってみます。
FreeBSDをインストールして初期設定をしたら、
続いてZFSを使う準備を以下のようにします。
/etc/rc.conf
zfs_enable="YES"
/boot/loader.conf
zfs_load="YES"
vfs.zfs.arc_max="256M"
vfs.zfs.vdev.cache.size="10M"
vm.kmem_size_max="512M"
vm.kmem_size="512M"
設定したらマシンを再起動します。
# shutdown -r now
以後作成したZFSがOS起動時に自動的にマウントされるようになります。
ストレージプールを作成します。
以下のコマンドは2~3秒で即座にRAID構成が完成します。
# zpool create tank mirror ad6 ad8 ad10
tank という名前のストレージプールを3-wayミラーリングで作成します。
# zpool add tank mirror ad12 ad14 ad16
容量が不足するならばいつでもストレージプールを拡張することができます。
# zpool create tank mirror ad6 ad8 ad10 mirror ad12 ad14 ad16
3-wayミラーリングのストライピング(RAID10相当)を作成します。
# zpool create tank raidz2 ad6 ad8 ad10 ad12 ad14 ad16
ストレージプールをダブルパリティで作成します。
# zpool export tank
ストレージプールをシステムの管理下から切り離します。
# zpool import tank
別の場所で作成したストレージプールを取り込みます。
# zpool destroy tank
ストレージプールを破棄します。
# zpool import -D tank
構成が破損していなければ破棄されたプールを回復します。
3-wayミラーリング+ストライピング上に4GBのファイルを作成して読込してみる。
# zpool destroy tank
# zpool create tank mirror ad6 ad8 ad10 mirror ad12 ad14 ad16
# zpool list
NAME SIZE USED AVAIL CAP HEALTH ALTROOT
tank 928G 112K 928G 0% ONLINE -
# zpool status
pool: tank
state: ONLINE
scrub: none requested
config:
NAME STATE READ WRITE CKSUM
tank ONLINE 0 0 0
mirror ONLINE 0 0 0
ad6 ONLINE 0 0 0
ad8 ONLINE 0 0 0
ad10 ONLINE 0 0 0
mirror ONLINE 0 0 0
ad12 ONLINE 0 0 0
ad14 ONLINE 0 0 0
ad16 ONLINE 0 0 0
errors: No known data errors
# dd if=/dev/zero of=/tank/image4G.dat bs=64k count=64k
65536+0 records in
65536+0 records out
4294967296 bytes transferred in 51.721632 secs (83040058 bytes/sec)
# dd of=/dev/null if=/tank/image4G.dat bs=64k count=64k
65536+0 records in
65536+0 records out
4294967296 bytes transferred in 11.281782 secs (380699373 bytes/sec)
容量 1TB (500GB+ミラーx2)+(500GB+ミラーx2)
書込 79.2MB/s
読込 363.0MB/s
ダブルパリティ上に4GBのファイルを作成して読込してみる。
# zpool destroy tank
# zpool create tank raidz2 ad6 ad8 ad10 ad12 ad14 ad16
# zpool list
NAME SIZE USED AVAIL CAP HEALTH ALTROOT
tank 2.73T 248K 2.73T 0% ONLINE -
# zpool status
pool: tank
state: ONLINE
scrub: none requested
config:
NAME STATE READ WRITE CKSUM
tank ONLINE 0 0 0
raidz2 ONLINE 0 0 0
ad6 ONLINE 0 0 0
ad8 ONLINE 0 0 0
ad10 ONLINE 0 0 0
ad12 ONLINE 0 0 0
ad14 ONLINE 0 0 0
ad16 ONLINE 0 0 0
errors: No known data errors
# dd if=/dev/zero of=/tank/image4G.dat bs=64k count=64k
65536+0 records in
65536+0 records out
4294967296 bytes transferred in 46.391234 secs (92581441 bytes/sec)
# dd of=/dev/null if=/tank/image4G.dat bs=64k count=64k
65536+0 records in
65536+0 records out
4294967296 bytes transferred in 13.986986 secs (307068822 bytes/sec)
容量 2TB (500GBx4+パリティx2)
書込 88.3MB/s
読込 292.8MB/s
信頼性と読込パフォーマンスか容量のどちらを取るかは運用方針と相談です。
当方はダブルパリティで容量を確保する事にしました。
読込はどう見てもGbE一本でまかなえる速度じゃないです。
(300MB/s=2700Mbps=2.7Gbpsだから)
FreeBSDのZFSはSUNのコードを移植されたものなので、
SUNのSolaris ZFS 管理ガイドが参考になります。
デバイス名の指定など多少違いますが、概念やコマンド体系はそのままです。
余談:
SW-RAIDの基本的なことですがパリティ計算をCPUが担当するので、
計算中は他の処理が停止するので可能であればDualCoreやQuadCoreなどを
載せるほうがいいかもしれない。
このハード構成はCPU交換すると電源容量が足らないかもしれない。
追記:
記載したパラメータがあまりよろしくないので修正。
その後のテストで、どうも書込みが80MB/s程度になっていたのは
CPUパワーとかキャッシュ量に問題がありそうだった。
USED 343G の時点でも、書込92MB/s、読込246MB/sを出せている。
さらにカスタムカーネルを作成してキャッシュを増量したところ、
書込104MB/s、読込263MB/sになりました。
(この値が良いかどうかは不明です)
Kernel CONFIG
include PAE
options KVA_PAGES=1024
nomakeoptions NO_MODULES
makeoptions MODULES_OVERRIDE="opensolaris zfs"
device iscsi_initiator
/boot/loader.conf
vm.kmem_size_max="1536M"
vm.kmem_size="1536M"
vfs.zfs.arc_max="512M"
vfs.zfs.vdev.cache.size="20M"
ddの結果はこんな感じに。
# dd if=/dev/zero of=/tank/image4G.dat bs=64k count=64k
65536+0 records in
65536+0 records out
4294967296 bytes transferred in 39.355941 secs (109131359 bytes/sec)
# dd of=/dev/null if=/tank/image4G.dat bs=64k count=64k
65536+0 records in
65536+0 records out
4294967296 bytes transferred in 15.525784 secs (276634487 bytes/sec)