ZFS入門——Copy-on-Write・スナップショット・RAID-Zがホームサーバーのストレージをどう変えるのか

はじめに——RAID5 + ext4 からの問い

自宅にNASや仮想化基盤を構築してきた技術者の多くは、「mdadmやハードウェアRAIDでRAID5を組み、その上にext4やXFSを置く」という構成に馴染みがあるでしょう。磁気ディスクが1台壊れてもパリティで復旧できる——この安心感が、長年ホームサーバーの定番構成でした。

しかし、この構成には死角があります。RAID5が守れるのは「ディスクの物理的な故障」だけだという点です。もっと静かな敵、サイレントコラプション(ビットロット)はどうでしょうか。磁気ディスクは経年で、エラーや警告なしにビットが書き換わることがあります。従来のRAIDコントローラやext4は「書き込みが成功した=データが正しい」と仮定してしまうため、破損したデータを正しいデータとして読み返し、最悪の場合、その破損をパリティ経由で他のディスクにまで複製してしまうのです。バックアップから戻そうにも、壊れた時点のファイルが「正常」として保存されていた、という事態も起こり得ます。

この問いに対する1つの答えがZFSです。Sun Microsystemsで2001年に開発が始まり、2005年にOpenSolarisで公開。その後のライセンス問題を経て2013年からはOpenZFSとしてコミュニティ開発へ移行し、現在はLinux・FreeBSDなどマルチプラットフォームで使われています。ファイルシステムとボリュームマネージャ、RAID機能を単一レイヤに統合した設計は、発表から20年以上経った今も独特の存在感を保っています。Proxmox VEやTrueNASが標準採用していることで、ホームラボでの実用度も十分です。

本記事では、ZFSの核となるCopy-on-Write(CoW)の仕組み、チェックサムとセルフヒーリングによるデータ整合性の担保、RAID-Zとミラーの選び方、そしてスナップショットを活用したバックアップ運用までを順に解説します。最後にProxmox・TrueNAS・Linuxでの実践構成例も紹介しますので、自宅NASや仮想化基盤を自前運用している方は、ぜひ最後までご覧ください。

ZFSとは何か——ファイルシステムとボリュームマネージャの融合

ZFSの最大の特徴は、従来はバラバラだったストレージの管理レイヤを1つに統合した点にある。これまでホームサーバーでは「ext4/XFS(ファイルシステム)+ LVM(ボリューム管理)+ mdadm/ハードウェアRAID(冗長化)+ バックアップツール」という多層構成を組み合わせるのが普通だった。各レイヤは互いの内側を知らない。RAIDコントローラは「書き込みが成功すればデータは正しい」と仮定し、ファイルシステムはディスクが返してきたデータをそのまま信じる。この分業構造こそが、サイレントコラプションを見逃す原因だった。

ZFSはこれらの役割——ファイルシステム、ボリュームマネージャ、RAID、そしてスナップショットやレプリケーションまで——を単一のレイヤに押し込めた。データがディスクに落ちる瞬間から読み戻されるまで、すべてをZFS自身が把握する。この「見通しの良さ」が、後の章で説明するチェックサム検証やセルフヒーリングの土台になっている。

Copy-on-Write——上書きしないファイルシステム

ZFSのもうひとつの根幹が CoW(Copy-on-Write) だ。従来のファイルシステムは、ファイルを変更するとき既存ブロックをその場(in-place)で上書きする。書き込みの途中で電源が落ちれば、ファイルは「古いデータと新しいデータが混在した」壊れた状態になりうる。fsckが必要になるのはこのためだ。

ZFSはデータを決して上書きしない。変更があると、空き領域に新しいブロックを書き、すべての書き込みが完了したタイミングでメタデータのポインタだけを入れ替える。つまり書き込みはトランザクション(原子的)であり、電源断が起きてもプール全体はオンディスク上一貫した状態(直前か新しい状態のいずれか)で復旧できる。この設計のためファイルシステム全体の整合性検証(fsck相当)は基本不要です。ただし、プールの整合性は保たれても、電源断の瞬間にコミット前だった書き込みが失われる可能性や、アプリケーション単位(DBのトランザクションなど)の整合性までは保証されない点には注意が必要です。副作用として書き込み増大(write amplification)があるが、これは後の章で扱うチューニングで緩和できる。

用語の整理——プール / vdev / データセット / zvol

ZFSの世界観を把握するには、4つの用語を押さえればよい(TrueNASのZFS Primerの定義に沿う)。

  • プール(zpool): ディスクを束ねたストレージの総体。すべてのデータと冗長性はプール単位で管理される
  • vdev: プールを構成する部品。ミラー2台やRAID-Z1の3台などの冗長構成が1つのvdev。プールの信頼性は「最も弱いvdev」で決まる
  • データセット(filesystem): プール上に作るファイルシステム。フォルダのように階層化でき、単位ごとに圧縮・クォータ・スナップショットを設定できる
  • zvol: ブロックデバイスとして提供される仮想ボリューム。VMのディスクイメージやiSCSI LUNに使われる
graph BT
    subgraph "ZFSプール(tank)"
        subgraph vdev1["ミラーvdev"]
            disk1["HDD A"] --- disk2["HDD B"]
        end
        subgraph vdev2["ミラーvdev"]
            disk3["HDD C"] --- disk4["HDD D"]
        end
    end
    dataset["データセット(filesystem/zvol)"] --> pool["プール"]
    pool --> vdev1
    pool --> vdev2
    snap["スナップショット(読み取り専用のポイントインタイム)"] -.-> dataset

図のように、データセットはプールという共通の入れ物の上に載り、プールは複数のvdevで構成される。スナップショットはデータセットのある瞬間の読み取り専用コピーで、CoWのおかげで作成は一瞬、消費するのは差分ブロックだけだ。この構造を一度理解すれば、次章以降の整合性検証やRAID-Zの設計論がぐっと読みやすくなるはずだ。

データ整合性——チェックサム・スクラブ・セルフヒーリング

ZFSが「ただのファイルシステム」と一線を画す最大の理由が、データ整合性をファイルシステム自身が守る設計だ。ZFSはプール上のすべてのブロックにチェックサムを付与する。デフォルトは fletcher4(高速な非暗号学的ハッシュ)、より高い整合性が欲しい場合はデータセット単位で sha256 を選択できる。ポイントは、この検証がディスクから読み出すたびにエンドツーエンドで行われることだ。

サイレントコラプションの実態

従来の ext4 + ハードウェアRAID構成は「書き込みが成功すればデータは正しい」と仮定している。しかし現実には、ビットロット(磁気ディスク上のビットが経年で静かに反転する現象)、DMA転送エラー、ドライブファームウェアの誤報告など、エラーを返さずに壊れたデータを「正常」として読み返す故障モードが存在する。恐ろしいのは、ハードウェアRAIDがこの破損を検出できないばかりか、ミラーとして破損データを正しく複製してしまうことだ。バックアップから戻しても、壊れたデータが戻ってくる。

ZFSでは読み取り時にブロックごとのチェックサムを毎回検証するため、この「静かな破損」を高い確度で検出できます。ただし万能ではありません。チェックサム衝突の理論上の可能性、RAMやアプリケーション層で生じた破損(正しいチェックサム付きで壊れたデータが書き込まれるケース)、そして冗長性のないシングルディスク構成では修復できず検出のみに留まります。セルフヒーリングはミラー/RAID-Z構成のプールで、正しいコピーが存在する場合に機能する仕組みです。

スクラブとセルフヒーリング

では、頻繁に読まれないデータはどうなるのか。それがスクラブ(zpool scrub)だ。プール内の全ブロックを総点検し、チェックサム不一致を洗い出す。ミラーやRAID-Zといった冗長構成を取っていれば、不一致を検出した時点でセルフヒーリング——正しいコピーまたはパリティから自動修復——が働く。管理者が壊れたファイルを探し回る必要はない。

破損検出から修復までの流れは次のとおりだ。

flowchart TD
    A["月次スクラブ実行<br/>zpool scrub tank"] --> B["全ブロックのチェックサム検証"]
    B --> C{チェックサム一致?}
    C -- はい --> D["正常: 何もしない"]
    C -- 不一致 --> E["ミラー/パリティから<br/>正しいコピーを再構成"]
    E --> F{修復用データは正常?}
    F -- はい --> G["破損ブロックを書き戻し<br/>セルフヒーリング完了"]
    F -- いいえ --> H["CKSUMエラーとして記録<br/>zpool status -v で確認"]
    H --> I["該当ファイルの復元を検討<br/>(バックアップ/レプリカから)"]

運用:zpool status -v

エラーの統計は zpool status -v で確認できる。CKSUM 列の増加がチェックサム不一致、zpool status -v tank の詳細出力には破損が特定できたファイルパスが表示される。スクラブは月次のcron/systemdタイマー登録が定番で、TrueNASならUIでスケジュールできる。実行中のスクラブは zpool scrub -s で中断可能、進捗は zpool status に表示される。

「ディスクが壊れたら交換すればいい」の時代から、「壊れる前に、壊れても、データ自身が自分の健全性を証明する」時代へ。これがZFSを選ぶ技術的な核心である。

RAID-Zとミラーの比較——プール設計の実践

ZFSのプール設計で最初に決めるのはvdev(仮想デバイス)の構成です。vdevがプールの構成単位であり、複数のvdevを束ねたものがプール(tank等)になります。代表的なvdevは、パリティ1/2/3重のRAID-Z1/Z2/Z3(RAID5/6/7.20相当)と、2〜3台で組むミラー(RAID1相当)です。

従来のRAIDとの違いは大きく2つあります。第一に、ハードウェアRAIDが悩まされてきたwrite hole問題——障害直近の更新でパリティとデータが不整合を起こす問題——を、ZFSはCoWとトランザクショナルな書き込みで構造的に解消しています。バッテリバックアップも特別なコントローラも不要です。第二に、リビルド(resilver)がディスク全容量の走査ではなく、実装によっては使用ブロックを対象とする方式が採られていること。空き領域の多いプールでは復旧が比較的早く済む傾向がありますが、resilverの方式や所要時間はOpenZFSのバージョン、プール構成、使用量、I/O負荷に依存するため一概には断定できません。

両者の性質を比較すると次のとおりです。

| 観点 | RAID-Z1/Z2/Z3 | ミラー(vdev) |
|---|---|---|
| ディスク効率 | Z1: 67%(3台) / Z2: 50%(4台) | 50% |
| ランダムI/O | 低め | 高い |
| 段階的拡張 | しづらい(2.3で改善) | ペア単位で容易 |
| リビルド | 長い | 短い |

実容量を8TBディスク×N台(同容量の場合の概算)で計算してみましょう。RAID-Z1×3台は3×8−8で約16TB、RAID-Z2×4台は4×8−16で約16TB、ミラー2台は約8TB、ミラー3組×6台は約24TBです。実際の実効容量はレコードサイズ、ashift、ディスク構成、メタデータ等によって変動するため、あくまで目安として扱ってください(OpenZFSの RAIDZ / zfsconcepts のドキュメントに容量の考え方がまとまっています)。

RAID-Zの弱点だった拡張性はRAID-Z expansionで大きく改善しました。OpenZFS 2.3(2024年末リリース)から、既存のRAID-Z vdevにディスクを1台追加してプールを拡張できるようになったのです。それまでは同サイズのvdev丸ごと追加か、zfs send/recv で作り直すしかありませんでした。ただし拡張領域はindirect mappingというレイアウトを挟むため、若干の性能低下がある点は留意が必要です。

選び方の指針はシンプルです。大容量のファイル保存・低予算・読み取り中心ならRAID-Z、とくに3TB超の現代ディスクではパリティ2重のRAID-Z2が安心です。VMディスクやデータベースなどランダムI/Oが多い用途・ペア単位での段階的拡張を重視するならミラーです。ミラーはディスク効率50%というコストと引き換えに、I/O性能・拡張柔軟性・リビルドの速さを得られます。ホームラボなら「VM用ミラープール+アーカイブ用RAID-Z2プール」とプールを分ける設計も定石です。

スナップショット・レプリケーション・圧縮——バックアップ運用

ZFSの運用面での恩恵を最も実感できるのが、スナップショット・レプリケーション・圧縮の三機能だろう。いずれもファイルシステム自身に組み込まれており、追加のソフトウェアなしで使える。

O(1)で作れるスナップショット

zfs snapshot tank/data@20260922 の一撃で、その瞬間のデータセット全体の読み取り専用コピーが作成できる。ポイントは処理コストが O(1)、つまりデータセットが何TBあっても作成は一瞬だという点だ。CoWの構造上、スナップショットは「現在のブロックツリーへの参照を固定する」だけで、データの複製は発生しない。以降は変更があったブロックだけが追加で消費され、実容量の増加は差分のみで済む。

この性質のため、 hourly / daily / weekly といった頻度での自動スナップショットが現実的な運用になる。誤ってファイルを削除してしまっても zfs rollback か古いスナップショットからのファイルコピーで即復帰でき、OSアップデートの失敗やランサムウェアによる暗号化(書き換え)からも、侵害前に取ったスナップショットが残っていれば比較的迅速に復元できる場合が多い。ただし攻撃者がスナップショット自体を削除できないよう権限分離・保持ポリシーを設けること、別ホストやオフライン・不変バックアップを併用すること、復元テストをしておくことが重要です。なおスナップショットを書き込み可能な分岐として展開する クローン(zfs clone) もあり、本番環境のコピーを壊さずに検証環境を作るような用途に便利だ。

zfs send/recv による増分レプリケーション

スナップショットは同一プール上に存在するため、これだけではディスク故障からデータを守れない。そこで使うのが zfs send / zfs recv だ。スナップショット間の差分ブロックのみをストリームで転送でき、zfs send -I で中間差分をまとめて流せる。初回だけ全量を送り、以降は増分だけで済む効率的なレプリケーションが構成できる。Proxmox VEの「レプリケーション」やTrueNASのレプリケーションタスクの中身はまさにこれで、SSH越しに別マシンのZFSプールへ送るのが定番の使い方だ。

LZ4 / ZSTD 圧縮

ZFSは透過的な圧縮にも対応する。LZ4 は圧縮・展開が非常に高速で、圧縮効率の低いデータでも判定コストがわずかしかないため、実質無料と言ってよい。より圧縮率の高い ZSTD(レベル指定可)も選べる。テキスト・JSON・VMディスクイメージは圧縮効果が大きく、ディスク容量の節約と読み取りI/O削減を同時に得られる。圧縮を無効化する理由はほぼない。

スナップショット≠バックアップ

最後に重要な注意点。スナップショットはバックアップそのものではない。同じ物理ディスク上に存在するため、ディスク故障・プール全損時にはスナップショットも一緒に失われる。ランサムウェア対策としても、攻撃者にrootを取られればスナップショットは削除されうる。データ保護の基本は 3-2-1の原則——データ3コピー・メディア2種・オフサイト1複製——であり、ZFSでは「ローカルのスナップショットで素早く復帰しつつ、zfs send で別の物理プール/遠隔地に複製を置く」という二段構えが正しい運用形だ。

ホームラボ実践構成とチェックリスト

最後に、実際にZFSを導入する際の構成選びと、初心者が陥りやすい落とし穴を避けるためのチェックリストをまとめます。

構成別の選び方

観点 Proxmox VE (ZFSPool) TrueNAS SCALE Linux (Ubuntu)
向いている用途 仮想化基盤・VM/LXC運用 ファイルサーバー・NAS 自由な自前構築・学習
ZFS導入 インストーラで選択可 OS自体がZFS前提 zfsutils-linuxで導入
操作感 Web UI + CLI Web UI中心(スクラブ・スナップショット・レプリケーションをGUI管理) CLI中心
VMストレージ ZFSPool(thin・スナップショット対応) zvol zvol / dataset
運用手間 中 小(UI任せ) 大(全部自前)

Proxmox VE を使うなら、VMディスクはCeph RBDではなく ZFSPool ストレージが単一ノードでは自然な選択です。LXCコンテナはデータセットとして直接置かれるため、スナップショット・バックアップ・レプリケーションと好相性。TrueNAS SCALE はZFS前提のNAS OSで、プール作成から月次スクラブ、スナップショット世代管理、リモートへのレプリケーションまでWeb UIで完結します。Ubuntu等のLinux は zfsutils-linux を入れ、zpool create から自分で組み上げる自由度重視の選択。学習目的や特殊な要件がある人向けです。

導入チェックリスト(ステップ形式)

  1. ディスクは /dev/disk/by-id/ で指定し、ashift は実ディスクの物理セクタサイズに合わせて明示する(4Kセクタの現行ディスクではashift=12が一般的)。/dev/sda のような名前は再起動で入れ替わることがあり、by-idパスなら確実。
  2. vdev構成を将来の拡張まで見て決める。RAID-Z2かミラーか。プールの冗長性は最小のvdevに律されるため、RAID-Z1のvdevに後からミラーを追加しても意味が薄い点に注意。
  3. compression=lz4(またはzstd)を有効化。LZ4は高速で実質無料、VMディスクやテキストはよく圧縮されます。無効化する理由はほぼありません。
  4. recordsizeをワークロードに合わせる。デフォルト128KBのままでも汎用には問題ないが、DB向けにはより小さい値(例: 16–64KB)への変更がよく知られたチューニングです。最適値はワークロードと実測に基づいて決めてください。
  5. ARC上限(zfs_arc_max)を環境に合わせて設定。ARCの既定の上限はプラットフォームやバージョンによって異なります(Proxmox VEの公式文書では版により異なる既定値が示されています)。VMとメモリを共有する環境では、ホストRAMと実際のワークロード・実測値に基づいて上限を決めるのが安全です。
  6. 月次スクラブをcron/systemdタイマーに登録。zpool scrub tank を定期実行し、zpool status -v でエラー統計を確認する習慣をつけます。
  7. スナップショットの世代管理+別物理プールへの zfs send レプリケーションを設定。スナップショットはバックアップではないため、3-2-1の原則に沿って別の物理デバイスへ複製して初めてバックアップになります。
  8. プール使用率の上限を運用ルールに。経験則として80%を超えると性能が低下しやすく、90%以上では性能劣化や運用リスクが増すとされています(環境・ワークロード依存の目安として扱う)。アラート化しておくと安心です。

ECCメモリについて

「ZFSにはECCメモリが必須」という言説をよく見かけますが、これはやや誇張です。ECCはRAM起因の破損を早期に検出できるだけで、非ECC環境でもZFSのチェックサム・セルフヒーリングは問題なく機能します。可能ならECC搭載機が望ましいものの、推奨だが必須ではない、というのがフェアな結論です。手持ちの非ECCマシンでも、ZFS導入の障害にはなりません。

まずは余ったディスク2台のミラーテストプールでスクラブとスナップショット復元を一度体験してから、本番設計に進むのがおすすめです。

よくある質問(FAQ)

Q: ZFSにECCメモリは必須?

A: 必須ではありません。「ZFSを使うならECCが絶対」という説をよく見かけますが、これはやや誇張された言い方です。ECCメモリが果たす役割は「RAM起因のビット反転を検出・訂正する」ことであって、ZFSの機能そのものは非ECC環境でも問題なく動作します。ポイントは、RAMで破損したデータはどんなファイルシステムでも正しく書き込まれてしまうという点です。ext4でもNTFSでもそれは同じであり、ZFSだから特別に危険というわけではありません。ECCがあればメモリ経由の破損を早期に捕捉できるため「可能なら推奨、ただし必須ではない」というのがフェアな結論です。古いワークステーションやXeon搭載機を中古で調達すればECC環境は意外と安く手に入りますが、非ECCの普通のデスクトップ機でもZFSのチェックサム・セルフヒーリングの恩恵は十分に受けられます。

Q: RAID-Z1にすべき? ミラーにすべき?

A: ワークロードと拡張計画で決めます。大容量のファイル保存(動画・写真・アーカイブ)が中心で予算を抑えたいならRAID-Zが有利です。3台のRAID-Z1で実効容量67%、4台のRAID-Z2なら50%で二重故障に耐えられます。信頼性の面からはディスク台数が多いならZ1よりZ2を推奨します。一方、VMディスクやデータベースなどランダムI/Oが多い用途、あるいは「2台ずつペアを追加して少しずつ増やす」段階的な拡張を重視するならミラーvdevが適しています。ミラーはリビルドが速く、障害時の復旧もシンプルです。OpenZFS 2.3でRAID-Z vdevへのディスク追加(expansion)が可能になりましたが、当分は「まとまった台数をvdevとして追加する」設計が安全です。プールの冗長性は最も弱いvdevに律されることも覚えておきましょう。

Q: スナップショットはバックアップになる?

A: なりません。これが最も誤解されやすい点です。スナップショットは同一のプール・同一の物理ディスク上に保持されるため、ディスク自体の故障やプール全体の破損からはデータを守れません。スナップショットが真価を発揮するのは「誤削除・誤変換・ランサムウェア・失敗したアップデート」からの復帰です。作成はO(1)で一瞬、差分ブロックのみを消費するため、時間単位・日単位の世代管理が現実的に行えます。ただし本来のバックアップにするには、zfs send / zfs recv でスナップショットの差分を別の物理プールや遠隔地のマシンへ転送するレプリケーションが必要です。Proxmox VEやTrueNASのレプリケーション機能の実体はこれです。3-2-1の原則(3コピー・2メディア・1オフサイト)に沿って、スナップショット+別プールへのsendを組み合わせて初めてバックアップと呼べます。

Q: Raspberry Piでも動く?

A: 動きますが、実験用途向きと考えてください。Linux用のOpenZFSをRaspberry Pi OS(64bit)でソースからビルド、あるいはパッケージで導入して動作させている報告は多数あります。ただし実用的なNASストレージとしては課題が多く、まずRAMが少なくARCキャッシュに十分な容量を割けません。次にディスク接続がUSB経由になりがちで、電源の安定性や転送エラーの面でSATA接続に劣ります。さらにカーネル更新のたびにARM向けモジュールの再ビルド・追従が必要になる場合があります。ZFSの概念を学んだり、小規模なレプリケーション転送先(受け側)として使うのは十分に有効ですが、常用するデータの置き場所としてはx86機+SATA(できればECC)環境を推奨します。

まとめ——今日から始める3つのアクション

ここまで見てきたように、ZFSの本質は「データ整合性をファイルシステム自身が守る」という設計思想にあります。従来のホームサーバー構成では、ext4 + LVM + mdadm/ハードウェアRAID + バックアップツールという多層レイヤーを組み合わせており、エンドツーエンドのデータ検証がない構成では、サイレントコラプション(ビットロット)を検出できないまま正常なデータとして読み返される(場合によっては複製される)危険を抱えていました。ZFSはこれらの多層構成を単一レイヤーに統合し、チェックサム検証・スクラブ・セルフヒーリングを常時働かせることで、ファイルシステムの層でデータの検出可能性と修復力を高めます。理屈はこれで十分。残すは実践です。今日から始められる3つのアクションを紹介します。

① 現行構成の点検 まず、いま運用中のNASやProxmoxのストレージ構成を書き出してください。RAIDレベル、ファイルシステム、そして「サイレントコラプションを検出する仕組みがあるか」を確認します。多くの場合、ここが空白です。スクラブ相当の運用(zpool scrub やファイルシステムレベルのチェックサム検証)が存在しなければ、静かに進む破損に気づけない状態にあると認識しましょう。

② テストプールで体験する 次に、余ったディスク2台でミラーのテストプールを作ってみてください。zpool create test mirror /dev/disk/by-id/... で数分で用意できます。スナップショットを撮り(zfs snapshot)、ファイルを削除し、スナップショットから復元する。最後に zpool scrub を実行し、zpool status -v でエラー統計を確認する。この一連の体験が、ZFSの価値を説明より確実に理解させてくれます。

③ 本番移行計画を1ページにまとめる 最後に、本番移行の計画を1ページにまとめます。ポイントは3つ。vdev設計(RAID-Z2かミラーか、将来の拡張単位まで決める)、プール使用率は80%上限(90%で警告)という運用ルール、そしてスナップショット≠バックアップであることを踏まえ、別物理プールへの zfs send レプリケーション(3-2-1の原則)を組み込むことです。

ハードルは思ったより低い。テストプールを始める今日が、データ整合性を自分で守る最初の一歩です。

参考文献

関連記事