Btrfs で RAID1 [Fedora 33]

(2020.11) 新規作成。

Fedora 33 Linux の Workstation editon で, Btrfs がデフォルトになった。Server Edition は引き続き XFS がデフォルト. また, Workstation editon でも, /boot は ext4 になっている。

Btrfs は ZFS と似た多機能のファイルシステムで, Linux LVM に載せずに運用する。

だが, まだ成熟していない。Linux kernel v5.9 段階で, RAID 5, RAID 6 は unstable. 他方, ZFSは, 書込みホール (write hole) 問題を解決する RAID-Z (単一パリティ; RAID-5相当), RAID-Z2 (二重パリティ; RAID-6相当) を備える。

[2020.11.22] 同じく Btrfs がデフォルトになっている OpenSUSE Leap 15.2 でもやってみたが、同様の失敗。特定のディストリビューションだけの問題ではない。何か手順が違うのだろうが、ギブアップ。

[2021.4] Fedora 34 が出たので、クリーンインストールして再度試した。再び失敗。やり方が違うのかなぁ? これと同じ問題; Degraded boot with systemd : btrfs.

A start job is running for /dev/disk/by-uuid/2148xxxxxxxxx

探すと他にも同様の挙動に直面している人は多いが、解決できない。アカンやん。

Btrfs の概念

Btrfs は、用語が紛らわしい.

  1. device - 物理デヴァイス. /dev/sdb2 などの path で指定.
  2. filesystem - ストレージプールの意味。複数の物理デヴァイスを束ねて作る。Linux LVM でのヴォリュームグループに相当。Label または uuid で識別する。
  3. subvolume - サブヴォリューム。これを mount する。

Step by Step: 物理デバイスの追加, RAID 1設定

2台目のディスクドライブを追加。

パーティションを切る. cfdiskgdisk GPT fdisk を使う。

# cfdisk /dev/sdb

ラベルタイプは dos, パーティション type は 83 Linux とすればよい。とりあえず /dev/sda のパーティションと大きさを合わせて、1G (起動可能) と 19G に分けた。

フォーマット - 不要だった

フォーマットする。コマンドは mkfs.btrfs. --いや違った。既存のストレージプールに加えるドライヴのフォーマットは不要。Btrfs におけるこのコマンドは, ストレージプールの作成。多くのWebサイトの解説は誤っている。

# mkfs.btrfs -L mylabel /dev/sdb2
btrfs-progs v5.7 
See http://btrfs.wiki.kernel.org for more information.

Label:              mylabel
UUID:               212777d7-839f-49cb-8cb1-a721c640de4b
Node size:          16384
Sector size:        4096
Filesystem size:    19.00GiB
Block group profiles:
  Data:             single            8.00MiB
  Metadata:         DUP             256.00MiB
  System:           DUP               8.00MiB
SSD detected:       no
Incompat features:  extref, skinny-metadata
Runtime features:   
Checksum:           crc32c
Number of devices:  1
Devices:
   ID        SIZE  PATH
    1    19.00GiB  /dev/sdb2

ストレージプールに追加

そして、既存のストレージプールにこの物理 device を追加. 未フォーマットでよい。2引数が必要。ここが紛らわしい。第2引数は, ストレージプール名ではなく, mount された path で指定する。

# btrfs device add /dev/sdb2 /

[2021.4] Fedora 34: UEFI 環境では, /dev/sda1 は VFAT で /boot/efi にマウントされる。Btrfs は /dev/sdb2 ではなく /dev/sdb3 になる。

追加されていることを確認する。btrfs filesystem show コマンドで、ストレージプールと関連デヴァイスの情報を表示できる。引数を省略すると、すべてのストレージプールの情報を表示。'ラベル' が真のストレージプール名。これを引数にしてもよい。

# btrfs filesystem show /
Label: 'fedora_localhost-live'  uuid: 3b75e79d-3bfa-49ce-a03d-d8f200539e80
        Total devices 2 FS bytes used 5.95GiB
        devid    1 size 19.00GiB used 9.02GiB path /dev/sda2
        devid    2 size 19.00GiB used 0.00B path /dev/sdb2

/dev/sdb2 が追加され、現在は片方のデヴァイスのみが使用されているのが分かる。

Btrfs はデフォルトでは, metadata はミラーされ、データはストライプされる。次のコマンドで作ったBtrfsファイルシステム (ストレージプール) と同じ; mkfs.btrfs -m raid1 -d raid0

どのような設定になっているかは btrfs filesystem df コマンドで確認できる。btrfs filesystem show では確かなことは分からないことに注意。

# btrfs filesystem df /
Data, single: total=8.01GiB, used=5.77GiB
System, DUP: total=8.00MiB, used=16.00KiB
Metadata, DUP: total=512.00MiB, used=183.12MiB
GlobalReserve, single: total=16.75MiB, used=0.00B

では, ストレージプールをRAID 1に変換してみよう。btrfs balance start コマンドを使う。

-dオプションがデータ領域の指定, -m オプションが metadata の指定。プロファイルとして次のいずれか一つを指定: raid0, raid1, raid10, raid5, raid6, dup, および single.

single はまったく複製しない。dup は一つの device 内で複製する。

# btrfs balance start -dconvert=raid1 -mconvert=raid1 /
Done, had to relocate 12 out of 12 chunks

再度、確認。

# btrfs filesystem df /
Data, RAID1: total=9.00GiB, used=5.77GiB
System, RAID1: total=32.00MiB, used=16.00KiB
Metadata, RAID1: total=512.00MiB, used=183.47MiB
GlobalReserve, single: total=17.06MiB, used=0.00B

OK. これは簡単。

ここで一旦電源を切り、2台目のドライヴを切り離して起動する。起動しない。アカンやん。

公式マニュアルを読むと, mount -o degraded /dev/sda1 /mnt のようにしなければならないような気もするが、missing device があるかどうかでオプションを変えるの?

どうやら, /etc/fstab ファイルでいつでも degraded マウントオプションを付けるのと, カーネルパラメータに rootflags=degraded を付ければいけるようだ (まだ試してない). See Btrfs - ArchWiki

[2021.4] Fedora 34: やっぱり失敗! カーネルは立ち上がるので, /etc/fstab に上記オプションを付けて, initramfs を再作成してみたが、まだ何か足らないようだ。うーむ・・・

2台目でブートできるようにする - GRUB

上記のとおり、1台目だけでも起動しないので、正しいかどうか確かではない。手順だけメモしておく。

起動ドライブをRAID 1にするときは、1台目が壊れても, 2台目のみで起動できるようにしておかないといけない。

ディレクトリ構成し, chroot

/dev/sdb1 をフォーマットして, /boot をコピーする。

# mkfs.ext4 /dev/sdb1
mke2fs 1.45.6 (20-Mar-2020)
Creating filesystem with 262144 4k blocks and 65536 inodes
Filesystem UUID: cab255f5-3f41-4809-808a-4efdf7cb949e
Superblock backups stored on blocks: 
        32768, 98304, 163840, 229376

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

ディレクトリ構成を作って, chroot する。

まず, 2台目をストレージプールから外して, /mnt/newdisk 辺りにマウントする。

# btrfs device remove /dev/sdb2 /
ERROR: error removing device '/dev/sdb2': unable to go below two devices on raid1

アカンやん。/dev/sda2 のほうを使う。subvolumeの指定を忘れずに。

# cd /mnt
# mkdir newdisk
# mount /dev/sda2 newdisk -o subvol=root
# cd newdisk

chroot する準備。いくつかをマウントする。

# mount /dev/sdb1 boot
# mount -t proc proc proc/
# mount -t sysfs sys sys/
# mount -o bind /dev dev/
# mount -t devpts pts dev/pts/

一度 findmnt でチェック.

では, chroot する. あらかじめ別にもう一つコンソールを開いておくこと。

# chroot /mnt/newdisk

GRUBの設定

現代では, /boot/grub2/grub.cfg ファイルを直接編集してはならない. 設定ファイルは /etc/grub.d 以下と /etc/default/grub ファイル。

次のようにするだけで、device の UUIDを検索し、grub.cfg ファイルを更新してくれる.

# grub2-mkconfig -o /boot/grub2/grub.cfg
Generating grub configuration file ...
done

よし、MBR に書き込む。

# grub2-install /dev/sdb
Installing for i386-pc platform.
Installation finished. No error reported.

1台目を外してテスト

アカン、起動できへん。上記のとおり, 2台目を外して1台目だけでも起動できない。原因は追いきれていない。