LoginSignup
2
3

More than 3 years have passed since last update.

Raspberry PiのルートにRAIDボリュームをマウントしてみた

Last updated at Posted at 2021-01-05

はじめに

Raspberry Piを24時間稼働のサーバーとして運用するにあたって、頻繁に読み書きがある領域をSDカードに任せるのは耐久性に難ありです。
そこで、以下の作業によってシステムの耐久性を向上させよう思います。

  • ソフトウェアRAID(mdadm)によりUSBドライブ2枚でRAID1を組む
  • そのRAIDボリュームを起動時にルートディレクトリ/にマウントする

概要

  1. まっさらなRaspberry Piに対する初期設定
  2. USBドライブのフォーマット
  3. RAID構築
  4. SDカードの/をRAIDボリュームにコピー
  5. 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):
  1. "p"で現在の状態を表示
  2. パーテーションがあれば"d"で削除
  3. "n"でパーテーションを作成、(Partition Type, Partition Number, First Sector, Last Sectorは全てデフォルト値)
  4. "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ドライブを定期交換

これでうまくいくのかは、運用しつつ見ていきます。

先行研究

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3