CentOS
RAID
ZFS

ZFS on Linuxを仮想CentOS7上で検証した

More than 3 years have passed since last update.


はじめに

我が家のストレージサーバは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本引き抜いてみます。

Imgur

再度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