世界を動かす技術を、日本語で。

高速かつ低コストの大容量ストレージ:SSD上でHDDをキャッシュするためのLVMの利用

概要

  • SSDとHDDのハイブリッドストレージ構成の利点と時代背景
  • LVMキャッシュによるSSDキャッシュ付きRAID 1 HDDアレイの構築手順
  • RAID 1によるHDD冗長化と障害対策の重要性
  • LVMの基本概念とセットアップ方法の解説
  • mdadmによるRAID 1作成、SSDパーティション作成、LVMキャッシュ設定の実践手順

SSDキャッシュ付きRAID 1 HDDストレージ構成の構築

  • SSD はランダムI/Oに優れた速度を持つが、 HDD は大容量・低コストストレージ用途
  • 頻繁にアクセスされるデータのみ SSDキャッシュ に保存し、他はHDDに保存する構成
  • かつては SSHDZFSのL2ARC などが主流だったが、SSD価格低下で一般用途では不要に
  • 大容量データの一部だけ高速アクセスが必要な場合(ミラーサイトやローカルLLM運用等)で有効
  • ZFSはLinux互換性の課題があるため、 LVMmdadm を組み合わせた構成を選択

LVMキャッシュを選ぶ理由

  • Linuxには他にも bcacheEnhanceIO などのブロックデバイスキャッシュ手法あり
    • bcacheはブロックデバイス全体の所有や設定の永続性・データ破損報告が難点
    • EnhanceIOはメンテナンスされておらず非推奨
  • LVMは構成情報の永続性・柔軟な管理・既存環境との親和性で優位
  • LVMの知識や運用経験がある場合、導入・運用の学習コストが低い

LVMの基礎知識

  • ブロックデバイス :/dev/sdaなど、一定サイズのデータブロックを持つデバイス
  • パーティション :/dev/sda1など、ブロックデバイスを分割した論理領域
  • LVMの3要素
    • Physical Volume (PV) :LVMで利用する物理ストレージ
    • Volume Group (VG) :複数PVを束ねて管理する単位
    • Logical Volume (LV) :VG上に作成する論理パーティション
  • LVは通常のパーティションのように利用可能で、サイズ拡張や動的割り当てが容易
  • キャッシュ付きLVThin pool 等、高度なLVも利用可能

ハードウェア構成例

  • 4TB SATA HDD x2(/dev/sda, /dev/sdb)を用意
  • 2TB SSD(/dev/nvme0n1)の一部(例:100GiB)をキャッシュ用パーティションとして利用
  • lsblk コマンドでデバイス確認を推奨
  • コマンド実行前は wipefs 等でデータ消去やパーティション確認を徹底

なぜHDDにRAID 1を使うのか

  • HDDは機械的故障が避けられない ため、冗長化が重要
  • データを冗長化せず単一ドライブやRAID 0で運用すると、故障時の復旧・再構築コストが高い
  • RAID 1なら 片方のドライブ故障時もサービス継続 が可能
  • 異なるメーカーや型番のドライブを組み合わせることで同時故障リスク低減

HDDパーティション分割の注意点

  • RAID構成時、 全デバイスのサイズ一致が必須
  • 「4TB」表記でも実容量に差があるため、正確なセクタ数でパーティションを切る
    • 例:4,000,000,000,000バイト ÷ 512バイト = 7,812,499,999セクタ
  • gdisk コマンドでGPTパーティションテーブル作成
    • パーティションタイプは「Linux RAID (fd00)」
    • 識別用に名前を付与すると管理が容易

mdadmによるRAID 1アレイ作成

  • mdadm --create でRAID 1アレイ(例:/dev/md0)を作成
  • 作成後、 /etc/mdadm/mdadm.conf に定義を追加し、initramfsを更新
  • /proc/mdstat で同期状況を確認可能(同期中も作業継続可能)

SSDキャッシュパーティションの作成

  • SSDの未使用領域 にキャッシュ用パーティションを作成
  • キャッシュパーティションは LVM LVではなく物理パーティション とすること
    • ネストしたLVM構成は不安定で、データ破損リスクが高い
  • パーティション作成後、LVM PVとして登録し、VGに追加

この後の手順(LVMキャッシュLVの作成、ファイルシステム作成、マウント、監視方法など)は省略されていますが、上記の流れで 信頼性と高速性を両立したストレージ構成 を構築可能です。

Hackerたちの意見

キャッシングのYMMVはアクセスパターンによるけど、私の場合、もっとも一貫してキャッシュ可能なパターンはext4のジャーナルだね。サイズが小さくて、すごい数のIOPSがヒットすることが多い。ext4は外部ジャーナルをサポートしていて、遅いSMRディスクがたくさんある場合に、それを単一のSSDに移動するのが過去にはうまくいった。ただ、SSDが故障すると、いくつかのディスクからのデータ損失の根本原因になっちゃう(リードキャッシュとは違って)。私が働いていたところでは、HDFSを使っていて、RAIDよりも複数のディスクのJBODレイアウトが好きだったから、ノードが完全に故障しても問題なかったし、大きなファイルをたくさんの固定サイズのファイル(blk_という名前)として書き込むことで、メタデータ操作がたくさんあった。SSDはその頃高かったけど、ここ10年で安くなってきたね。

ハイブリッドドライブを思い出すな。NVMが故障したときは、対処が大変だった。個人的には、安定性の観点から、ドライブから不揮発性メモリにキャッシュするのは悪いアイデアだと思う。

ZFSにも同じことが言えるよ。「zil」デバイスを作るためのプロビジョニングがある - ZFS Intent Log、基本的にはジャーナルだね。ZFSはこのジャーナルが明示的に使い捨てである点がちょっといい。ZILデバイスを失うと、そのホライズン以降の書き込みを失うけど、全体のアレイを失うわけじゃない。次のステップは「メタデータ」デバイスを構築することで、ファイルシステムのメタデータを保存するけどデータは保存しない。これはext4ジャーナルと同じように危険で、メタデータを失うと全てを失うことになる。どちらも大幅なスピードアップになる。大きな書き込みをするとき、たくさんのスピニングラストだけではSSD ZILなしではフルスループットを達成できない。私の8+2アレイはほぼ2ギガビット書き込めるけど、ZILなしではひどい(単一のドライブの速度程度)。同様に、メタデータデバイスはファイルシステム全体をSSDのようにスナッピーに感じさせることができるけど、十分なキャッシュスペースがあれば必要ない。ZFSはそれを好むから、メタデータがキャッシュSSDに収まるなら、大部分は常にロードされた状態になるよ。

しかし、SSDが故障すると、それがいくつかのディスクからのデータ損失の根本原因になる(リードキャッシュとは違って)。理論的には、ジャーナルのコピーをメモリに保持することで、このリスクを大幅に減らせるけど、ディスクの損失と電源の喪失が数秒以内に起こらない限り、壊れないんだ。でも、利用可能なツールがそれを適切に行えるかは分からないな。

ツインSSDとRAID 1。

オプテインドライブが懐かしいな。

Aliexpressでまだ買えるうちに一つゲットしとこうかな。

RAID1のことを忘れがちなのは、これは壊滅的なディスク故障からしか守れないってこと。つまり、RAIDが保護するためにはドライブが死んでないといけないんだよね。問題は、データが壊れ始めると、RAIDはそれを知る手段がないこと。そうなると、健康なドライブのデータも壊れちゃうことがある(壊れたデータが読み込まれて、両方のドライブに書き込まれる)。データのコピーが2つあるけど、RAIDはどちらが正しいか判断できないから、基本的にはコインを投げてどちらかを選ぶことになる。たとえファイルシステムがその内容が意味をなさないことを知っていても。これが、ZFSやBtrfsのようなファイルシステムの最大の利点で、RAIDを自分で管理していて、チェックサムがあって、どのコピーが有効かを知っていて、復旧できるんだ。だから、1つのドライブは健康そうに見えてもデータを壊しているから、交換した方がいいよって教えてくれる。

2011年頃にその体験をしたことがあるよ。MinecraftサーバーをRAID1のボックスでホストしてたんだ。面白いのは、1時間ごとにマップをPNGファイルにレンダリングするcronジョブを動かしてたこと。ある時、友達からマップに穴が開いてるって聞かれたんだよね。当時、Minecraftはマップの16x16チャンクを個別のgzippedファイルに保存してたんだ。RAID1が悪いドライブからチャンクを読み込もうとすると、解凍できなかったんだよ。それがレンダラーに起こると、マップに穴ができちゃうし、ゲームサーバーに起こるとチャンクが再生成されて、古いものが両方のドライブ、健康な方も上書きされちゃう。幸いなことに、確かそれはランダムな地形でしか起こらなかったから、誰かが家の半分を失うことはなかったけどね。

LVMを使うと、dm-integrityターゲットを使ってデータの破損を検出できるよ。

自分の高級RAID5カードがディスクアクセスにDMAを使ってて、自前のメモリを持ってないって知った時は驚いたよ。本当にバカな設計だよね。電源の問題でマシンの最後のメモリスティックが壊れちゃって、クリーンに立ち上がるけど負荷がかかるとディスクの破損を報告するようになった。ディスクは問題なかったのに、メモリが壊れてた。メモリアナライザーを使うまで、そのクソ配列を三回も再構築したよ。

QNAP NASシステムのティアリングの技術について知っている人いる?SSD RAID 1をRAID 10の前に使ってるけど、すごくうまく機能してる。個人的には、キャッシングよりも柔軟なティアリングが多くのシステムにとって良いと思う。ユーザーに古いデータと変化するデータを分けるのは結構難しいから。完璧である必要はないことが多いし。

Bcachefsはキャッシングとティアリングの両方をサポートしてるよ:https://wiki.archlinux.org/title/Bcachefs#SSD_caching FUSEベースのソリューションはautotierだね:https://github.com/45Drives/autotier

ZFSが最近(過去5年くらい)専用のメタデータキャッシュデバイスを実装したことを思い出させてくれるね。これにより、ファイルシステムのメタデータや小さなファイルを超高速のSSDミラーにキャッシュできるようになった。これは、非常に遅いRAIDZ3のzpoolでも数千のIOPSを追加する簡単な方法だよ。いつものように、「繰り返し強調するけど、SLOGやL2ARCは失うのが不便なだけだけど、メタデータvdev(あなたの「特別な」vdev)を失うと、他のフルvdevのどれかを失ったのと同じように、zpool全体を失うことになるからね…」

ZFSがプールからメタデータをSSDにミラーリングする方法を持っていることを願ってる。そうすれば、実際にはキャッシュだけど、データ損失の確率が上がらない。

最近やってることの一つは、SSDやSSDのRAID0にデータを保存して、変更されたファイルを遅いHDDに継続的にバックアップすること。単一トランザクションのデータ安全性は求めてないし、バックアップが常に動いてるからデータを失う可能性はすごく小さいんだ。このやり方は、超警戒なHAセットアップよりもずっと速いし、かなり安く済むよ(HDDは別のボックスや建物に置いてもいいし、Glacierとかでもいい)。

もしよかったら、あなたのアプローチについてもう少し詳しく教えてもらえますか? どんなツールを使ってるの? どうやって設定してるの?

LVMはすごくクールなもので、ちょっと過小評価されてる気がする。俺はいつもこんな感じでシステムを構築してきた:2つのハードディスク => RAID1 => LVM VG1、nvme => LVM VG2。LVMは柔軟なパーティションみたいなもので、マニュアルの他の大量の情報にはあまり注意を払ってなかったんだ。結果的にそれはあまり良い方法じゃなかったみたい。LVMはRAIDもできるし、デバイス間での移動も扱えるし、他にもいろんな便利な機能があるんだ。だから、上記のようにする代わりに、RAIDなしで同じVGに全部入れちゃった方がいいよ。個別のLVをRAIDすることもできるし、RAID1、RAID5、RAID0、何もなし、って感じで、どのディスクに何を置くか選べる。MD RAIDができない整合性チェックも追加できるし、キャッシングもできる。書き込み可能なスナップショットもできるし、スリムプロビジョニングもできる。すごく柔軟な技術だよ。ただ、必要ない限りスリムプロビジョニングは避けた方がいいかな。パフォーマンスへの影響が大きいし、virt-managerがなぜかスリムLVを正当なディスクとして認識しない(でも簡単に回避できるけどね)。スリムプロビジョニングは独自の不具合を発生させることもあるみたい。昔のセットアップで、あるブロックがどういうわけか読み取れなくて、それがスリムプロビジョニングのせいだったように思う。基盤のディスクが悪いとは言わず、メタデータが壊れてるみたいな感じ。アップグレードするには、LVを一つのディスクから別のディスクに移動して空けて、取り除くことができる。標準のRAIDよりも、異なるサイズのディスクの問題はずっと少ないよ。

約20年前、誰かのメールサーバーのストレージサーバーを手伝ってたんだけど、10Kのディスクが8台RAID-1で使われてたんだ。常に負荷に苦しんでて、しばしば追いつけなかった。IntelがSSDを出したばかりで、友達がそのサイズより大きいSSDにアクセスできたんだ。小さなノートパソコンのドライブをストレージサーバーに取り付けてもらうために送ったんだ。SSDがサーバーに搭載されたら、稼働中のシステムで「pvmove」を使ってデータを回転するアレイからSSDに移動したんだ。その数時間の間にサーバーの負荷が下がった。これらの8台のハードドライブが、俺の財布より小さいもので置き換えられるなんて面白かったよ。でも、pvmoveがこのショーのもう一つの主役だった。

LVMは過小評価されてるんじゃなくて、もう時代遅れだよ。特にZFSは、LVMを実際に信頼性よく動かそうとするときに遭遇する多くの問題がない(自己破損するスナップショットがないとかね)。

確かにLVM RAIDは内部的にはmdraidを使ってるみたいだね。LVMを使ってRAIDを設定・管理する利点は、必要なツールが一つで済むことだと思う。LVMのユーティリティが必要なものを全部提供してくれればだけど。自分はずっとmdraidを使ってて、時々mdraidデバイスの上にLVMを乗せてたよ。

LVMやZFSを使ってNASを再構築するのはちょっと面倒だけど、最初からやり直すならどちらかを使ってビットロットを避けたいな。今はSATA HDDでRAID 10、NVME SSDでRAID 1を使って、bcacheで両方を一つのボリュームにして、上にext4を乗せてる。十分なSMARTモニタリングとバックアップがあれば大丈夫だと思う。

ある時点でLVMは柔軟なパーティションみたいなもんだと決めつけて、manページにある大量の他の情報にはあまり注意を払わなかったんだ。Linuxを初めて使い始めた時、mdの上にLVMを使うという概念に戸惑ったのを覚えてる。LVMのmanページを読んでたら、他の抽象レイヤーを使わずにLVMだけで全部できることが明らかだった。でも、ハードウェアRAIDコントローラーがあったから、それを使ってたんだよね。

こんな感じのことを試してみようかな。いくつかの大きなHDDにメディアをたくさん保存してて、mergerfs(ユニオンファイルシステム)を使ってそれらをまとめてる。でも、ブロックデバイスじゃなくてファイルレベルでキャッシュする何かが必要だと思う。別々のファイルシステムが異なるディスクにあるからね。このアイデアはここから得たんだ:https://perfectmediaserver.com/02-tech-stack/mergerfs/

私もmergerfsを使ってるよ。結局、全てのドライブをbcache上でmergerfsで動かして、キャッシュ用に1つのSSDを使ってる。mergerfsのドキュメントには階層キャッシングの方法が載ってるよ:https://trapexit.github.io/mergerfs/preview/usage_patterns/ 。ただ、実際にはリードキャッシュはやってないんだ。最新のファイルだけをSSDに保持するだけ。bcachefs(bcacheじゃなくて)がもっと良くなるといいな。私がmergerfsでやってるみたいに、複数の異なる遅いドライブを組み合わせることができるし、SSD上でファイルレベルのキャッシュもできる。さらに、メタデータをSSDに完全に保持することもサポートしてる。エラージャーコーディングはまだできてないから、SnapRAIDの代わりにはならないけどね。

これは良いまとめだけど、パフォーマンス向上を定量的に理解するためのテスト方法論(fioとかrsyncのジョブとか)が欠けてるのが残念だね。

mdadmには特別な憎しみを抱いてるし、LVMにも少しだけ嫌悪感がある。今は管理がずっと楽になってると思うけど、最初に触れたときのドキュメントの質は本当にひどかった。古いシステム管理者が特別な授業を開いて、mdadmで全てを台無しにしないための秘密の知識を教えてくれたんだ。LVMは少しマシだけど、初期のLVMスナップショットの偽の約束は実質的にプラセボだった(今は変わってるかもしれないけど)。実際にLVMが成功したのを見たのは一度だけで、それは60台の悪いLFF RAIDを使って4つのハードウェアRAID-7ディスクアレイで単一の名前空間を作ったときだった。他の時は全部クラスターの大混乱だった。貧乏ならZFS、金持ちならGPFSだね。新しいシステムもあるだろうけど、ほとんどの場合、耐障害性、レイテンシ、パフォーマンステストに失敗する。(咳、gluster、ceph、HTTPを輸送システムとして使うもの全般)