はじめに
Raspberry Piを24時間稼働のサーバーとして運用するにあたって、頻繁に読み書きがある領域をSDカードに任せるのは耐久性に難ありです。
そこで、以下の作業によってシステムの耐久性を向上させよう思います。
- ソフトウェアRAID(mdadm)によりUSBドライブ2枚でRAID1を組む
- そのRAIDボリュームを起動時にルートディレクトリ
/
にマウントする
概要
- まっさらなRaspberry Piに対する初期設定
- USBドライブのフォーマット
- RAID構築
- SDカードの
/
をRAIDボリュームにコピー - RAIDボリュームから起動するための設定
USBドライブはHDD/SDD等々、中のデータがどうなってもよいものをご用意ください。
筆者の環境
SDカードにOSイメージを焼き、bootパーテーションに空のssh
ファイルを書き込んだだけのまっさらなラズパイにssh接続して設定します。
- Raspberry Pi 4B (4GBモデル), Raspberry Pi OS Buster (kernel release: 5.4.79-v7l+)
- microSDカード (32GB)
- 2.5インチHDD x 2 (どちらも1TB)
Raspberry PiのバスパワーはHDD2台に電源供給するには不十分なので、別途電源付きUSBハブを使っています。
構築するRAIDレベルは1(ミラーリング)です。
0. 初期設定
初期起動後の各種設定です。済んでいる方は読み飛ばしてください。
rootパスワードの設定
sudo passwd root
raspi-config
による設定
sudo raspi-config
- "1 System Options" > "S3 Password" > ユーザー"pi"のパスワード設定
- "3 Interface Options" > "P2 SSH" > "Enable"
- "5 Localization Options" > "L2 Timezone" > "Asia/Tokyo"
- "8 Update"
パッケージ更新などなど
パッケージの更新、OSの更新。
sudo apt-get update && sudo apt-get upgrade
sudo apt-get dist-upgrade
1. USBドライブのフォーマット
ディスク確認
接続したUSBドライブのデバイス名を確認します。
$ sudo fdisk -l
Disk /dev/mmcblk0: 29.8GiB, ...
Device ...
/dev/mmcblk0p1 ...
/dev/mmcblk0p2 ...
Disk /dev/sda: 931.5GiB, ...
Disk model: ...
Device ...
/dev/sda1 ...
Disk /dev/sdb: 931.5GiB, ...
Disk model: ...
Device ...
/dev/sdb1 ...
実際はRAMについても出力されるため、もっと多く情報が出力さます。上から順に、こんな情報が書かれています。
- SDカード:
/dev/mmcblk0
- パーテーション1:
/dev/mmcblk0p1
- パーテーション2:
/dev/mmcblk0p2
- USBドライブ1:
/dev/sda
- パーテーション1:
/dev/sda1
- USBドライブ2:
/dev/sdb
- パーテーション1:
/dev/sdb1
パーテーションの削除と作成
fdisk
を使って、すべてのUSBドライブを単一のLinux用パーテーションからなるデバイスにします。
今回は、各USBドライブにもともと存在するパーテーション/dev/sda1
、/dev/sdb1
を削除して新たにパーテーションを作成します。
$ sudo fdisk /dev/sda
Command (m for help):
- "p"で現在の状態を表示
- パーテーションがあれば"d"で削除
- "n"でパーテーションを作成、(Partition Type, Partition Number, First Sector, Last Sectorは全てデフォルト値)
- "w"でコマンドの反映 (入力ミスしたら"q"で反映せずに終了)
もう一つのUSBドライブについても同様に設定。
2. RAID構築
2つのUSBドライブから1つのRAID1ボリュームを作成します。
RAIDソフトウェアのインストール
mdadm
を使用します。
sudo apt-get install mdadm
RAIDボリュームの構築
今回はRAID1(ミラーリング)ボリュームを/dev/md0
として、さきほど作成したパーテーション/dev/sda1
と/dev/sdb1
を対象に構築します。
sudo mdadm --create --verbose /dev/md0 --level=1 --raid-devices=2 /dev/sda1 /dev/sdb1
確認メッセージに対して"y"を入力すると構築が始まります。
構築後、以下のコマンドで同期の進捗が確認できます。
$ sudo mdadm --detail /dev/md0
/dev/md0:
...
Resync Status: 1% complete
RAIDボリュームの登録
このままでも構築したRAIDは有効ですが、デバイスファイル名/dev/md1
に永続性がありません。
あとで設定するfstabではマウント対象をデバイスファイル名によって指定するため固定したいです。
そこで、mdadm
の設定ファイルにをRAIDボリュームと名称の対応を登録します。
mdadm --detail --scan
コマンドにより現在有効なRAIDが全てリストアップされるので、それを設定ファイル/etc/mdadm/mdadm.conf
に追記します。
これは、以下のコマンドをrootユーザーとして実行することと等価です。
mdadm --detail --scan >> /etc/mdadm/mdadm.conf
RAIDボリュームのフォーマット
構築したRAIDボリュームをLinux用のファイルシステム"ext4"でフォーマットします。
sudo mkfs.ext4 /dev/md0
3. SDカードの/
をRAIDボリュームにコピー
SDカードにRaspberry Pi OSを焼いた場合は、/dev/mmcblk0p2
が/
にあたるデバイスです。
RAIDボリュームに/
をコピー
dd
コマンドにより、RAIDボリュームを/
の複製に変換します。
sudo dd if=/dev/mmcblk0p2 of=/dev/md0 bs=32M conv=noerror,sync status=progress
ifとofに指定するデバイスを逆にしてしまうとSDカードへのOSイメージ作成からからやり直しになります。注意して実行してください。
"i"fはin、"o"fはoutです。
ファイルシステムのチェック
sudo e2fsck -f -y /dev/md0
パーテーションの拡張
このままではコピー元のSDカードと同じサイズのパーテーションなので、USBドライブ本来のサイズまで拡張します。
sudo resize2fs -p /dev/md0
4. RAIDボリュームから起動するための設定
RAIDをつかさどるmdadmが/boot
の外にいるため、このままfstabでRAIDボリュームを/
にマウントしてもうまくいきません。
そこで、起動時にRAIDが使用できるinitiramfs
(initial ram file system)のイメージを作成します。
initramfsイメージの作成
sudo vi /etc/initramfs-tools/modules
このファイルの最後に以下の3行を追加します。
raid1
md_mod
ext4
そして、イメージ作成します。実行結果として、生成されたイメージファイル名が返ってきます。
$ sudo update-initramfs -c -k `uname -r`
update-initramfs: Generating /boot/initrd.img-5.4.79-v7l+
ブートイメージの設定
sudo vi /boot/config.txt
このファイルの最後にさきほど生成したイメージファイルを読み込むよう設定します。
initramfs initrd.img-5.4.79-v7l+ followkernel
cmdline.txtの設定
起動時にRAIDボリュームを/
とするよう設定します。
sudo vi /boot/cmdline.txt
- console=serial0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait
+ console=serial0,115200 console=tty1 root=/dev/md0 rootfstype=ext4 elevator=deadline fsck.repair=yes rootdelay=10 rootwait
変更は2点だけです。
-
root=
以降にRAIDボリュームを指定する -
rootdelay=10
によりRAIDボリュームがマウントされるまで待つようにする
fstabの更新
起動時にRAIDボリュームが/
にマウントされるように設定します。
ここで編集すべきは、SDカード内の/etc/fstab
ではなく、RAIDボリュームの中にあるものです。
読み書きできるようにするために、一時的にRAIDボリューム/dev/md0
をどこかへマウントします。今回は/mnt/md0
ディレクトリを作成してそこへマウントしました。
sudo mkdir /mnt/md0
sudo mount /dev/md0 /mnt/md0
そして、RAIDボリューム内のfstabを書き換えます。ついでに、SDカードを変更できるように/boot
に対するデバイスをPARTUUIDによる紐づけからデバイスファイル名称に変えます。
sudo vi /mnt/md0/etc/fstab
- PARTUUID=... /boot vfat defaults 0 2
- PARTUUID=... / ext4 defaults,noatime 0 1
+ /dev/mmcblk0p1 /boot vfat defaults 0 2
+ /dev/md0 / ext4 defaults,noatime 0 1
The moment of truth
設定に間違いがなければ、再起動してください。
RAIDボリュームが/
としてマウントされた状態で起動します。
sudo reboot
最後にdf
コマンドで、期待通りか確認できます。
$ df -h
Filesystem Size Used Avail Use% Mounted on
/dev/mmcblk0p1 253M 58M 195M 24% /boot
/dev/md0 917G 1.9G 878G 1% /
さいごに
/boot
の中身はSDカード内にあるためSDカードなしにこのRaspberry Piは起動しません。
視点を変えると、このSDカードの役割は、起動ディスクのみ言えます。
さらに、このSDカードのbootパーテーションを別のFAT32でフォーマットされたSDカードにコピーすれば、それが起動ディスクになります。
そこで、以下のようにメンテナンスすることでシステムの耐久性が向上すると思います。
- bootパーテーションの中身をバックアップ、定期的に他のSDカードに交換
- それ以外のデータはRAIDでUSBドライブを定期交換
これでうまくいくのかは、運用しつつ見ていきます。