Chienomi

2台のSSDをLUKS+md(mdadm/dm-raid)+F2FSでキャッシュ用にする

Live With Linux::technique

事の発端としてはゲームに使用しているWindowsの空き容量が足りなくなったことだ。 ゲーム自体のインストール容量も大きいが、Radeon ReLiveの録画がすぐ数百GBになってしまうため、かなりこまめに転送しないといけない。 残り100GB程度まで減ったことで非常に使いにくくなってしまった。

そこで現状1TBのWindows用SSD(PCIe 3.0 M.2)を2TBにリプレイスすることを決めた。

問題はSSDの行き場である。 現在、PCIe M.2ディスクを使うのは

  • ラップトップ2台
  • 2機内蔵のデスクトップ2台
  • 1機内蔵のデスクトップ1台
  • 1機拡張のデスクトップ1台

となっている。

ラップトップは自身がもともと持っているものがあるため除外するとして、2機挿しのデスクトップは埋まっている状態。 1機挿しの2台はそれぞれ2.5インチのSSDを使用している。

拡張のものに関しては480GBのSSDを搭載する。 これでも足りないくらいなので、1TBのSSDを搭載するという方法はなくはない。 だが、これはリビング機のWindowsで、ほぼ使っていないのでもったいない話になってしまう。

そして残る1機は防音室にあるもので、ドラムを叩くときに音楽を再生するためのもので、計算力を使うことがなく容量も必要ない。

結果的に1TBのSSDを浮いてしまったが、ここで先ごろから考えていた「メインデスクトップのキャッシュに2TB欲しい→960GBが2台あるからRAIDにすれば良いのではないか」を実現するべく

  1. 現在256GBのSSDを使っているP720のLinuxを浮いた1TB SSDに
  2. P720のキャッシュSSD(960GB)の内容を新しい内蔵ディスクに移す
  3. メインデスクトップのキャッシュSSD(1TB)のデータを退避させる
  4. 同SSDにUSB-SSD(960GB)のデータを移し、ポータブルSSDとする
  5. 2つの960GB SSDをメインデスクトップに組み込み、RAID0を構成する

というプランを立てた。

これによる狙いは

  • メインデスクトップのキャッシュ容量の拡大
  • メインデスクトップに対する転送速度の向上

である。

後者については、様々な条件下で工夫してもメインデスクトップに対するデータ転送速度が40MB/s程度に留まることが多く、これはSSDの書き込み速度に対してかなり低い値だが、 数百GBにも及ぶデータを書き込むときにスタックしてしまうこともあり、書き込みの高速化によってデータ転送自体を改善することができないか、というものである。 最も多いケースはP720からメインデスクトップへの転送になるが、HDDからの転送でも40MB/s程度に留まっている。

前提の検討事項

SSDは1TBをまとめるべきか

8TBまで容量単価が同じなので、単に容量がほしければ大きいディスクを買うほうが良い。

今回の場合、既にある2つの960GB SSDを活かそうということである。 (500GBや1TBのSSDの容量がやや微妙で、不足しがちだから)

Btrfs RAID0 vs mdadm F2FS

実はBtrfsのRAID0は「あんまり速くない」。

Btrfs RAID1 vs md(dm-raid) mirrored Btrfsなら考える余地はある。 というよりも、メタデータ破損などの状況を考えると、これはBtrfs RAID1のほうが堅牢だと言える。 (復帰はmdadmのほうが簡単で早い。)

速さの問題としてはBtrfs RAID0よりもBtrfs on md RAIO0のほうが速く、 mdでまとめるのであればファイルシステムにBtrfsの縛りはなく、より高速なF2FSを使うことができる。

md RAIO0 vs LVM stripeという話をするならば、基本的にmdのほうが高速だが、柔軟性はLVMが優る。

mdadmとLUKS、どっちが上か

パフォーマンス的にはmd上にLUKSとしたほうが良いらしい。

しかし、これはmdにおけるストライプ幅とファイルシステムのチューニングを合わせることが困難になるほか、暗号化レイヤーの取り扱いに難がある。 このため、dm-crypt, dm-raid, filesytemの順に並べる。

mdadm(=md, dm-raid)とLUKS(dm-crypt luks)を組み合わせる場合、ほとんどのケースで「/dev/md0を暗号化する」という方法が取られているが、 ここではその逆を選択する。 逆の実現方法は記事として見当たらなかったので、参考になるかもしれない。

実施

1TB Windows to 2TB

  1. ddで複製
  2. sync
  3. GPartedでディスクサイズをfix
  4. GPartedでリカバリーパーティションを末尾へ移動
  5. Windowsでパーティションを拡大

ディスクサイズのfixやパーティションの移動はWindowsのパーティショナーでできないため、GPartedで行う。

256GB Linux (incl. LUKS Swap) to 1TB

これは、LUKSのかかったSwapを移動させる方法がわからなかったので、 新規パーティションで対応した。

結果的にデータキャッシュ部分にF2FSを使えたので悪くない。

Rotate 2x 960GB and 1TB

ふたつの960GBと1TBのディスクはそれぞれある程度のデータが入っており、 今回は1TBのディスクの位置にふたつの960GBディスクが置かれる。 960GBのディスクは、それぞれ追加されたLinuxの後方パーティションと1TBディスクに配置される。

まずは960GBディスクのひとつのファイルをLinuxの後方パーティションにコピーする。 これで960GBがひとつ空く。

次に1TBのディスクを退避させる。 私の場合、6TBディスクが別にあるので、ここに退避させることになる。 今回、動画ファイルの圧縮が必要だったため、ここにかなり時間がかかった。

これで1TBディスクのファイルシステムを作り直し、960GBディスクの内容を入れる。 F2FSを新規に作るときはcryptsetupにおいて--allow-discardsをつけるのを忘れずに。 これにより、F2FS作成時にSSDをクリーンアップできる。

これで2つの960GBディスクが空いたので、取り付けてmdadmによるセットアップを行う。

mdadm, cryptsetup, mount

luksFormat

まずはキーファイルを作る。ここではルートファイルシステムは暗号化されている前提で、ルートファイルシステムから連鎖的にアンロックする流れを考える。

# dd if=/dev/urandom of=/etc/mysystem/cachedisk.key.bin bs=512 count=8

バイナリキーでもテキストキーでも指定の仕方は変わらない。

# cryptsetup luksFormat --key-file=/etc/mysystem/cachedisk.key.bin /dev/sda
# cryptsetup luksFormat --key-file=/etc/mysystem/cachedisk.key.bin /dev/sdb

自動解除

システム起動時にアンロックするには/etc/crypttabに記載する。

今回気づいたのだが、Manjaroの起動時のシーケンスは、パスフレーズ入力した内容をキーファイルにして、テキストキーファイルとしてアンロックしているようだ。

crypttabファイルは、名前(cryptsetupのデバイス名と同じ。/dev/mapper/<name>になる), デバイス, キーファイル, オプションの順。 オプションのluksをお忘れなく。

cachessd-A UUID=ABCDE-FGHI-JKLMNOP /etc/mysystem/cachedisk.key.bin luks
cachessd-B UUID=QRSTU-VWXY-ZABCDEF /etc/mysystem/cachedisk.key.bin luks

これなら別にplainでも良さそうだな、と思った。

ここで間違えると起動しなくなる。 起動しなくなった場合、ライブシステムで起動して本来のルートファイルシステムをマウントし、crypttabファイルを修正するというリカバリーが必要になる。

再起動せずにそのままオープンする場合は

# cryptsetup luksOpen --key-file=/etc/mysystem/cachedisk.key.bin UUID=ABCDE-FGHI-JKLMNOP cachessd-A 
# cryptsetup luksOpen --key-file=/etc/mysystem/cachedisk.key.bin UUID=QRSTU-VWXY-ZABCDEF cachessd-B

mdadmのセットアップと自動編成の設定

# mdadm --create /dev/md0 --verbose --level=0 --chunk=64 --raid-devices=2 /dev/mapper/cachessd-*
# mdadm --detail --scan >> /etc/mdadm.conf

Archwikiの記事では --create のあとの値が抜けているので注意。

ここでは64kBチャンクにした。

ファイルシステムの作成

F2FSはファイルシステム自体のチューニングができない。 そのためRAID0のパフォーマンスを十分に活かせないが、それでもなおF2FSは速い。

# mkfs.f2fs -l SSDLocalCache -O extra_attr,inode_crtime,compression -t 0 /dev/disk/by-uuid/GHIJK-LMNOPQRS-TUVWXY

Windows系ファイルシステムへのファイルのコピー時に楽をしたい場合、casefoldも使うと良いだろう。 だが、私が試した限りだと、casefoldを有効にするとマウントできない。

LUKSを使う場合、デフォルトではDiscardを許さないため、Discardは無効にしたほうが良い。 安全性を犠牲にしてDiscardを許すのであれば、LUKS側のフラグに設定した上で有効にすることになる。 LUKSはオープン時に切り替えられるが、F2FSはファイルシステムを作るときに切り替える形になっている。

ファイルシステムの自動マウント

/etc/fstabに記載。crypttab同様「コケたらライブディスクで変更する」という覚悟が必要。 nofailをつけておけば、マウントできないがために起動しない、ということは避けられるはずだ。

UUID=GHIJK-LMNOPQRS-TUVWXY /home/foo/data f2fs defaults,noatime,nofail 0 0

効果はあったか

なかった。

結局、転送速度は40MB/s程度にとどまっている。

経路は3台のTPLink製ルーターと宅内LAN(LAN延長ケーブルだと思われる)からなり、単純な転送(/dev/zero-socat-/dev/null)でも43MB/sにとどまった。

試しにルーターのLANポートだけでつないだところ、AX73でもAC1200でも117MB/sとなり、ネットワーク上限に近い速度が出た。 また、ローカルに/dev/zeroからSSDストライプへの40GBの書き込みを行ったところ、498MB/sの速度が出た。

このことからボトルネックは宅内LANであることが判明した。

宅内LANの仕様として100BASE-TXであると記されているので、「遅い」と言えるような状況ではないのだが、 40MB/s出ている以上実際は1000BASE-Tであると思われ、にも関わらず40MB/sしか出ない、というのはよくわからない。

速度をケアするなら宅内LANを使わずに配線すれば良いが、対象の2台はかなり離れており、長い線を這わせる気にはならない。 結局、時間がかかるのは致し方なし、あまりにも巨大で時間がかかるならどちらかのPC自体を近くに持っていく、ということになるだろうか。 それでもネットワーク経由だと117MB/sにしかならないので、「3倍で十分か」というとまた微妙ではあるのだが。

ただし、速度が向上したことで~/.cacheの置き場としての性能が向上し、容量も拡大したので無駄ではないし、意図としては達成している。 ついでに、今まで面倒がってやらなかった自動マウントまで手を付けたことで使いやすさはさらに向上した。