zfs on linuxのversion 0.8.0が5月末にリリースされました。新しいFeatureはReleaseページにあるのですが、今回は新しい機能であるzfs Device Removal(#6900) の挙動を確認しつながら、ロングスパンでのzfsの拡張可能性について考えてみたいと思います。
zfsは、ストレージプールに新たなボリュームをコマンド一発($ zpool add [pool] [device]
)で追加することができます。お客様の中にもこのようにしてストレージを拡張されている方は多いのですが、何度も拡張を繰り返していくと最初のボリュームを構成しているハードウェア、ディスクは当然古くなっていくわけで、10年も20年も拡張し続けることはできません。
また、どこかのタイミングでこれを一気にリプレースするとなると、既存のストレージより大きなサイズのストレージが必要になり、多くの予算が必要になります。また、既存のストレージの中には1,2年前に増設したばかりのものもあるかもしれません。
例として以下の図のようなケースで考えてみます。初年度に40TBを導入し、翌年に80TB増設、4年目に50TBを増設して、約170TBのzfsのストレージプールを持っているようなケースです。
この後、仮に何らかの理由で最初に導入した40TBを継続して利用するのが難しいという状況になったとしても、データは3つのストレージにまたがって保存されているので、ファイルシステムのレベルで40TBのディスクに書き込まれたデータだけを取り出すことはできません。
そうすると、冒頭で書いたように全体をリプレースするしか選択肢は無いのでしょうか。
そのような問題意識から今回のテーマであるzfsのDevice Removalの機能を使う方法を試してみました。
具体的には、以下の図のように100TBのストレージを増設した上で、40TBの領域をストレージプールから削除する、というコマンドを実行します。これが実行されると、バックグラウンドで40TBの領域にあるデータが残りのデバイスにRe-Allocateされ、完了すると40TBのディスクがプールから削除されます。そしてディスクの容量も170TBから230TBになります。(実際には、増やしてから減らすので170TB -> 270TB -> 230TBという推移です。)
この機能を使うと、何年かおきにデバイスを一つずつ置き換えながら徐々に増やしていくということが可能になりそうです。
zpool removeの挙動
では実際に、Device Removalの挙動を見てみたいと思います。
準備
- まず, zfsのプールを作成します。
# lsblk -d
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sdd 8:48 0 10.9T 0 disk
sde 8:64 0 7.3T 0 disk
sdf 8:80 0 7.3T 0 disk
sdg 8:96 0 7.3T 0 disk
# zpool create abacus /dev/sde
# zpool status -v
pool: abacus
state: ONLINE
scan: none requested
config:
NAME STATE READ WRITE CKSUM
abacus ONLINE 0 0 0
sde ONLINE 0 0 0
# zpool list -v
NAME SIZE ALLOC FREE CKPOINT EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT
abacus 7.27T 408K 7.27T - - 0% 0% 1.00x ONLINE -
sde 7.27T 408K 7.27T - - 0% 0.00% - ONLINE
- 次にzfsのファイルシステムを作成します。
# zfs create abacus/data -o mountpoint=/data2
# df -TH -t zfs
Filesystem Type Size Used Avail Use% Mounted on
abacus zfs 7.8T 132k 7.8T 1% /abacus
abacus/data zfs 7.8T 132k 7.8T 1% /data2
- remove時の挙動を確認するためにも100GBちょっとのデータをコピーしておきます。
# du -hs /data/
109G /data/
# rsync -aP /data/ /data2/
# df -Th -t zfs
Filesystem Type Size Used Avail Use% Mounted on
abacus zfs 7.0T 128K 7.0T 1% /abacus
abacus/data zfs 7.1T 109G 7.0T 2% /data2
# zpool list -v
NAME SIZE ALLOC FREE CKPOINT EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT
abacus 7.27T 109G 7.16T - - 0% 1% 1.00x ONLINE -
sde 7.27T 109G 7.16T - - 0% 1.45% - ONLINE
- さらにプールを2つ追加し、データをコピーして以下の状態を作ります。
# zpool status
pool: abacus
state: ONLINE
scan: none requested
config:
NAME STATE READ WRITE CKSUM
abacus ONLINE 0 0 0
sde ONLINE 0 0 0
sdf ONLINE 0 0 0
sdg ONLINE 0 0 0
# zpool list -v
NAME SIZE ALLOC FREE CKPOINT EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT
abacus 21.8T 200G 21.6T - - 0% 0% 1.00x ONLINE -
sde 7.27T 148G 7.12T - - 0% 1.98% - ONLINE
sdf 7.27T 41.4G 7.23T - - 0% 0.55% - ONLINE
sdg 7.27T 11.0G 7.25T - - 0% 0.14% - ONLINE
3つのボリュームで構成されたzpool(abacus)に200GB程度のデータを配置できたので準備完了です。
zpool removeの実行
上の状態から、10.9TBのsddを追加し、7.27TBのsdeを削除します。
- デバイス毎のデータのアロケーションを見ると追加したばかりのsddには当然何のデータもありません。
# zpool list -v
NAME SIZE ALLOC FREE CKPOINT EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT
abacus 32.7T 200G 32.5T - - 0% 0% 1.00x ONLINE -
sde 7.27T 148G 7.12T - - 0% 1.98% - ONLINE
sdf 7.27T 41.4G 7.23T - - 0% 0.55% - ONLINE
sdg 7.27T 11.0G 7.25T - - 0% 0.14% - ONLINE
sdd 10.9T 464K 10.9T - - 0% 0.00% - ONLINE
- この状態で、zpool remove を実行します。
# zpool remove abacus sde
Re-Allocation中の挙動
- zpool iostatで各デバイスのDisk IOを見てみると、sdeからREAD、sdf,sdg,sddにWriteのIOが発生しています。
# zpool iostat -v
capacity operations bandwidth
pool alloc free read write read write
---------- ----- ----- ----- ----- ----- -----
abacus 202G 32.5T 12 48 200M 204M
sde 148G 7.12T 12 0 200M 0
sdf 42.0G 7.22T 0 15 0 67.2M
sdg 11.7G 7.25T 0 16 0 66.1M
sdd 690M 10.9T 0 15 0 70.4M
---------- ----- ----- ----- ----- ----- -----
- zpool status -vでも状態が確認でき、Evacuationが進んでいることがわかります。
# zpool status -v
pool: abacus
state: ONLINE
scan: none requested
remove: Evacuation of /dev/sde1 in progress since Wed Jun 12 18:05:56 2019
29.2G copied out of 148G at 197M/s, 19.74% done, 0h10m to go
config:
NAME STATE READ WRITE CKSUM
abacus ONLINE 0 0 0
sde ONLINE 0 0 0
sdf ONLINE 0 0 0
sdg ONLINE 0 0 0
sdd ONLINE 0 0 0
完了後の状態
- zpool statusからもsdeの表示が無くなりました。また、zpool removeの実行時のサマリーも表示されています。
# zpool status
pool: abacus
state: ONLINE
scan: none requested
remove: Removal of vdev 0 copied 148G in 0h12m, completed on Wed Jun 12 18:18:43 2019
229K memory used for removed device mappings
config:
NAME STATE READ WRITE CKSUM
abacus ONLINE 0 0 0
sdf ONLINE 0 0 0
sdg ONLINE 0 0 0
sdd ONLINE 0 0 0
- zpool list では以下のようにsdeにあったデータが他のデバイスにコピーされトータルの容量が同じになっていることがわかります。
# zpool list -v
NAME SIZE ALLOC FREE CKPOINT EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT
abacus 25.4T 200G 25.2T - - 0% 0% 1.00x ONLINE -
sdf 7.27T 90.9G 7.18T - - 0% 1.22% - ONLINE
sdg 7.27T 59.6G 7.21T - - 0% 0.80% - ONLINE
sdd 10.9T 49.8G 10.9T - - 0% 0.44% - ONLINE
zpool removalによって削除したデバイスからデータが吸いだされ、残りのデバイスに再配置されたことが確認できました。
removeできないケース
上の例以外にも3TB, 6TB, 10TBのHDDの組み合わせによるRAIDなどでもテストをしてみましたが、removeを実行すると以下のようなエラーが出て実行できなかったケースがありました。どうもzfsのプールを構成している各ボリュームが同じセクターサイズでないとremoveできないようです。
cannot remove sda: invalid config; all top-level vdevs must have the same sector size and not be raidz.
まとめ
zfsのDevice Removalによって古いボリュームをリタイヤさせて、新しいボリュームを追加するという動作が少ない容量ながら確認できました。
実際の環境で適用するには、ストレージサイズが大きくなった際にも問題ないのか、removeのバックグラウンドのプロセスの間に再起動などをしても問題ないのか、このプロセスの間ディスク性能はどれほど低下するのか、上記のセクターサイズの違い以外でremoveができないケースは無いのか、などなど確認すべき点が多々あります。
ただ、実際にそのあたりがきちんと確認されたとすると、上にも書いたように毎年少しずつ増設していき、徐々に古いものをリタイヤさせるという形で長期間に渡って増設が続けられそうですです。
ご関心やご質問などがありましたら担当の営業かエンジニア、あるいはこちらまでお問い合わせ頂ければと思います。