背景と概要
Linuxで高速大容量ストレージを安価に組みたい!
現状のストレージのコスト感
デバイスタイプ | 価格帯 |
---|---|
HDD 4TB | 0.8〜2万 |
SSD(SATA) 4TB | 6〜9万 |
SSD(NVMe) 2TB | 2〜4万 |
という時代に、Linuxで4〜8TB程度のRAID1ストレージのマシンをこさえるというシチュエーションです。
SSDが安くなってきたとは言え、容量単価はまだHDDの5倍くらいの感覚です。4TBでSSDでRAID1を組もうと思ったら10万円コースですし、その容量だとNVMeはまだ出てこないのでSATAのSSDになってしまいます。
そこで、容量と速度のいいトコ取りをお値打ち価格で、を目指してファイルシステム全体を HDDのRAID1 + SSDキャッシュ の構成で組むことにしました。SSDキャッシュ化はbcacheを使います。
RAIDはいらないけどファイルシステム全体をbcacheで高速にしたい、というケースでも似たような手順になるかと思います。
実際に使用するマテリアル、その他
HDD 6TB x 2 + NVMe SSD 1TB (合計3.5万円)
Ubuntu 18.04 LTS をインストールメディアで入れます。(Ubuntu 20.04, 22.04 でも以下手順で確認済み)
UEFIブートします。
インストール手順
全体の流れ
インストーラはbcacheに対応していませんので、通常のパーティションに仮インストールをしたのち、ファイルシステムを構成してから本環境にデータを移動する流れになります。
最終形イメージ
デバイス | マウントポイント |
---|---|
HDD | /boot/efi |
HDD | /boot |
bcache (backing=HDDのRAID1, cache=SSD) | / |
通常のデスクトップ用であればESPや/bootはSSDに置く方が起動が高速になって良いかもしれません。今回は立ち上げっぱなしのサーバ用途なので、起動の速さはどうでもよくってキャッシュ容量を最大化するためSSDを丸ごとキャッシュにしました。
パーティショニング
起動: live media
最初にUSBメモリ等のlive mediaを使って(インストールせずに)起動し、gdiskでパーティションを以下のように切っておきます。
(2019-09-18 修正: 障害時にHDD交換しやすいように、左右対象にしました。交換時には /etc/fstab を調整するなりして残すHDDだけで起動できるようにする手順になります)
sda, sdb: HDD (6TiB)
nvme0n1: NVMe SSD (1TiB)
として認識されています。
sda:
Number Start (sector) End (sector) Size Code Name
1 2048 499711 243.0 MiB EF00 EFI System Partition
2 499712 4196351 1.8 GiB 8300 Linux filesystem
3 4196352 11721045134 5.5 TiB 8300 Linux filesystem
sdb:
Number Start (sector) End (sector) Size Code Name
1 2048 499711 243.0 MiB EF00 EFI System Partition
2 499712 4196351 1.8 GiB 8300 Linux filesystem
3 4196352 11721045134 5.5 TiB 8300 Linux filesystem
nvme0n1:
Number Start (sector) End (sector) Size Code Name
1 2048 2000409230 953.9 GiB 8300 Linux filesystem
仮インストール
このうち、以下のパーティションを使用してUbuntuを仮インストールします。
デバイス | ファイルシステム | マウントポイント |
---|---|---|
/dev/sda1 | EFI | /boot/efi |
/dev/sda2 | ext4 | /boot |
/dev/nvme0n1p1 | ext4 | / |
sda3とsdb3はのちほどRAIDを組むパーティションで、ここでは使いません。
またsdb1とsdb2は、sdb単体でもブートできるように後ほどsda1とsda2と等価になるようにします。
/ がSSDなので速いですね。すぐに終わります。
パッケージ更新と追加
再起動: 仮インストールしたシステム
インストールしたシステムを起動し、パッケージの更新およびRAIDとbcacheに必要なパッケージの追加をします。
sudo apt-get udpate
sudo apt-get install mdadm
sudo apt-get install bcache-tools
RAID + bcache でファイルシステム作成
RAID1を組み、それを使用してbcacheデバイスを作成します。ここではまずバッキングデバイス(HDD RAID)だけを登録し、あとでSSDが空いたらキャッシュデバイスとして追加します。
sudo mdadm --create /dev/md0 --level=raid1 --raid-device=2 /dev/sda3 /dev/sdb3
(※再起動するとIDが変わって /dev/md127 になったりするので注意)
sudo modprobe bcache
sudo /usr/sbin/make-bcache -B /dev/md0
sudo mkfs.ext4 /dev/bcache0
仮インストールしたルートファイルシステムをbcacheに移動
2021.02.08: 以下、ルートファイルシステムの移動のためlive mediaから起動しなおしてコピー操作していましたが、そのままの状態で次のコマンドでコピーできるので記述修正しました。GNU tarはextended attributeをサポートしないなどファイルシステムのコピーには問題がある可能性がありそうなので、bsdtarを使います。--one-file-system は別ファイルシステムがマウントされている先をアーカイブの対象にしないオプションで、この場合 /boot /sys /proc /dev などをコピーしないためのものです。
sudo mount /dev/bcache0 /mnt
sudo apt-get install bsdtar # (ubuntu-20.04 以降は sudo apt-get install libarchive-tools)
sudo bsdtar cvpf - --one-file-system / | sudo bsdtar xvpf - -C /mnt
fstabを修正してgrub更新、再起動
bcache0のUUIDを調べます。
ls -l /dev/disk/by-uuid
合計 0
lrwxrwxrwx 1 root root 10 9月 12 16:31 12732d48-4b0d-464f-938a-66fceca525f7 -> ../../sdb1
lrwxrwxrwx 1 root root 10 9月 12 16:31 1EE3-33F7 -> ../../sda1
lrwxrwxrwx 1 root root 11 9月 12 16:31 935f09e9-1aaf-4243-b433-974d83427b7d -> ../../md127
lrwxrwxrwx 1 root root 10 9月 17 11:09 b131c455-8bdb-4486-bf50-2f12140c9b37 -> ../../sda2
lrwxrwxrwx 1 root root 10 9月 17 11:09 a5a262cb-5016-44b6-9b62-bd139ed7784d -> ../../sdb2
lrwxrwxrwx 1 root root 13 9月 12 16:31 ab55455c-c7ea-4e36-9101-ac82e4571e33 -> ../../bcache0
lrwxrwxrwx 1 root root 15 9月 12 16:31 f7952b71-49b7-41a4-9e5c-54b33ab166b3 -> ../../nvme0n1p1
/mnt/etc/fstabの / のエントリを、bcache0に変更します。
# / was on /dev/nvme0n1p1 during installation
# UUID=f7952b71-49b7-41a4-9e5c-54b33ab166b3 / ext4 errors=remount-ro 0 1
# / on /dev/bcache0
UUID=ab55455c-c7ea-4e36-9101-ac82e4571e33 / ext4 errors=remount-ro 0 1
本番ファイルシステム構成を再現した状態でgrubを更新
sudo mount -B /dev /mnt/dev
sudo mount -B /proc /mnt/proc
sudo mount -B /sys /mnt/sys
sudo mount /dev/sda2 /mnt/boot
sudo mount /dev/sda1 /mnt/boot/efi
sudo chroot /mnt
grub-install --recheck /dev/sda
update-grub
今動いているSSDのシステムも検出してしまいますが、後でもう一度更新します。
再起動: 本システム
再起動すると bcache0 が / になってブートします。
df
(必要なものだけ抜粋)
/dev/bcache0 5811055832 48770652 5469354184 1% /
/dev/sda2 1998672 120548 1756884 7% /boot
/dev/sda1 244988 6201 238787 3% /boot/efi
bcacheにキャッシュデバイスを追加
これでSSDを使わずにブートができたということになるので、仮インストールをしたSSDを潰してキャッシュにすることができます。
sudo wipefs -a /dev/nvme0n1p1
sudo make-bcache -C /dev/nvme0n1p1
UUID: f7952b71-49b7-41a4-9e5c-54b33ab166b3
Set UUID: 333480d8-9c84-4cda-8c4c-82029e85eed6
:
echo 333480d8-9c84-4cda-8c4c-82029e85eed6 | sudo tee /sys/block/bcache0/bcache/attach
bcacheの状態確認
ls /sys/block/bcache0/slaves
md127 nvme0n1p1
sudo bcache-super-show /dev/md127
sb.magic ok
sb.first_sector 8 [match]
sb.csum 4DC6313D63E40B61 [match]
sb.version 1 [backing device]
dev.label (empty)
dev.uuid 935f09e9-1aaf-4243-b433-974d83427b7d
dev.sectors_per_block 1
dev.sectors_per_bucket 1024
dev.data.first_sector 16
dev.data.cache_mode 0 [writethrough]
dev.data.cache_state 1 [clean]
cset.uuid 333480d8-9c84-4cda-8c4c-82029e85eed6
cset.uuidが先ほどセットしたUUIDになり、 cache_stateが [clean] になっています。(attachする前は [detached])
最後に両方のHDDにgrubをインストール
sdbの方は今やらなくてもよいのですが、一応両方のHDDにgrubをインストールしておきます。
sudo grub-install --recheck /dev/sda
sudo update-grub
# copy sda1, sda2 -> sdb1, sdb2
sudo mkfs.vfat -F32 /dev/sdb1
sudo mkfs.ext4 /dev/sdb2
sudo mount /dev/sdb2 /mnt
sudo mkdir /mnt/efi
sudo mount /dev/sdb1 /mnt/efi
sudo cp -a /boot/* /mnt
sudo umount /mnt/efi
sudo umount /mnt
sudo mount /dev/sdb2 /boot
sudo mount /dev/sdb1 /boot/efi
sudo grub-install --recheck /dev/sdb
sudo update-grub
sudo umount /boot/efi
sudo umount /boot
これで完成です。
6TB RAID1でSSDキャッシュの効いたルートファイルシステムが完成しました。
補足
一旦作ってしまったbcacheデバイスを止めたいときは以下のようにします。
echo 1 | sudo tee /sys/block/bcache0/bcache/stop
sudo wipefs -a /dev/md127