Ubuntu Weekly Recipe

第857回bcacheでHDDへの書き込みを見かけ上速くする

今回はLinuxカーネルのブロック層キャッシュ、bcacheを紹介します。

NASとbcache

第851回では、SMBサーバー実装としてKSMBDを紹介しました。

そのときは10GbEを使用しており、速度もそれなりに出ていましたが、テスト用ということで共有フォルダーはNVMe SSD上に作成していました。

NVMe SSDは、2TBであればそれなりに手出しできる価格ですが、NASとして使用するストレージで2TBというのは少々心許ないといっていいでしょう。4TBとなると3〜4万円となり、なかなか手を出すのが難しくなってきます。8TBであればなおさらです。

ではHDDはというと、容量あたりの価格はSSDよりもはるかに安いものの、速度は文字どおり桁違いに遅くなります。せっかくの10GbEが活かせません。

用途にもよりますが、頻繁に読み書きするものの、あまり大きなファイルを置かないストレージをSSDにします。バックアップのような大容量を使用し、書き込みはするもののあまり読み込まないストレージをHDDにすれば、コストパフォーマンスのいいNASになります。

しかし、ここでネックになるのは前述のようにHDDの書き込みの遅さです。この解決のために、SSD上にキャッシュ領域を設けることを考えました。

そこで見つけたのがbcacheです。まさに期待したとおりのものであり、かつ歴史もあって不具合に遭遇することもそうはなさそうです。ファイルシステムで冒険する度胸は、筆者にはありません。SSDに専用のキャッシュ領域を用意するのはわかりますが、HDDもフォーマットし直さなければいけないというのがネックではあるものの、そこがどうにかなるのであれば有用そうです。

具体的な用途としては、Clonezillaのバックアップ置き場を想定しています。バックアップをアーカイブイメージとして作成しているアプリケーション(Acronis True Imageなど)でも同様の効果を得られるでしょう。

HDDに書き込んだ場合

今回は6TB HDDを用意し、ここに適当なフォルダーを作成し、KSMBDで共有します。まずはリファレンスとしてベンチマーク結果を見てみましょう。10GBのファイルを3回転送しています。

図1 直接HDDに書き込んだ場合

10GbEは理論上1250MB/sくらいの速度が出ますが、その1/5くらいしか出ていません。明らかにHDDがボトルネックになっています。

bcacheの設定

では、bcacheを設定していきます。

おさらいになりますが、前提としては専用のSSDとHDDが必要になります。ただし、パーティションでも構いません。用途的には、SSDにはUbuntuとbcacheのパーティションを作成し、HDDは専用となるケースが多いでしょうか。

というわけで、インストールの時点でbcache用のパーティション領域を用意しておきましょう図2⁠。

図2 1TBのSSDのうち、後ろ半分を空けておく

実際にはキャッシュ領域に500GBはいささか多すぎるので、例えば容量の小さなNAS向けSSDを購入するのもいいでしょう。キャッシュ領域は100GBもあれば充分かと思われます。

設定方法はUbuntu Wikiにかかれているものを参考にします。

パーティションは次のとおりです。

  • システムパーテション:/dev/nvme0n1p2
  • SSDキャッシュパーティション:/dev/nvme0n1p3
  • HDD:/dev/sda

繰り返しになりますが、キャッシュパーティションとHDDはフォーマットされます。すなわち、すべてのデータが消えますので、くれぐれも気をつけください。

作業を続行する決意ができたら、端末から次のコマンドを実行してください。

$ sudo apt install bcache-tools
$ sudo dd if=/dev/zero if=/dev/nvme0n1p3 bs=512 count=8
$ sudo dd if=/dev/zero if=/dev/sda bs=512 count=8
$ sudo wipefs -a /dev/nvme0n1p3
$ sudo wipefs -a /dev/sda
$ sudo make-bcache -C /dev/nvme0n1p3 -B /dev/sda --discard --writeback
$ sudo mkfs.ext4 /dev/bcache0
$ sudo mkdir /media/hdd
$ sudo sh -c "/dev/disk/by-uuid/(UUID) /media/bcache ext4 rw 0 0 >> /etc/fstab"

今回作成したHDDのパーティションのUUIDは"8c9c8369-f175-43ea-9ae2-3632d7e7d068"でした。mkfs.ext4コマンドの実行結果にUUIDが含まれるので、それを参考にしてください。以下が実行結果の例です。

$ sudo mkfs.ext4 /dev/bcache0/bcache0
mke2fs 1.47.0 (5-Feb-2023)
Discarding device blocks: done
Creating filesystem with 1465130644 4k blocks and 183144448 inodes
Filesystem UUID: 8c9c8369-f175-43ea-9ae2-3632d7e7d068
Superblock backups stored on blocks:
        32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
        4096000, 7962624, 11239424, 20480000, 23887872, 71663616, 78675968,
        102400000, 214990848, 512000000, 550731776, 644972544

Allocating group tables: done
Writing inode tables: done
Creating journal (262144 blocks): done
Writing superblocks and filesystem accounting information: done

/media/hdd以下に共有フォルダーを作成し、先ほどと同じく10GBのファイルを3回転送してみます。

図3 bcacheを経由した場合

いい感じの速度になりました。

パフォーマンスのチューニング

今一度bcacheの設定コマンドを見てみます。

$ sudo make-bcache -C /dev/nvme0n1p3 -B /dev/sda --discard --writeback

bcacheには4つのキャッシュモードがあり、ここでは"writeback"モードを指定しています。それぞれ見ていきましょう。

  • writeback:一度キャッシュに書き込み後、非同期にHDDと同期する。特徴上一番高速だが、HDDに書き出す前に電源が切れるとデータが失われる
  • writethrough:キャッシュとHDDに同時に書き込み、HDDに書き込み完了後キャッシュから消える。安全だが速度は出ない
  • writearound:書き込みにキャッシュを使用しない。読込時のみに使用する。SSDの書き込みを減らすためのモード
  • none:キャッシュを使用しない

正直なところ"writeback"モードを使用しないのであれば、bcacheを使用する意味がないといっていいでしょう。たくさん書き込める(TBWの値が大きい)SSDを使用し、UPS等を併用すれば、"writeback"モードの欠点を補うことができます。

またbcacheのドキュメントによると、

$ echo 0 |sudo tee /sys/block/bcache0/bcache/sequential_cutoff

を実行すれば、あらゆるファイルに関してキャッシュが効くようになります。

"sequential_cutoff"は読込時のみに影響し、デフォルトは4MBで、このサイズよりも大きなファイルはキャッシュせずにHDDから直接読み込みます。

ドキュメントには他のパラメーターも紹介されていますが、今回のような用途では制限に引っかかることはないと思われるため、紹介を省略します。

/sys/以下に書き込んだ場合、再起動すると設定が消えてしまうので、永続化したい場合は次のようなコマンドを実行します。

$ echo "w /sys/block/bcache0/bcache/sequential_cutoff - - - - 0" | sudo tee /etc/tmpfiles.d/bcache.conf

おすすめ記事

記事・ニュース一覧