日曜夜のscrubで家族に不満を言われた話
何も考えずcronで週次scrubを日曜21時に設定していたら、家族の動画配信視聴とまともにぶつかって苦情が来たことがあります。scrubの頻度設計、resilver中の二重障害リスク、sequential resilverとの違い、そしてHDDプールでの所要時間見積もりを実務目線で整理します。
homenasのscrubを何も考えずcronで「毎週日曜21時」に設定していたことがあります。しばらくして家族から「日曜の夜だけ動画配信がカクつく」と苦情が来ました。scrubがちょうどそこにぶつかっていたわけです。「scrubは定期的に回しておけば安心」という理解は半分正しく、半分は運用設計が抜けています。scrubはプール全体のデータをすべて読み出し、チェックサムを検証してビット腐敗(bit rot)やサイレント破損を検出・修復する仕組みですが、それ自体が大きなI/O負荷を伴う処理です。
この記事では、scrubをどれくらいの頻度・タイミングで回すべきか、resilver(再構築)中に何が起きているのか、そしてHDDプールでの所要時間をどう見積もるかを整理します。
scrubは「読み直して検証する」処理で、バックアップではない
まず前提として、scrubはプール上の全ブロックを読み出し、チェックサムを検証する処理です。ZFSは書き込み時に必ずチェックサムを保存しているため、scrubは経年劣化や電源ノイズなどで発生するサイレントなビット化けを能動的に見つけ出せます。冗長性(ミラー/RAIDZ)があれば、破損が見つかった時点で健全なコピーから自動修復されます。
zpool scrub tank
zpool status tank # 進捗とエラーカウントを確認
ここで誤解しやすいのは、scrubはバックアップの代わりにはならないという点です。scrubが検出・修復できるのは冗長性の範囲内の破損だけであり、冗長性を超える同時障害(例: RAIDZ1で2台同時に不良セクタを踏む)には無力です。scrubは「静かに進行している破損を早期発見する」ための仕組みであり、災害復旧計画そのものを代替するものではありません。
「週次」が絶対解ではない理由
よく言われる目安は「エンタープライズ用途(信頼性の高いドライブ)は月次、コンシューマ用途のHDDは週次」というものです。この差は、ドライブのUBER(Unrecoverable Bit Error Rate、読み出し不能ビット率の指標)がコンシューマ向けドライブほど高めに設定されている傾向があることに由来し、UBERが高いほど気づかないうちに蓄積するビット腐敗の量が増えるためです。とはいえ、この目安を鵜呑みにする前に、自分の環境で考慮すべき要素があります。
- プールの用途と負荷パターン: 24時間稼働の本番プールで日中帯にscrubをぶつけると、通常のI/Oと帯域を奪い合い、体感速度に影響します。バックアップ専用プールのように空き時間が明確な用途とは、適切な頻度もタイミングも変わります
- ディスク容量とプール規模: 容量が大きいほどscrubの所要時間は伸びるため、「週次」で回そうとしても前回のscrubが終わらないうちに次のスケジュールが来てしまう、という事態が起こり得ます
- すでにS.M.A.R.T.監視をしているか:
smartdなどで代替セクタ数やペンディングセクタ数を継続監視できているなら、scrubに頼る比重は多少下げられます。逆に何も監視していないなら、scrubが唯一のサイレント破損の検出手段になります
実務上の落とし所としては、「本番負荷の低い時間帯に収まる頻度」を優先し、それが週次で収まらないほどプールが大きいなら隔週や月次に調整する、という所要時間ベースでの頻度設計をおすすめします。うちの場合、「夜間」と一括りにして日曜21時を選んだのが失敗でした。今は平日の未明にずらしています。頻度の数字だけを一人歩きさせないことが重要です。
scrubのスロットリングと優先度制御
scrubがI/O帯域を専有して本番トラフィックに影響するのを防ぐため、OpenZFSにはいくつかの調整ノブがあります。
# scrub中でも通常I/Oを優先させる(遅延ベースのスロットリング、多くのバージョンでデフォルト有効)
cat /sys/module/zfs/parameters/zfs_scan_vdev_limit
# scrub自体を一時停止/再開する
zpool scrub -p tank # pause
zpool scrub tank # resume
OpenZFSのスキャン(scrub/resilverの内部処理)は、通常I/Oが来ている間はスキャン用のI/Oレートを自動的に下げる設計になっていますが、それでも大規模プールやHDD中心の構成では体感できる程度の影響が出ることがあります。業務時間帯にscrubが終わらず食い込みそうな場合は、zpool scrub -pで一時停止し、夜間にzpool scrubで再開する、という運用も選択肢です。ただし一時停止中もそれまでの進捗は保持されるため、途中から再開しても最初からやり直しにはなりません。
resilverは「scrubの緊急版」ではなく「今まさに冗長性が減っている」状態
resilverは、故障したディスクを交換した際に、残りの健全なディスクからデータを再構築してくれる処理です。scrubと同じく全データを読み直す点は似ていますが、決定的に違うのはresilver中はプールの冗長性が一時的に低下しているということです。
- ミラー2-wayでディスクが1台故障してresilver中: この間、もう1台が故障すればデータは失われます(単一障害点の状態)
- RAIDZ1でディスクが1台故障してresilver中: 同様に、resilverが終わるまでは追加の1台の故障が致命傷になります
- RAIDZ2/RAIDZ3であれば、resilver中でも許容できる追加故障の余地が残ります
resilverが終わるまでの時間がそのまま「無防備な時間」の長さになるため、resilver時間を短縮すること自体がリスク低減に直結します。初代homenasはまだRAIDZ1で組んでいた頃にディスクが1本壊れ、resilverに丸1日近くかかったことがあります。残りのディスクが1本でも不調を見せたらそこで終わり、という状況で丸1日過ごすのは生きた心地がしませんでした。大容量HDD(特に10TB超)でRAIDZ1を組んでいる場合、resilverに丸1日以上かかることは珍しくなく、「resilver中にもう1台故障してプールを失う」というシナリオの現実味が高まります。
sequential resilverとhealing resilverの違い
OpenZFS 2.0以降では、ミラーの再構築にsequential resilver(zpool attach/replace時に条件を満たすと自動選択される、LBA順に読み書きする再構築方式)が導入されています。従来のhealing resilver(ファイルシステムのメタデータをたどって使用中ブロックだけを再構築する方式)と比べて、ランダムI/Oを避けてシーケンシャルに近いアクセスパターンになるため、HDD環境では所要時間を大きく短縮できる場合があります。
zpool status tank # resilverの進行中、"resilver in progress" とスキャン方式の情報が出力される
ただし、sequential resilverは主にミラー構成が対象で、RAIDZ/dRAIDでは条件が異なります(dRAIDはディストリビューテッドスペアの仕組み自体が再構築時間の短縮を狙った設計です)。自分のプール構成でどちらの再構築方式が使われるかはzpool statusの出力で確認できるため、resilverが発生した際は方式と推定残り時間を必ず確認する習慣をつけてください。
HDDプールでのscrub所要時間の見積もり
scrub/resilverの所要時間は、単純な「容量 ÷ シーケンシャル速度」では見積もれません。実際に読み出されるのはランダムアクセスに近いパターンになることが多く(ファイルシステム上のデータ配置に依存するため)、カタログスペック上のシーケンシャル速度よりもずっと遅くなるのが通例です。目安として次の要素を押さえておくと、体感とのズレを減らせます。
| 要因 | 所要時間への影響 |
|---|---|
| ディスク使用率(空き容量ではなく使用済み容量) | scrubは使用済みブロックのみを読むため、使用率が低いプールはスカスカでも空き領域はスキップされ、想定より早く終わることがある |
| 断片化の進み具合 | 断片化が進んでいるほどランダムI/O寄りになり、シーケンシャル速度からの乖離が大きくなる |
| ディスク本数と並列度 | vdev数が多いほど並列に読み出せるため、同じ総容量でも所要時間は短縮される傾向がある |
| 小ファイル/大量ファイルのワークロード | メタデータ探索が増え、HDDのシーク時間がボトルネックになりやすい |
事前の理論値だけに頼らず、zpool statusが表示する進捗率と推定残り時間を初回scrub時に記録しておき、以降のプール拡張時の見積もりの基準値として使うのが実務的です。特に大容量HDDでRAIDZを組んでいる環境では、「scrubに数日かかる」ことを前提にした運用カレンダー設計(業務影響の少ない期間にまたがるよう開始日を選ぶなど)が必要になります。
今のcronはこう組んでいる
- scrubの頻度は「週次/月次」という一般論だけでなく、自分のプール規模での実際の所要時間から逆算する
- 本番負荷・家族の生活パターンとぶつからない時間帯か(自分は平日未明に変更しました)
- RAIDZ1やミラーなど冗長性に余裕のない構成で、resilverにかかる時間(=無防備な時間)を把握しているか
zpool statusでresilverの再構築方式(sequential/healing)と進捗を確認する習慣があるか- S.M.A.R.T.監視(
smartdなど)と併用し、scrubだけに破損検出を依存していないか
初代homenasのRAIDZ1は、あの丸1日のresilverの後にRAIDZ2へ組み直しました。RAIDZ本数の選択やspecial vdevの冗長性設計と同様、scrub/resilverの運用設計もプールが大きくなってから慌てて考えると手遅れになりやすい領域です。