[DESIGN]ADVANCED

「vdev幅は後から変えられない」が半分だけ嘘になっていた

RAIDZ設計の記事で「vdev幅はプール作成後に変えられない」と書きました。あれは今でも大筋では正しいのですが、OpenZFSにRAIDZ拡張(raidz expansion)という機能が入り、既存のRAIDZ vdevにディスクを1本ずつ追加できるようになっています。`homenas`で実際に使ってみて分かった、便利さと「思ったほど得しない」落とし穴を整理します。

以前RAIDZ設計の記事で、「vdev幅はプール作成時点で固定され、後から広げることはできない」と書きました。あれは長らく正しかったのですが、OpenZFS 2.3で**RAIDZ拡張(raidz expansion)**という機能が入り、既存のRAIDZ vdevに1本ずつディスクを追加できるようになりました。homenasの容量が心もとなくなってきたタイミングでちょうどこの機能を試す機会があり、便利だった反面、「思っていたほど得しなかった」部分もあったので記録しておきます。

zpool attachでRAIDZ vdevを広げる

RAIDZ拡張は、既存のRAIDZ vdev内のどれか1台のデバイスを指定して、新しいディスクをzpool attachで追加する形で行います。

zpool attach homenas raidz2-0/disk4 /dev/nvme2n1

これでRAIDZ2の6台構成だったvdevが7台構成に広がります。パリティ本数(この場合は2)は変わらないため、同じ冗長性を保ったままデータディスクの本数だけが増える形です。プール作成時に本数を見誤っても、もう最初から作り直す必要はありません。少なくともディスクスロットに空きがある限りは。

拡張には条件があります。RAIDZ拡張はraidz_expansionというfeature flagとして提供されており、プール側とzfsutils-linux/カーネルモジュール側の両方が対応しているバージョンである必要があります。以前書いたfeature flagの記事の通り、この手のfeatureを有効化すると古い環境には二度と戻せなくなるので、拡張前にzpool upgrade -vで確認する癖はここでも活きます。

拡張中は resilver に似た負荷がかかる

zpool attachを実行すると、既存データを新しいディスク本数のレイアウトに再配置する「reflow」という処理がバックグラウンドで走ります。

zpool status homenas

zpool statusにはexpandの進行状況が表示され、所要時間はディスクの空き容量ではなくすでに書き込まれているデータ量に比例します。挙動としてはresilverに近く、この間はプールに追加の負荷がかかり続けます。homenasでは数TB分のデータで半日ほどかかりました。この間に別のディスクがさらに故障すれば、resilver中と同じようにリスクが高まる時間帯になるので、拡張作業もresilverと同じ感覚でタイミングを選ぶべきです。

一番の落とし穴: 既存データは「得」をしない

ここが実際に使ってみて一番意外だった点です。RAIDZ拡張は、拡張前に書き込まれていたデータのパリティ比率を変えません。たとえばRAIDZ2の6台構成(4データ+2パリティ)で書かれたブロックは、vdevが7台に広がった後も、そのブロック自身は4データ+2パリティの比率のまま存在し続けます。容量効率が改善するのは、拡張後に新しく書き込まれるデータだけです。

これを知らずに拡張直後のzpool listを見て、「あれ、空き容量がそんなに増えていない」と拍子抜けしました。過去に書き溜めたデータの分だけ、旧比率のパリティオーバーヘッドがそのまま残っているからです。既存データにも新しい比率の恩恵を受けさせたいなら、以前書いたsend/receiveの記事のように、データセットを作り直して送り直すしかありません。recordsizeや圧縮の設定変更が既存データに遡及しないのと、根っこは同じ話です。

冗長性の実質的な意味も変わる

もう一つ意識しておきたいのが、パリティ本数は変わらないのに保護対象のデータ量は増える、という点です。RAIDZ2の6台を7台に広げても「2台まで同時故障に耐える」という仕様上の数字は変わりませんが、その2台分のパリティが守る実データの量は増えています。極端に広げすぎると、以前の記事で書いた「vdev幅を無制限に広げるべきではない」という原則に、今度は別の形で引っかかることになります。拡張できるからといって際限なく1本ずつ足し続けるのではなく、RAIDZ2なら6〜10本前後という目安は拡張後も意識しておくべきだと思っています。

今のところの運用

  • 拡張前にzpool upgrade -vで対応バージョンを確認する(featureの片道切符問題は相変わらず健在)
  • 拡張中はresilverと同じ感覚で、負荷とリスクの高い時間帯として扱う
  • 拡張直後に空き容量が期待ほど増えなくても慌てない。過去データは旧比率のまま残る
  • 過去データにも新しい比率を反映させたいなら、send/receiveでのデータセット作り直しを検討する
  • 拡張後もvdev幅の目安(RAIDZ2で6〜10本など)は引き続き意識する

「vdev幅は固定」という自分の中の常識が半分覆ったのは新鮮でしたが、「拡張すれば万事解決」というほど都合の良い機能でもありませんでした。既存データの扱いを理解した上で使う分には、ディスクを1本ずつ足していける選択肢が増えたのは素直にありがたいです。