Edited at

ZFS on Linuxで高信頼なストレージを作る(Ubuntu 14.04)


ZFSとは何か?


ファイルシステムの限界に挑んだZFS

コンピュータのメモリやCPUを限界まで利用したファイルシステムを目指して作られた。よって、通常ではありえないくらいメモリやCPUを消費してしまう。が、それでも利用したいと思うメリットが沢山。


ZFSのメリット


  • 128bitファイルシステムであるので現行の64bitファイルシステムよりはるかに大きな容量のデータを扱うことが可能。最大16EiBのファイルサイズ、最大256ZiBのファイルシステム。

  • ストレージプールの採用。複数のHDD の容量をまとめて大きなプールとして扱い、その中から必要な容量を切り出して利用する。

  • コピーオンライト。ファイルへの書き込み時にデータを上書きしない仕組み。書き込み中に電源断が発生したとしても、元のファイルが保たれるのでエラーの発生が防げる。

  • 64bitチェックサム(スクラブ)。一部の領域だけでなくファイルシステム全体に対してEnd-to-Endのチェックサムを行う仕組み。データの構造に関する誤りを訂正できる。

  • RAID5/6の書き込みホール問題の解決。RAID5/6には書き込みが途中で中断された場合、検出不可能なパリティとデータの不整合が起きてしまう問題がある。通常はハードウェアRAIDボードに大容量のキャパシタを載せることで対処ができるがコストが高い。これを可変長ストライプとコピーオンライトによってソフトウェア上で解決した世界初の技術

  • ゼロアドミニストレーション。基本的にzpoolやzfsの2つのコマンドしか使用しないので操作が簡単。LVMとは大違い。
    等々。他にもホットスペアやスナップショットにも対応しているので便利。スナップショットはLVMと違いデータのレストアまでコマンドが用意されている。

ZFSはいいぞ


ZFS on Linuxの登場

元々このZFSは2005年にOpenSolaris用に開発されたシステムなので、ライセンスの問題(CDDLライセンスとGPLライセンス)によってLinuxではネイティブに利用することはできなかった。

しかし、サードパーティのカーネルモジュールとしてZFS on Linuxが登場したことによって状況が変わりました。先のライセンス問題で色々と議論されているが、新しいUbuntu16.04LTSではZFS on Linuxがデフォルトでサポートされ、利用の幅が拡がりそうだ。

ただ、安定性を考えるとホントはできればBSDで利用したほうがいいかも。


手順


環境

Fujitu TX100S3(RAM 6G)Ubuntu 14.04.04lts

システム用HDD 320GB

ZFS用HDD 3TB✕1本、2TB✕3本


インストール

今回はZFSで3TBHDD 1台、2TBHDD 3台を使用するRAID-Zを構築した。

1台だけ3TBのHDDを使用していることにより1TBの無駄が発生するが気にしてはいけない。(RAIDディスクに不揃いがあると最小領域に合わせて無駄が生じる。今回では2TBに合わせられる。)RAIDZ1ではRAID5相当の環境となるので実効容量は約6TBになるね。

まずは2TB以上のHDDをZFSとして利用する場合パーティションテーブルがGPTである必要がある。

方法は色々とあるが今回はpartedコマンドを利用した。実行結果を以下に示す。

kazuki@ubuntuserver:~$ sudo parted -l

[sudo] password for kazuki:
Model: ATA ST250DM000-1BD14 (scsi)
Disk /dev/sda: 250GB
Sector size (logical/physical): 512B/4096B
Partition Table: msdos

Number Start End Size Type File system Flags
1 1049kB 256MB 255MB primary ext2 boot
2 257MB 250GB 250GB extended
5 257MB 250GB 250GB logical lvm

Model: ATA TOSHIBA DT01ACA2 (scsi)
Disk /dev/sdb: 2000GB
Sector size (logical/physical): 512B/4096B
Partition Table: gpt

Number Start End Size File system Name Flags
1 1049kB 2000GB 2000GB ext4

Model: ATA WDC WD30EZRX-00D (scsi)
Disk /dev/sdc: 3001GB
Sector size (logical/physical): 512B/4096B
Partition Table: gpt

Number Start End Size File system Name Flags
1 1049kB 3001GB 3001GB Linux LVM lvm

Model: ATA WDC WD20EADS-55R (scsi)
Disk /dev/sdd: 2000GB
Sector size (logical/physical): 512B/512B
Partition Table: msdos

Number Start End Size Type File system Flags
1 1049kB 2000GB 2000GB primary ext4

Model: ATA WDC WD20EZRX-00D (scsi)
Disk /dev/sde: 2000GB
Sector size (logical/physical): 512B/4096B
Partition Table: gpt

Number Start End Size File system Name Flags
1 20.5kB 210MB 210MB fat32 EFI System Partition boot
2 210MB 2000GB 2000GB hfs+ imac2TB
3 2000GB 2000GB 650MB hfs+ Recovery HD
 <以下略>

GPTに揃えてからZFSのフォーマットを行う。

因みに、sdaはルートファイルシステムとして使用しているLVM領域である。これをZFSにすることは今回はしない。あまりおすすめもしない。ここは正直普通に運用したほうが障害発生時の対応が楽(LVMには悩まされたことが…)

partedコマンドでGPTに揃えた。

kazuki@ubuntuserver:~$ sudo parted /dev/sdd

[sudo] password for kazuki:
GNU Parted 2.3
Using /dev/sdd
Welcome to GNU Parted! Type 'help' to view a list of commands.
(parted) mklabel gpt
Warning: The existing disk label on /dev/sdd will be destroyed and all data on this disk will be lost. Do you want to continue?
Yes/No? Yes
(parted) quit
Information: You may need to update /etc/fstab.

kazuki@ubuntuserver:~$ sudo parted -l
<中略>
Model: ATA WDC WD20EADS-55R (scsi)
Disk /dev/sdd: 2000GB
Sector size (logical/physical): 512B/512B
Partition Table: gpt

Number Start End Size File system Name Flags
<以下略>

早速ZFS on Linuxのインストールにかかる。

先のライセンス問題もありデフォルトで提供されていないのでPPAを追加する。

kazuki@ubuntuserver:~$ sudo apt-add-repository --yes ppa:zfs-native/stable

gpg: keyring `/tmp/tmp1u6dk_fo/secring.gpg' created
gpg: keyring `/tmp/tmp1u6dk_fo/pubring.gpg' created
gpg: requesting key F6B0FC61 from hkp server keyserver.ubuntu.com
gpg: /tmp/tmp1u6dk_fo/trustdb.gpg: trustdb created
gpg: key F6B0FC61: public key "Launchpad PPA for Native ZFS for Linux" imported
gpg: Total number processed: 1
gpg: imported: 1 (RSA: 1)
OK

レポジトリの更新を行い必要なパッケージをインストールする。DKMS対応版があるようなのでもちろんこれを利用する。ZFSはカーネルモジュールなので毎回コンパイルが必要だがこれを自動化してくれる。

kazuki@ubuntuserver:~$ sudo apt update

<略>
kazuki@ubuntuserver:~$ sudo apt install debootstrap spl-dkms zfs-dkms ubuntu-zfs
<略>
kazuki@ubuntuserver:~$ sudo modprobe zfs
kazuki@ubuntuserver:~$ dmesg | egrep "SPL|ZFS"
[113146.602200] SPL: Loaded module v0.6.5.6-1~trusty
[113146.614929] ZFS: Loaded module v0.6.5.6-1~trusty, ZFS pool version 5000, ZFS filesystem version 5

by-idを使用してZFSでフォーマットを行いRAID-Z1も同時に作成する。このような複雑な操作をワンラインで実行できるというのがとても嬉しい。めったに操作しないコマンドであるからこそ、障害時に慌てて操作してオペミス…という最悪の事態を起こしにくくなる。

kazuki@ubuntuserver:~$ ls -l /dev/disk/by-id | grep sd

lrwxrwxrwx 1 root root 9 May 3 01:09 ata-ST250DM000-1BD141_Z6E048GZ -> ../../sda
lrwxrwxrwx 1 root root 10 May 1 18:21 ata-ST250DM000-1BD141_Z6E048GZ-part1 -> ../../sda1
lrwxrwxrwx 1 root root 10 May 1 18:21 ata-ST250DM000-1BD141_Z6E048GZ-part2 -> ../../sda2
lrwxrwxrwx 1 root root 10 May 1 18:21 ata-ST250DM000-1BD141_Z6E048GZ-part5 -> ../../sda5
lrwxrwxrwx 1 root root 9 May 3 01:09 ata-TOSHIBA_DT01ACA200_349KWKBKS -> ../../sdb
lrwxrwxrwx 1 root root 9 May 3 01:09 ata-WDC_WD20EADS-55R6B0_WD-WCAVY1097330 -> ../../sdd
lrwxrwxrwx 1 root root 9 May 3 01:09 ata-WDC_WD20EZRX-00DC0B0_WD-WMC1T1988512 -> ../../sde
lrwxrwxrwx 1 root root 9 May 3 01:09 ata-WDC_WD30EZRX-00D8PB0_WD-WCC4NJPSFKE2 -> ../../sdc
lrwxrwxrwx 1 root root 10 May 1 18:21 ata-WDC_WD30EZRX-00D8PB0_WD-WCC4NJPSFKE2-part1 -> ../../sdc1
lrwxrwxrwx 1 root root 9 May 3 01:09 wwn-0x5000039ff3f26847 -> ../../sdb
lrwxrwxrwx 1 root root 9 May 3 01:09 wwn-0x5000c50066322d44 -> ../../sda
lrwxrwxrwx 1 root root 10 May 1 18:21 wwn-0x5000c50066322d44-part1 -> ../../sda1
lrwxrwxrwx 1 root root 10 May 1 18:21 wwn-0x5000c50066322d44-part2 -> ../../sda2
lrwxrwxrwx 1 root root 10 May 1 18:21 wwn-0x5000c50066322d44-part5 -> ../../sda5
lrwxrwxrwx 1 root root 9 May 3 01:09 wwn-0x50014ee258dd8f76 -> ../../sdd
lrwxrwxrwx 1 root root 9 May 3 01:09 wwn-0x50014ee25ff398cf -> ../../sdc
lrwxrwxrwx 1 root root 10 May 1 18:21 wwn-0x50014ee25ff398cf-part1 -> ../../sdc1
lrwxrwxrwx 1 root root 9 May 3 01:09 wwn-0x50014ee6586f0074 -> ../../sde
kazuki@ubuntuserver:~$ zpool create tank raidz ata-TOSHIBA_DT01ACA200_349KWKBKS ata-WDC_WD30EZRX-00D8PB0_WD-WCC4NJPSFKE2 ata-WDC_WD20EADS-55R6B0_WD-WCAVY1097330 ata-WDC_WD20EZRX-00DC0B0_WD-WMC1T1988512

永続的なマウントを有効にするためにby-id名を利用して作成する。HDDをまるごと利用するのでデバイス自体のidを参照した。

が、しかしここでエラーが発生

色々と試行錯誤をした結果、Multipath関連の相性がZFSと宜しくないということがわかった。そういえばISCSIのテストをした時に入れてたなあ。そこでMultipathの無効化を以下で行った。

root@ubuntuserver:~# multipath -ll 

350014ee6586f0074 dm-5 ATA ,WDC WD20EZRX-00D
size=1.8T features='0' hwhandler='0' wp=rw
`-+- policy='round-robin 0' prio=1 status=active
`- 3:0:0:0 sde 8:64 active ready running
35000039ff3f26847 dm-3 ATA ,TOSHIBA DT01ACA2
size=1.8T features='0' hwhandler='0' wp=rw
`-+- policy='round-robin 0' prio=1 status=active
`- 0:0:1:0 sdb 8:16 active ready running
350014ee258dd8f76 dm-4 ATA ,WDC WD20EADS-55R
size=1.8T features='0' hwhandler='0' wp=rw
`-+- policy='round-robin 0' prio=1 status=active
`- 1:0:1:0 sdd 8:48 active ready running

次に、

/etc/multipath.confを作成し内容は

kazuki@ubuntuserver:~$ cat /etc/multipath.conf 

blacklist {
wwid 35000039ff3f26847
wwid 350014ee6586f0074
wwid 350014ee258dd8f76
}

これでOK

以下で作成。

kazuki@ubuntuserver:~$ sudo zpool create tank raidz /dev/disk/by-id/ata-TOSHIBA_DT01ACA200_349KWKBKS /dev/disk/by-id/ata-WDC_WD30EZRX-00D8PB0_WD-WCC4NJPSFKE2 /dev/disk/by-id/ata-WDC_WD20EADS-55R6B0_WD-WCAVY1097330 /dev/disk/by-id/ata-WDC_WD20EZRX-00DC0B0_WD-WMC1T1988512 -f

そんなこんなで作成できたZpoolを確認する。

kazuki@ubuntuserver:~$ sudo zpool list

NAME SIZE ALLOC FREE EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT
tank 7.25T 552K 7.25T - 0% 0% 1.00x ONLINE -

tankと言うのはZFSのストレージプールによく使われる名称で自分もそれを使った。

マウントポイントは/tankとして自動でマウントされる。ストレージプールから別のプールを切り出すこともできる。幾つか切り出しを行った。

kazuki@ubuntuserver:~$ sudo zfs create tank/video5

kazuki@ubuntuserver:~$ sudo zfs create tank/samba
kazuki@ubuntuserver:~$ df -h
Filesystem Size Used Avail Use% Mounted on
udev 2.9G 4.0K 2.9G 1% /dev
tmpfs 594M 964K 593M 1% /run
/dev/dm-1 227G 69G 147G 32% /
none 4.0K 0 4.0K 0% /sys/fs/cgroup
none 5.0M 0 5.0M 0% /run/lock
none 2.9G 4.0K 2.9G 1% /run/shm
none 100M 0 100M 0% /run/user
/dev/sda1 236M 39M 185M 18% /boot
tank 5.2T 128K 5.2T 1% /tank
tank/video5 5.2T 128K 5.2T 1% /tank/video5
tank/samba 5.2T 128K 5.2T 1% /tank/samba

起動時に自動マウントを行うために以下を/etc/default/zfsに追加。

また、/etc/init/zpool-import.confzfs_autoimport_disableを0に

# When OS startup, automount ALL ZFSfilesystem.

ZFS_MOUNT='yes'

追加で幾つかチューニングを行う。

評判の良い新圧縮アルゴリズムであるlz4圧縮を全Poolにおいて有効にし、

ついでに大抵の人には関係のないatimeを全Poolにおいて無効にした。

kazuki@ubuntuserver:~$ sudo zfs set compression=lz4 tank

kazuki@ubuntuserver:~$ sudo zfs get compress
NAME PROPERTY VALUE SOURCE
tank compression lz4 local
tank/samba compression lz4 inherited from tank
tank/video5 compression lz4 inherited from tank
kazuki@ubuntuserver:~$ sudo zfs set atime=off tank

他にも沢山のオプションが有るので調べてみるといいかも。

後はSambaの設定ファイルを編集して以前の設定を書き換えた。

/etc/samba/smb.confに追加

[video5]

path = /tank/video5/video5
writable = yes
force create mode = 0777
force directory mode = 0777
guest ok = yes
guest only = yes

[ZFSshare]
path = /tank/samba/samba
writable = yes
force create mode = 0777
force directory mode = 0777
guest ok = yes
guest only = yes

smbdを再起動して変更を適用する。

kazuki@ubuntuserver:/tank/samba$ sudo service smbd restart

smbd stop/waiting
smbd start/running, process 13637

おしまいです

samba周りについてだけどWindows10から接続する場合は

ユーザ認証が必須となっているので注意が必要。


その他

ZFSにはfsckがないが代わりに週に一回スクラブをすることでファイルシステムの整合性を保つことにする。

# crontab -e

...
30 19 * * 5 zpool scrub tank
...


補足

今回マルチパス関連のエラーが出たが、Googleフォーラムの力を借りてなんとか対処できた。しかし、話によると本来の挙動とは異なる動作をしているとのことで、いつかまた別の問題が起きるかもしれない。きっとどこかで設定ミスがあるのでしょう。


参考文献

https://wiki.archlinuxjp.org/index.php/ZFS

http://lazy-dog.hatenablog.com/entry/2014/08/17/033038

http://l-w-i.net/t/ubuntu/zfs_001.txt

https://github.com/zfsonlinux/pkg-zfs/wiki/HOWTO-install-Ubuntu-14.04---15.04-to-a-Native-ZFS-Root-Filesystem

https://groups.google.com/a/zfsonlinux.org/forum/#!topic/zfs-discuss/V9OyIbb_6tc

http://www.atmarkit.co.jp/ait/articles/0903/13/news125.html