はじめに
我が家のストレージサーバはFreeNASっていうソフトで運用してます。こいつはFreeBSD上で動くやつで、大変簡単に高価なストレージサーバレベルの機能を使用できる優れものです。FreeNASでは、RAIDを使うことはもちろんのこと、ZFSというファイルシステムを使用してファイルシステム上でRAID機能を実現することができます。今回はこのZFSについて簡単にメモしつつ、Linux上でZFSを使うことができるZFS on Linuxを使ってみようと思います。また、ZFSの機能を色々検証してみたのでそれもメモとして残しておきます。
ZFSのすごいところ
ZFSはオラクルによって開発されたファイルシステムで、以下のような特徴があります。
- RAID機能がある
- スナップショットが取れる
- めっちゃ簡単、コマンド一行で終わる
- ホットスペア対応
- 重複排除機能がある
- 割とメモリー容量を欲する
実に便利そうですなあ。メモリー以外。メモリー容量が少ないとカーネルパニック起こすらしいので注意です。
RAID-Zについて
ZFSが実装しているRAIDは、RAID-Zと呼ばれてます。
RAID-Z1がRAID5相当にあたります。いまはRAID-Z3までありトリプルパリティまでいけます。
あとRAIDでは「RAID5書き込みホール」問題というものがあります。データとパリティの間で不整合が起きる問題のことで、一見正常に動いているように見えていても徐々にデータが破壊されていくというオバケめいた問題です。この問題は停電やクラッシュで発生するようで、これを防ぐためにハードウェアRAIDではバッテリーを積んで防いでいるようです。おっかないです。RAID-Zを使用すると、この問題が起きないそうです。理由としてはコピーオンライト機能と可変ストライプ幅によるものと記載されていることが多いのですが、詳しいアーキテクチャについては難しくて謎です。特に可変ストライプ幅についてはいろいろ意見があるようなので特に謎です。
ZFS on Linux
今回の仮想マシン
早速インストールしてみたいと思います。例にもよって仮想環境を構築しました。今回はこんな感じのスペックです。
- CPU:1ソケット2コア
- ハードディスク:8GB×5本
- NIC:VMXNET3
- OS:CentOS7 最小インストール
いつも邪魔ばっかしてくるSELinuxとかは既に止めてあります。
あ、あと下のコマンドラインに出てくる容量表示は今回の値とは異なってる場合があるんで気にしないでください。
ZFS on Linuxのインストール
公式ページを参考にインストールしていきます。
まずはEPELという外部リポジトリをインストールします。
$ sudo yum localinstall --nogpgcheck https://download.fedoraproject.org/pub/epel/7/x86_64/e/epel-release-7-5.noarch.rpm
読み込んだプラグイン:fastestmirror
epel-release-7-5.noarch.rpm | 14 kB 00:00:00
/var/tmp/yum-root-1fgyJT/epel-release-7-5.noarch.rpm を調べています: epel-release-7-5.noarch
/var/tmp/yum-root-1fgyJT/epel-release-7-5.noarch.rpm をインストール済みとして設定しています
依存性の解決をしています
--> トランザクションの確認を実行しています。
---> パッケージ epel-release.noarch 0:7-5 を インストール
--> 依存性解決を終了しました。
依存性を解決しました
====================================================================================================
Package アーキテクチャー バージョン リポジトリー 容量
====================================================================================================
インストール中:
epel-release noarch 7-5 /epel-release-7-5.noarch 24 k
トランザクションの要約
====================================================================================================
インストール 1 パッケージ
合計容量: 24 k
インストール容量: 24 k
Is this ok [y/d/N]: y
Downloading packages:
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
インストール中 : epel-release-7-5.noarch 1/1
検証中 : epel-release-7-5.noarch 1/1
インストール:
epel-release.noarch 0:7-5
完了しました!
次に、ZFSのRPMパッケージをダウンロードします。
$ sudo yum localinstall --nogpgcheck http://archive.zfsonlinux.org/epel/zfs-release.el7.noarch.rpm
読み込んだプラグイン:fastestmirror
zfs-release.el7.noarch.rpm | 4.3 kB 00:00:00
/var/tmp/yum-root-1fgyJT/zfs-release.el7.noarch.rpm を調べています: zfs-release-1-2.el7.centos.noarch
/var/tmp/yum-root-1fgyJT/zfs-release.el7.noarch.rpm をインストール済みとして設定しています
依存性の解決をしています
--> トランザクションの確認を実行しています。
---> パッケージ zfs-release.noarch 0:1-2.el7.centos を インストール
--> 依存性解決を終了しました。
依存性を解決しました
====================================================================================================
Package アーキテクチャー
バージョン リポジトリー 容量
====================================================================================================
インストール中:
zfs-release noarch 1-2.el7.centos /zfs-release.el7.noarch 2.4 k
トランザクションの要約
====================================================================================================
インストール 1 パッケージ
合計容量: 2.4 k
インストール容量: 2.4 k
Is this ok [y/d/N]: y
Downloading packages:
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
インストール中 : zfs-release-1-2.el7.centos.noarch 1/1
検証中 : zfs-release-1-2.el7.centos.noarch 1/1
インストール:
zfs-release.noarch 0:1-2.el7.centos
完了しました!
準備が整ったので、kernel-develというのとZFSをインストールします。
# sudo yum install kernel-devel zfs
読み込んだプラグイン:fastestmirror
epel/x86_64/metalink | 4.6 kB 00:00:00
epel | 4.4 kB 00:00:00
zfs | 2.9 kB 00:00:00
(1/3): epel/x86_64/group_gz | 169 kB 00:00:00
(2/3): epel/x86_64/primary_db | 3.5 MB 00:00:01
(3/3): zfs/x86_64/primary_db | 31 kB 00:00:01
(1/2): epel/x86_64/updateinfo | 365 kB 00:00:00
(2/2): epel/x86_64/pkgtags | 1.5 MB 00:00:00
~(省略)~
spl-dkms.noarch 0:0.6.4.1-1.el7.centos zfs-dkms.noarch 0:0.6.4.1-1.el7.centos
完了しました!
インストール完了です。簡単です。
ちゃんとインストールできているか確認してみましょう。
$ cat /proc/filesystems
nodev sysfs
nodev rootfs
nodev bdev
nodev proc
nodev cgroup
nodev cpuset
nodev tmpfs
nodev devtmpfs
nodev debugfs
nodev securityfs
nodev sockfs
nodev pipefs
nodev anon_inodefs
nodev configfs
nodev devpts
nodev ramfs
nodev hugetlbfs
nodev autofs
nodev pstore
nodev mqueue
xfs
nodev zfs
一番下にzfs
と表示されています。問題なさそうです。
ZFSプール作成
まず、現状のデバイス状況を確認してみます。
$ parted -l
モデル: VMware Virtual disk (scsi)
ディスク /dev/sda: 17.2GB
セクタサイズ (論理/物理): 512B/512B
パーティションテーブル: msdos
ディスクフラグ:
番号 開始 終了 サイズ タイプ ファイルシステム フラグ
1 1049kB 525MB 524MB primary xfs boot
2 525MB 17.2GB 16.7GB primary lvm
エラー: /dev/sdb: ディスクラベルが認識できません。
モデル: VMware Virtual disk (scsi)
ディスク /dev/sdb: 17.2GB
セクタサイズ (論理/物理): 512B/512B
パーティションテーブル: unknown
ディスクフラグ:
エラー: /dev/sdc: ディスクラベルが認識できません。
モデル: VMware Virtual disk (scsi)
ディスク /dev/sdc: 17.2GB
セクタサイズ (論理/物理): 512B/512B
パーティションテーブル: unknown
ディスクフラグ:
エラー: /dev/sdd: ディスクラベルが認識できません。
モデル: VMware Virtual disk (scsi)
ディスク /dev/sdd: 17.2GB
セクタサイズ (論理/物理): 512B/512B
パーティションテーブル: unknown
ディスクフラグ:
エラー: /dev/sde: ディスクラベルが認識できません。
モデル: VMware Virtual disk (scsi)
ディスク /dev/sde: 17.2GB
セクタサイズ (論理/物理): 512B/512B
パーティションテーブル: unknown
ディスクフラグ:
モデル: Linux device-mapper (linear) (dm)
ディスク /dev/mapper/centos-root: 14.9GB
セクタサイズ (論理/物理): 512B/512B
パーティションテーブル: loop
ディスクフラグ:
番号 開始 終了 サイズ ファイルシステム フラグ
1 0.00B 14.9GB 14.9GB xfs
モデル: Linux device-mapper (linear) (dm)
ディスク /dev/mapper/centos-swap: 1720MB
セクタサイズ (論理/物理): 512B/512B
パーティションテーブル: loop
ディスクフラグ:
番号 開始 終了 サイズ ファイルシステム フラグ
1 0.00B 1720MB 1720MB linux-swap(v1)
sda
がLinuxがインストールされているデバイスのようです。
sdb
とかsdc
がまだ何もフォーマットされてないディスクたちです。
さっそくZFSプールを作成してみます。
ZFSでは基本的にzfs
コマンドかzpool
コマンドしか使いません。単純明快なところが助かります。今回は調子に乗ってトリプルパリティであるRAID-Z3にします。
$ zpool create tank raidz3 /dev/sdb /dev/sdc /dev/sdd /dev/sde /dev/sdf
invalid vdev specification
use '-f' to override the following errors:
/dev/sdb does not contain an EFI label but it may contain partition
information in the MBR.
といった矢先にエラーが出た。EFIラベルが無いとかなんとかってかいてあります。なんか-f
っていうオプションつけたらいけるって書いてあるのでやってみます。ちなみにtank
というのはzfsでのプールにおける慣例的なディレクトリらしく、みんなそこにマウントするので私もそうします。
$ zpool create tank raidz3 /dev/sdb /dev/sdc /dev/sdd /dev/sde /dev/sdf -f
$
何のエラーなく終わりました。行けたのかしら。
zpool
コマンドで確認してみます。
$ zpool list
NAME SIZE ALLOC FREE EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT
tank 63.5G 100K 63.5G - 0% 0% 1.00x ONLINE -
ちゃんとできてるっぽいです!
ファイルシス サイズ 使用 残り 使用% マウント位置
/dev/mapper/centos-root 14G 1.2G 13G 9% /
devtmpfs 1.9G 0 1.9G 0% /dev
tmpfs 1.9G 0 1.9G 0% /dev/shm
tmpfs 1.9G 8.5M 1.9G 1% /run
tmpfs 1.9G 0 1.9G 0% /sys/fs/cgroup
/dev/sda1 497M 151M 347M 31% /boot
tank 16G 0 16G 0% /tank
なんと今の一行のコマンド一つでマウントまでされました。簡単すぎて泣きそう。
以下のコマンドでZFSプールの状態を確認できます。
$ zpool status
pool: tank
state: ONLINE
scan: none requested
config:
NAME STATE READ WRITE CKSUM
tank ONLINE 0 0 0
raidz3-0 ONLINE 0 0 0
sdb ONLINE 0 0 0
sdc ONLINE 0 0 0
sdd ONLINE 0 0 0
sde ONLINE 0 0 0
sdf ONLINE 0 0 0
errors: No known data errors
重複排除の威力
ZFSファイルシステムは、標準装備で重複排除機能を持っています。
ですが、デフォルトだと無効になっているのでまずは重複排除を有効化します。
$ zfs set dedup=on tank
この状態で1GBのファイルを作成してみます。
$ if=/dev/zero of=/tank/bigfile count=1024 bs=1M
サイズを確認してみます。
$ ls -lha
合計 1.0G
drwxr-xr-x 2 root root 3 5月 18 11:57 .
drwxr-xr-x. 18 root root 4.0K 5月 18 11:44 ..
-rw-r--r-- 1 root root 1.0G 5月 18 11:57 bigfile
ちゃんと1GBのファイルが作成されています。普通のファイルシステムであれば、ストレージの容量も1GB分減っているはずです。
$ zpool list
NAME SIZE ALLOC FREE EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT
tank 39.8G 980K 39.7G - 0% 0% 8192.00x ONLINE -
ALLOCというのが使用容量を示しています。なんと驚きの980KB!
今回の実験では高効率のゼロ埋めファイルですが、例えばメールデータのバックアップ先なんかにしたら文字情報しかない為に結構な高率で保存できると思います。
ZFSスナップショット機能
次はスナップショットという機能を使ってみます。
ファイルを削除する前とかにスナップショットを取っておいて、なんかミスったらすぐに元に戻せるっていう機能です。
まずはスナップショットを作成します。
$ zfs snapshot tank@20150518
スナップショットを一覧するコマンドがあるので確認してみます。
$ zfs list -t snapshot
NAME USED AVAIL REFER MOUNTPOINT
tank@20150518 1020M - 1020M -
ちゃんと作成されていました。1GB使用済みって表示されているので、そんなに容量喰うのかと思ってzpool list
を再確認。
$ zpool list
NAME SIZE ALLOC FREE EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT
tank 39.8G 1.04M 39.7G - 0% 0% 8192.00x ONLINE -
よかった、60KB位しか増えてないようです。とりあえずこれでスナップショットはとれました。
ここで作成した空ファイルを削除します。
$ rm bigfile
rm: 通常ファイル `bigfile' を削除しますか? y
これでbigfile
は消えてなくなりました。
かわりにsmallfile
というファイルを作成しておきます。
$ dd if=/dev/zero of=/tank/smallfile count=128 bs=1M
128+0 レコード入力
128+0 レコード出力
134217728 バイト (134 MB) コピーされました、 0.142223 秒、 944 MB/秒
そして、さらにスナップショットを作成します。
$ zfs snapshot tank@20150518-2
なぜここでスナップショットを撮ったのか?
なんとZFSはスナップショット同士を比較することができるのです。!
以下のコマンドで何が変わったかを確認することができます。
# zfs diff tank@20150518 tank@20150518-2
M /tank/
- /tank/bigfile
+ /tank/smallfile
表示された識別子で、何が変化したかを表してます。以下に表を置いておきます。
|識別子|意味|
|:--:||:--:|
|M|変更|
|-|削除|
|+|追加|
|R|リネーム|
/tank
ディレクトリが変更され、bigfile
が削除されsmallfile
が追加されたことがわかります。
もちろんロールバックも簡単です。やってみます。
$ zfs rollback tank@20150518
ちゃんと元に戻ってるか確認してみます。
$ ll
合計 1044588
-rw-r--r-- 1 root root 1073741824 5月 18 17:19 bigfile
完璧に元に戻りました。神ゲー
耐障害性の実験
RAID機能の力を見る時がやってきました。
あらためてZFSプールの状態を確認しておきます。
$ zpool status
pool: tank
state: ONLINE
scan: none requested
config:
NAME STATE READ WRITE CKSUM
tank ONLINE 0 0 0
raidz3-0 ONLINE 0 0 0
sdb ONLINE 0 0 0
sdc ONLINE 0 0 0
sdd ONLINE 0 0 0
sde ONLINE 0 0 0
sdf ONLINE 0 0 0
errors: No known data errors
stateがONLINEと表示されています。問題ない状態です。
仮想マシンのいいところでHDDをぶっさすのも引っこ抜くものも自由自在です。さっそくハードディスクを1本引き抜いてみます。
再度ZFSプールの状態を確認します。
$ zpool status
pool: tank
state: DEGRADED
status: One or more devices could not be used because the label is missing or
invalid. Sufficient replicas exist for the pool to continue
functioning in a degraded state.
action: Replace the device using 'zpool replace'.
see: http://zfsonlinux.org/msg/ZFS-8000-4J
scan: none requested
config:
NAME STATE READ WRITE CKSUM
tank DEGRADED 0 0 0
raidz3-0 DEGRADED 0 0 0
sdb ONLINE 0 0 0
sdc ONLINE 0 0 0
sdd ONLINE 0 0 0
18248829720282346757 FAULTED 0 0 0 was /dev/sde1
3834187477602051621 UNAVAIL 0 0 0 was /dev/sdf1
errors: No known data errors
stateがDEGRADEDにかわっています。一台死んでやばい状態です。
この状態でファイルが参照できるか確認してみます。
$ cd /tank/
$ ll
合計 1044588
-rw-r--r-- 1 root root 1073741824 5月 18 17:19 bigfile
問題なく参照できるようです。
vSphereクライアントから新しいハードディスクを追加してparted -l
を確認します。
$ parted -l
~(省略)~
エラー: /dev/sde: ディスクラベルが認識できません。
モデル: VMware Virtual disk (scsi)
ディスク /dev/sde: 8590MB
セクタサイズ (論理/物理): 512B/512B
パーティションテーブル: unknown
ディスクフラグ:
一台フォーマットしていないディスクが見えてきました。こいつをZFSプールに参加させます。
$ zpool replace tank /dev/sde -f
からのZFSプールの状態確認。
$ zpool status
pool: tank
state: ONLINE
scan: none requested
config:
NAME STATE READ WRITE CKSUM
tank ONLINE 0 0 0
raidz3-0 ONLINE 0 0 0
sdb ONLINE 0 0 0
sdc ONLINE 0 0 0
sdd ONLINE 0 0 0
sde ONLINE 0 0 0
sdf ONLINE 0 0 0
エラーが無くなりました。
パーフェクトだにゃん・・・
おわり
素晴らしいZFSでした。非力なマシンだとかなりパフォーマンスが落ちるそうですが、マシンパワーに自信ニキであれば相当なパフォーマンスを発揮するそうです。耐障害性、堅牢性だけじゃなくて高速化を図るテクノロジーもいっぱい搭載してるらしい。
ちなみにホットスペアも検証してみました。そうしたらZFSファイルシステムが***壊れた。***しにてえ!以上です。
参考サイト様
SIOS "OSSよろず" ブログ出張所
http://sios-oss.blogspot.jp/2012/02/zfs-on-linux1zfs-on-linux.html
私をペロペロするがよい
http://lazy-dog.hatenablog.com/entry/2014/08/17/033038
メモ帳みたいなもの
http://nsrzakki.hateblo.jp/entry/2013/04/09/010854
Life with IT
http://l-w-i.net/t/solaris/zfs_001.txt
ADWAYS ENGINEERS BLOG
http://blog.engineer.adways.net/archives/31692610.html
[[zfs コマンド]] メモとかメモのようなものとか(By ルーキーの中のひと)
http://wiki.rookie-inc.com/serverapps/zfs/command
hirotomium.com
http://hirotomium.com/memories/2011/11/zfsreplace.php