ゼロから CentOS 7 をインストールし ZFS で RAIDZ を使ってみた

ハードウェア構成

CPU Pentium Gold G4560
RAM 4GB(DDR4-2400) * 2
M/B H270chipset
システム用ドライブ その辺りに転がってたSSD 128GB
RAIDZ用ドライブ 買ってきた4TB*5

まずOSのインストール。

光学ドライブは準備してないので、USBから。
ISOイメージのDLはこちらhttps://www.centos.org/download/
何も考えずに、minimal ISO をチョイス。

過去の記憶を頼りに、UNetbootinでブートUSBを作って使ってみるが、
何度やってもインストール前のbootで止まる。

調べたところ、
CentOS7をUSBからインストール – インフラMemoブログ
ここのブログと同じような事象だと思われる。

なので、rufusを使うことに。

今度は成功。
ちゃんとインストールまで終わった。
設定がよくわからない方はCentOS 7インストールなどを参考に。

セットアップ

で、起動。
まずは、無心でアップデート

[root@xfs ~]# yum -y update

結構な数のパッケージがアップデートされた。
その他もろもろ。

で、一通り終わったことで一応再起動。

パーティションテーブルの設定

現状の確認

[root@xfs ~]# df
ファイルシス                1K-ブロック    使用   使用可 使用% マウント位置
/dev/mapper/centos_xfs-root    52403200 1076580 51326620    3% /
devtmpfs                        3842996       0  3842996    0% /dev
tmpfs                           3854208       0  3854208    0% /dev/shm
tmpfs                           3854208    8888  3845320    1% /run
tmpfs                           3854208       0  3854208    0% /sys/fs/cgroup
/dev/sda2                       1038336  185560   852776   18% /boot
/dev/sda1                        204580    9956   194624    5% /boot/efi
/dev/mapper/centos_xfs-home    63317804   32944 63284860    1% /home
tmpfs                            770844       0   770844    0% /run/user/0
[root@xfs ~]# parted -l
モデル: ATA SAMSUNG SSD 830 (scsi)
ディスク /dev/sda: 128GB
セクタサイズ (論理/物理): 512B/512B
パーティションテーブル: gpt
ディスクフラグ:

番号  開始    終了    サイズ  ファイルシステム  名前                  フラグ
 1    1049kB  211MB   210MB   fat16             EFI System Partition  boot
 2    211MB   1285MB  1074MB  xfs
 3    1285MB  128GB   127GB                                           lvm


エラー: /dev/sdb: ディスクラベルが認識できません。
モデル: ATA ST4000DM004-2CV1 (scsi)
ディスク /dev/sdb: 4001GB
セクタサイズ (論理/物理): 512B/4096B
パーティションテーブル: unknown
ディスクフラグ:

エラー: /dev/sdc: ディスクラベルが認識できません。
モデル: ATA ST4000DM004-2CV1 (scsi)
ディスク /dev/sdc: 4001GB
セクタサイズ (論理/物理): 512B/4096B
パーティションテーブル: unknown
ディスクフラグ:

エラー: /dev/sdd: ディスクラベルが認識できません。
モデル: ATA ST4000DM004-2CV1 (scsi)
ディスク /dev/sdd: 4001GB
セクタサイズ (論理/物理): 512B/4096B
パーティションテーブル: unknown
ディスクフラグ:

エラー: /dev/sde: ディスクラベルが認識できません。
モデル: ATA ST4000DM004-2CV1 (scsi)
ディスク /dev/sde: 4001GB
セクタサイズ (論理/物理): 512B/4096B
パーティションテーブル: unknown
ディスクフラグ:

エラー: /dev/sdf: ディスクラベルが認識できません。
モデル: ATA ST4000DM004-2CV1 (scsi)
ディスク /dev/sdf: 4001GB
セクタサイズ (論理/物理): 512B/4096B
パーティションテーブル: unknown
ディスクフラグ:

モデル: Linux device-mapper (linear) (dm)
ディスク /dev/mapper/centos_xfs-home: 64.9GB
セクタサイズ (論理/物理): 512B/512B
パーティションテーブル: loop
ディスクフラグ:

番号  開始   終了    サイズ  ファイルシステム  フラグ
 1    0.00B  64.9GB  64.9GB  xfs


モデル: Linux device-mapper (linear) (dm)
ディスク /dev/mapper/centos_xfs-swap: 8187MB
セクタサイズ (論理/物理): 512B/512B
パーティションテーブル: loop
ディスクフラグ:

番号  開始   終了    サイズ  ファイルシステム  フラグ
 1    0.00B  8187MB  8187MB  linux-swap(v1)


モデル: Linux device-mapper (linear) (dm)
ディスク /dev/mapper/centos_xfs-root: 53.7GB
セクタサイズ (論理/物理): 512B/512B
パーティションテーブル: loop
ディスクフラグ:

番号  開始   終了    サイズ  ファイルシステム  フラグ
 1    0.00B  53.7GB  53.7GB  xfs

sd[b-f]に対して、パーティションテーブルを設定する

[root@xfs ~]# parted /dev/sdb
GNU Parted 3.1
/dev/sdb を使用
GNU Parted へようこそ! コマンド一覧を見るには 'help' と入力してください。
(parted) p
エラー: /dev/sdb: ディスクラベルが認識できません。
モデル: ATA ST4000DM004-2CV1 (scsi)
ディスク /dev/sdb: 4001GB
セクタサイズ (論理/物理): 512B/4096B
パーティションテーブル: unknown
ディスクフラグ:
(parted) mklabel gpt
(parted) q
通知: 必要であれば /etc/fstab を更新するのを忘れないようにしてください。

これをsdfまで繰り返す

ZFS on Linux のインストール

オフィシャルのインストール情報を確認
https://github.com/zfsonlinux/zfs/wiki/RHEL-and-CentOS

[root@xfs ~]# cat /etc/redhat-release 
CentOS Linux release 7.4.1708 (Core) 
[root@xfs ~]# sudo yum install http://download.zfsonlinux.org/epel/zfs-release.el7_4.noarch.rpm
読み込んだプラグイン:fastestmirror
zfs-release.el7_4.noarch.rpm                                                                                                                                                                                                                                   | 5.2 kB  00:00:00     
/var/tmp/yum-root-Q0lldg/zfs-release.el7_4.noarch.rpm を調べています: zfs-release-1-5.el7_4.noarch
/var/tmp/yum-root-Q0lldg/zfs-release.el7_4.noarch.rpm をインストール済みとして設定しています
依存性の解決をしています
--> トランザクションの確認を実行しています。
---> パッケージ zfs-release.noarch 0:1-5.el7_4 を インストール
--> 依存性解決を終了しました。

依存性を解決しました

======================================================================================================================================================================================================================================================================================
 Package                                                           アーキテクチャー                                             バージョン                                                      リポジトリー                                                                     容量
======================================================================================================================================================================================================================================================================================
インストール中:
 zfs-release                                                       noarch                                                       1-5.el7_4                                                       /zfs-release.el7_4.noarch                                                       2.9 k

トランザクションの要約
======================================================================================================================================================================================================================================================================================
インストール  1 パッケージ

合計容量: 2.9 k
インストール容量: 2.9 k
Is this ok [y/d/N]: y
Downloading packages:
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
  インストール中          : zfs-release-1-5.el7_4.noarch                                                                                                                                                                                                                          1/1 
  検証中                  : zfs-release-1-5.el7_4.noarch                                                                                                                                                                                                                          1/1 

インストール:
  zfs-release.noarch 0:1-5.el7_4                                                                                                                                                                                                                                                      

完了しました!
[root@xfs ~]# gpg --quiet --with-fingerprint /etc/pki/rpm-gpg/RPM-GPG-KEY-zfsonlinux
gpg: 新しいコンフィグレーション・ファイル「/root/.gnupg/gpg.conf」ができました
gpg: *警告*: 「/root/.gnupg/gpg.conf」のオプションはこの実行では、まだ有効になりません
pub  2048R/F14AB620 2013-03-21 ZFS on Linux <zfs@zfsonlinux.org>
   フィンガー・プリント = C93A FFFD 9F3F 7B03 C310  CEB6 A9D5 A1C0 F14A B620
sub  2048R/99685629 2013-03-21

DKMS style で進めてみる
[追記]※普通は kABI-tracking kmod で進めるべきです。

[root@xfs ~]# sudo yum install kernel-devel zfs
読み込んだプラグイン:fastestmirror
Loading mirror speeds from cached hostfile
 * base: ftp.riken.jp
 * extras: ftp.riken.jp
 * updates: ftp.riken.jp
依存性の解決をしています
--> トランザクションの確認を実行しています。

(省略)

--> 依存性の処理をしています: dkms >= 2.2.0.2 のパッケージ: spl-dkms-0.7.6-1.el7_4.noarch
---> パッケージ zfs-dkms.noarch 0:0.7.6-1.el7_4 を インストール
--> 依存性の処理をしています: dkms >= 2.2.0.3 のパッケージ: zfs-dkms-0.7.6-1.el7_4.noarch
--> 依存性解決を終了しました。
エラー: パッケージ: spl-dkms-0.7.6-1.el7_4.noarch (zfs)
             要求: dkms >= 2.2.0.2
エラー: パッケージ: zfs-dkms-0.7.6-1.el7_4.noarch (zfs)
             要求: dkms >= 2.2.0.3
 問題を回避するために --skip-broken を用いることができます。
 これらを試行できます: rpm -Va --nofiles --nodigest

依存性の問題が起こった。

依存性の対応

[root@xfs ~]# yum install epel-release

(省略)

インストール:
  epel-release.noarch 0:7-9

完了しました!

インストールの再実行

[root@xfs ~]# sudo yum install kernel-devel zfs

(省略)

完了しました!

インストールできた。

念のため確認

[root@xfs ~]# which zpool
/usr/sbin/zpool

ZFSプールの作成

このあたりの情報をを参考に進める。
Archlinux スレッドプールの作成

本家はここ
selecting-dev-names-when-creating-a-pool

ホームサーバ用途などはデバイスIDでプールを作った方が良いらしいので、IDの確認

[root@xfs ~]# ls -lh /dev/disk/by-id/
合計 0
lrwxrwxrwx 1 root root  9  3月 11 18:19 ata-SAMSUNG_SSD_830_Series_S0XYNEXXXXXXXX -> ../../sda
lrwxrwxrwx 1 root root 10  3月 11 18:19 ata-SAMSUNG_SSD_830_Series_S0XYNEXXXXXXXX-part1 -> ../../sda1
lrwxrwxrwx 1 root root 10  3月 11 18:19 ata-SAMSUNG_SSD_830_Series_S0XYNEXXXXXXXX-part2 -> ../../sda2
lrwxrwxrwx 1 root root 10  3月 11 18:19 ata-SAMSUNG_SSD_830_Series_S0XYNEXXXXXXXX-part3 -> ../../sda3
lrwxrwxrwx 1 root root  9  3月 11 18:19 ata-ST4000DM004-2CV104_ZFNXXXX1 -> ../../sdb
lrwxrwxrwx 1 root root  9  3月 11 18:19 ata-ST4000DM004-2CV104_ZFNXXXX2 -> ../../sdd
lrwxrwxrwx 1 root root  9  3月 11 18:19 ata-ST4000DM004-2CV104_ZFNXXXX3 -> ../../sdc
lrwxrwxrwx 1 root root  9  3月 11 18:19 ata-ST4000DM004-2CV104_ZFNXXXX4 -> ../../sdf
lrwxrwxrwx 1 root root  9  3月 11 18:19 ata-ST4000DM004-2CV104_ZFNXXXX5 -> ../../sde

※以後IDはフェイク

続いて、プールを作りたいとこですが、
AFでのパーティションアライメントの対策を。
advanced-format-disks
こちらを読む限り ashift=12 を指定することで、いい感じになるっぽい。

では、raidz1でタンクの作成

[root@xfs ~]# zpool create -f -o ashift=12 tank raidz1 ata-ST4000DM004-2CV104_ZFNXXXX1 ata-ST4000DM004-2CV104_ZFNXXXX2 ata-ST4000DM004-2CV104_ZFNXXXX3 ata-ST4000DM004-2CV104_ZFNXXXX4 ata-ST4000DM004-2CV104_ZFNXXXX5
The ZFS modules are not loaded.
Try running '/sbin/modprobe zfs' as root to load them.

おっと、、モジュールがロードされてないらしい

気を取り直して。

[root@xfs ~]# /sbin/modprobe zfs
[root@xfs ~]# zpool list
no pools available
[root@xfs ~]# zpool create -f -o ashift=12 tank raidz1 ata-ST4000DM004-2CV104_ZFNXXXX1 ata-ST4000DM004-2CV104_ZFNXXXX2 ata-ST4000DM004-2CV104_ZFNXXXX3 ata-ST4000DM004-2CV104_ZFNXXXX4 ata-ST4000DM004-2CV104_ZFNXXXX5
[root@xfs ~]# zpool list
NAME   SIZE  ALLOC   FREE  EXPANDSZ   FRAG    CAP  DEDUP  HEALTH  ALTROOT
tank  18.1T   912K  18.1T         -     0%     0%  1.00x  ONLINE  -
[root@xfs ~]# zpool status
  pool: tank
 state: ONLINE
  scan: none requested
config:

        NAME                                 STATE     READ WRITE CKSUM
        tank                                 ONLINE       0     0     0
          raidz1-0                           ONLINE       0     0     0
            ata-ST4000DM004-2CV104_ZFNXXXX1  ONLINE       0     0     0
            ata-ST4000DM004-2CV104_ZFNXXXX2  ONLINE       0     0     0
            ata-ST4000DM004-2CV104_ZFNXXXX3  ONLINE       0     0     0
            ata-ST4000DM004-2CV104_ZFNXXXX4  ONLINE       0     0     0
            ata-ST4000DM004-2CV104_ZFNXXXX5  ONLINE       0     0     0

errors: No known data errors

df

[root@xfs ~]# df -h
ファイルシス                サイズ  使用  残り 使用% マウント位置
/dev/mapper/centos_xfs-root    50G  1.7G   49G    4% /
devtmpfs                      3.7G     0  3.7G    0% /dev
tmpfs                         3.7G     0  3.7G    0% /dev/shm
tmpfs                         3.7G  8.8M  3.7G    1% /run
tmpfs                         3.7G     0  3.7G    0% /sys/fs/cgroup
/dev/sda2                    1014M  182M  833M   18% /boot
/dev/sda1                     200M  9.8M  191M    5% /boot/efi
/dev/mapper/centos_xfs-home    61G   33M   61G    1% /home
tmpfs                         753M     0  753M    0% /run/user/0
tank                           15T  128K   15T    1% /tank

4TB*5台=20TB ですが、1台はアレなので、計算上は16TBとして、こんなもんでしょう。

ZFSの設定

圧縮

zfsでは圧縮アルゴリズムのサポートが複数あります。
https://pthree.org/2012/12/18/zfs-administration-part-xi-compression-and-deduplication/
このあたりのドキュメントを読む限り、彼のIMO(in my opinion)ベースではあるのですが、
『圧縮はcpuにとって軽い作業でしかないので、圧縮ファイル(動画、画像なども含む)が多い環境においても全ての環境においてonにすることを進める。
lz4が速いだけでなく圧縮率も高めなのでおすすめ。』
みたいなことが書いてあり、共感できる部分も多いため、採用。
※途中で圧縮を有効にしてもそれ以降しか圧縮が適用されないので、最初からやるべき。

[root@xfs ~]# zfs get compress
NAME  PROPERTY     VALUE     SOURCE
tank  compression  off       default
[root@xfs ~]# zfs set compression=lz4 tank
[root@xfs ~]# zfs get compression
NAME  PROPERTY     VALUE     SOURCE
tank  compression  lz4       local

圧縮のテスト

[root@xfs ~]# zfs list
NAME   USED  AVAIL  REFER  MOUNTPOINT
tank   614K  14.0T   153K  /tank
[root@xfs ~]# tar -cf /tank/text.tar /var/log/
tar: メンバ名から先頭の `/' を取り除きます
[root@xfs ~]# ll /tank/
合計 934
-rw-r--r-- 1 root root 4515840  3月 11 21:54 text.tar
[root@xfs ~]# zfs list /tank/
NAME   USED  AVAIL  REFER  MOUNTPOINT
tank  1.57M  14.0T  1.06M  /tank
[root@xfs ~]# zfs get compressratio /tank/
NAME  PROPERTY       VALUE  SOURCE
tank  compressratio  4.59x  -

ゴミ削除

[root@xfs ~]# rm /tank/text.tar 
rm: 通常ファイル `/tank/text.tar' を削除しますか? y

1/4.59 に容量を抑えられたってことですね。
効率的。

最終アクセス日

atime はファイルアクセスをするたびに最終アクセス日時の属性の更新を行うため、
relatime をonにすることで、その頻度を下げパフォーマンスを改善します。

[root@xfs ~]# zfs get atime
NAME  PROPERTY  VALUE  SOURCE
tank  atime     on     default
[root@xfs ~]# zfs get relatime
NAME  PROPERTY  VALUE     SOURCE
tank  relatime  off       default
[root@xfs ~]# zfs set relatime=on tank
[root@xfs ~]# zfs get relatime
NAME  PROPERTY  VALUE     SOURCE
tank  relatime  on        local

重複排除について

こちらも、先程のページに説明があります。

ZFSでは(ファイル単位でもなく、バイト単位でもなく)ブロック単位で重複の制御を行います。
ブロック単位で制御することで、効率よく重複データの制御ができるとのこと。

ただし問題があり、基本的にはRAM上で重複の管理をする作りになっており、
メモリの使用量がとにかく多いです。

メモリ使用量の結論としては、
1TBあたり5GBのメモリが必要とされるということで、
今回16TBなので80GBのメモリが必要です。
また、ZFSにはARCというキャッシュシステムがありますが、そのうち25%を重複管理に利用するとのことで、
320(80*4)GB以上のメモリが必要です。
安く仕上げたいホームサーバとしては完全に無理ゲーです。

ただ、特定のプールなど部分的に重複排除の設定を入れるのは有りかも。

そんなこんなで重複排除は難しいですが、
しばらく使ってみます。