CentOS Stream 9でのVirtual Data Optimizer (VDO) 構築ガイド:圧縮と重複排除でストレージ容量を最適化

CentOS tutorial - IT technology blog
CentOS tutorial - IT technology blog

Linuxにおけるストレージ容量最適化ソリューションの比較

ストレージサーバーやバックアップサーバー、KVM仮想化クラスタの運用管理において、ディスク容量の不足は常に付きまとう課題です。ブロック層やファイルシステム層でこの問題を根本的に解決するため、システム管理者は主に以下の3つのアプローチを検討します。

  • ZFS (ZFS on Linux): ZFSの圧縮および重複排除機能は非常に強力です。しかし、ライセンスの非互換性(CDDL vs GPL)によりRHEL/CentOSのメインラインカーネルには含まれておらず、DKMS経由で外部モジュールをビルドする必要があります。最大の難点は大量のメモリを消費することで、重複排除を有効にすると1TBのストレージあたり通常1GB〜5GBのRAMが必要になります。
  • Btrfs: 透過的圧縮(zstd、lzo)は非常にスムーズに動作します。ただし、Btrfsの重複排除はリアルタイムのインライン処理ではなく、duperemoveなどの外部ツールを用いたオフラインスキャンで実行する必要があります。さらに、Red HatはEnterprise LinuxでのBtrfsサポートを数年前に終了しています。
  • Virtual Data Optimizer (VDO): Red Hatが独自開発し、Linuxカーネルに直接統合されたソリューションです。VDOは仮想ブロックデバイスとして動作し、ディスクへの書き込み直前にゼロブロックの自動排除(Zero-block elimination)、UDSインデックスによるインライン重複排除、LZ4アルゴリズムによるデータ圧縮を実行します。

ソリューション比較一覧表

既存のインフラに適したソリューションを選定するための比較表です:

項目 ZFS on Linux Btrfs (Offline Dedup) LVM-VDO (CentOS Stream 9)
重複排除 (Deduplication) インライン(大量のRAMを消費) オフライン(定期バッチスキャン) インライン(UDSインデックス、低メモリ消費)
データ圧縮 インライン(LZ4、ZSTD) インライン(ZLIB、ZSTD、LZO) インライン(CPU経由のLZ4)
RHEL/CentOSカーネル互換性 サードパーティ製リポジトリが必要 公式サポートなし ネイティブ対応、LVM2に統合済み
リソース消費量 極めて高い(RAMおよびCPU) スキャン実行時に急増 中程度(UDSのRAM使用量を調整可能)

CentOS Stream 9でLVM-VDOが最適な選択肢となる理由

従来のCentOS 7や8では、VDOは独立したデーモンとして動作し、vdoやvdomgrコマンドで管理されていました。しかし、RHEL 9およびCentOS Stream 9において、Red Hatは設計を刷新しました。個別の管理パッケージを廃止し、VDOをLVM2 (LVM-VDO)ツールセットへ完全に統合したのです。

この統合により、以下の3つの大きなメリットがもたらされます:

  • 使い慣れた管理操作: lvcreate、lvextend、lvsなど、日常的に使っているLVMコマンドをそのまま利用できます。固有の新しいCLIを覚える必要はありません。
  • 柔軟なシンプロビジョニング: 推定圧縮率に基づき、物理ディスク容量の3倍から5倍の論理容量を柔軟にオーバーコミットできます。
  • VMやバックアップでの高い効果: 仮想マシンテンプレート(qcow2/raw)や日次バックアップディレクトリでは、60%〜85%のデータ重複が発生することがよくあります。VDOを活用すれば、500GB相当のバックアップデータを実ディスク上ではわずか120GB程度に抑えることが可能です。

LVM-VDOのステップバイステップ構築手順

ここでは、サーバーに50GBの物理ディスク(/dev/sdb)を追加し、150GBの仮想ボリュームを作成してデータを保存する構成例を解説します。

ステップ1: 必要なパッケージのインストールとカーネルモジュールのロード

CentOS 9のデフォルトリポジトリからLVMパッケージとVDOドライバをインストールします:

sudo dnf install -y lvm2 kmod-kvdo vdo

# kvdoカーネルモジュールのロード
sudo modprobe kvdo
lsmod | grep kvdo

ステップ2: フィジカルボリューム (PV) とボリュームグループ (VG) の作成

/dev/sdbにフィジカルボリュームを作成し、vg_storageという名前のボリュームグループを作成します:

# PVの作成
sudo pvcreate /dev/sdb

# VGの作成
sudo vgcreate vg_storage /dev/sdb

ステップ3: VDOプールの作成とロジカルボリューム (LV) のプロビジョニング

--type vdoパラメータを指定してlvcreateコマンドを実行します。以下の例では、物理ディスクから40GBを重複排除/圧縮処理用のプールとして切り出し、システムに対して150GBの仮想容量(Virtual Size)を割り当てます:

sudo lvcreate --type vdo \
  -n vdo_volume \
  -L 40G \
  -V 150G \
  --vdo-pool vdo_pool \
  vg_storage

主要パラメータの解説:

  • -L 40G: データおよびインデックステーブルの保存用にボリュームグループから確保する実物理容量。
  • -V 150G: OS側から認識される仮想サイズ(Virtual Size)。
  • --vdo-pool vdo_pool: 内部で圧縮および重複排除を担うプール名。
  • -n vdo_volume: ファイルシステムをフォーマットしてマウントする最終的なロジカルボリューム名。

ステップ4: ファイルシステムのフォーマットとマウント

XFSファイルシステムでボリュームをフォーマットします。不要なメタデータの肥大化を防ぎ即時フォーマットできるよう、未使用ブロックへのTRIM処理をスキップする-Kオプションを必ず指定してください:

# -Kオプションを付けてXFSファイルシステムをフォーマット
sudo mkfs.xfs -K /dev/vg_storage/vdo_volume

# マウントポイントの作成とテストマウント
sudo mkdir -p /data_vdo
sudo mount /dev/vg_storage/vdo_volume /data_vdo

再起動時にも自動マウントされるよう、/etc/fstabに次の行を追記します:

echo '/dev/vg_storage/vdo_volume /data_vdo xfs defaults 0 0' | sudo tee -a /etc/fstab

ステップ5: 実際の圧縮率と重複排除効果の確認

削減されたストレージ容量を確認するには、vdostatsコマンドを使用します:

sudo vdostats --human-readable

Ubuntu 22.04の仮想マシンのクローンを5台分(各10GB)コピーした後の出力結果例:

Device                    Size      Used Available Use% Space saving%
vg_storage-vdo_pool-vpool 40.0G      9.8G     30.2G  24%           79%

書き込んだ元のファイルサイズ合計は50GBですが、実際に消費された物理容量は10GB未満です。容量節約率(Space saving%)はおよそ80%に達しています。

運用上の注意点とベストプラクティス

  • 物理ディスク残量を常時監視する: オーバープロビジョニングには注意が必要です。物理ディスクが100%枯渇した場合、VDOボリュームはデータ保護のために自動的に読み取り専用(Read-Only)モードに移行します。lvs -a -o +vdo_operating_mode,vdo_compression,vdo_deduplicationコマンドで定期確認するか、プールの使用率が85%を超えた際にPrometheusなどでアラートを発出する構成を推奨します。
  • Sparse Indexによるメモリ最適化: デフォルトのUDSインデックスはdense(高密度)モードで動作し、1TBのストレージのインデックスに約1GBのRAMを使用します。RAMリソースが限られているサーバーでは、--vdo-pool-args '--uds-memory-size=sparse'フラグを指定することで、メモリ消費量を約80%削減(約250MBフットプリント)できます。
  • 圧縮済みファイルをVDOに保存しない: .tar.gzや.zip、MP4動画、暗号化済みデータベースなど、すでに圧縮・暗号化されているファイルは追加の圧縮や重複排除が効きません。これらのファイルをVDOに書き込むと、CPUサイクルを無駄に消費するだけになります。
Share: