(前置き)
以下、「USBメモリー」は「USB-HDD」に置き換えても同じです。
USB-HDD の場合でも同様にお試し下さい。
一つ前の記事 では、ラズパイ2B を使って microSD から起動したのちに USBメモリー をデータ領域として使う風なイメージで RAID-1 を構築しましたが、なにもそんな古いの使わないで、実はラズパイ 3B+ を持ってたんでした!

2018/06/30 Raspberry PI 3 B+ の PoE HAT を自作する(前編)
2018/07/10 Raspberry PI 3 B+ の PoE HAT を自作する(後編)
ラズパイ2B を使った例(microSDからブート)だと、いずれ microSD が壊れたら起動しなくなってしまいますが、こいつは microSD じゃなくて USBメモリー から起動できますので、もし冗長化できれば、片方が壊れてたとしてももう片方で時間稼ぎ、という技が使えるではありませんか!
■この記事で出来ること・出来ないこと
- microSD は全く使わない
- /boot を USBメモリー の中に置く(ただし RAID-1 の中には置けない)
- /boot の変更は頻繁じゃないため、rsync で同期を取る運用でも実害ないはず
- /(root)は RAID-1 の中に配置(データは安全に保全)
- 1枚目が壊れたとき、自動で2枚目をブートするようにはできない(差し替え必要なので完全無人運用は無理)
ラズパイ歴が浅いので、詳しい方からの「そこはあかんだろ」って指摘は大歓迎です。(コメント欄にお願いします!)
Etcher などを使ってイメージを USBメモリー に焼きますが、出来た USBメモリー をそのままラズパイに挿してセットアップし始めると SSH が無効状態のため、ラズパイにキーボードやモニターなどを付けないといけなくなります。
それでいい人はいいのですが、そんなの面倒だって人は(かつネットワーク内に悪意あるユーザーがいない場合は)最初から SSH を有効してしまったほうがラクチンです。
USBメモリー のブート領域は普通のパソコンでも読み書きできる FAT32 なので、パソコンに繋いでルートの直下に SSH というファイルをメモ帳か何かで作ってやって下さい。
中身が空でいいですが、メモ帳でやるとデフォで .txt の拡張子が付きますため、.txt を削除するのを忘れぬよう・・・
※Etcher で焼いたあと、いったん外して刺し直ししないとパソコン側が認識しない場合があります。中が見れなかったら抜き差ししてみましょう。
これをラズパイに挿して起動させますが、挿す場所は LANコネクタに近い側の上段にして下さい。
ここが最初のデバイス番号(sda)になって、その下段が次(sdb)という風に認識するようです。
pi や root のパスワード設定や、ネットワークの設定(固定IP化)や、SSH の接続を制限したりとかの辺は今回は割愛しますので各自でお願いします。
あと sudo ・・・ って書くのが面倒なので、su した状態で作業する前提で書いてますので、su したくない人は全ての行の先頭に sudo を付けてコマンド叩いて下さい。
ちなみに su したいときは、先に
sudo passwd root
として、root のパスワードを決定する必要があります。
最後に答えを書きますが、本来は apt-get update / upgrade してから作業に取りかかるべきところなのですが、mdadm をインストする時に要求されない限り、あえてやらずに作業してみて下さい。
ひとつだけテストが待ち構えていますので。
作業を開始するに当たりタイムスタンプは JST で残したいでしょうから、真っ先にタイムゾーンを Tokyo にしておきます。
dpkg-reconfigure tzdata
まずは現在のデバイスの状態を確認します。
fdisk -l
赤で囲ったところが Etcher で焼かれた(起動に使われた)デバイスとなります。
Start/End の部分が重要になりますが、環境によって異なるので、たぶん皆さんのは違うと思います。
その下の青い枠のところが Etcher で焼いてない、RAID-1 のもう片方となる予定の USBメモリー です。
もしかしたら最初から領域が確保されているかもしれませんが、次の作業で消えるので、消えては困るデータがあったら退避させておいて下さい。
parted /dev/sdb
として以下を順に指定します。
mktable msdos Y mkpart primary fat32 8192S 96663S mkpart primary ext4 98304S 100% print quit
mkpart の行は RAID-1 の元になる(sda1/sda2)の値と同じにして下さい。
私の場合、/dev/sda1 が START:8192・End:96663、/dev/sda2 が START:98304、にそれぞれなってるのでそのようにしてます。
「100%」は最後まで使うって意味で、私の場合だったら 30744576S って書いても一緒です。
成功したぽいか確認します。
fdisk -l
Type が Linux raid になってないけど良いのか?って疑問が沸きましたが結果論では気にしなくて大丈夫でした。
まずは順番に /boot のほうから・・・と言いたいところですが、先に RAID-1 のほうをやっつけておきます。
最終的に /dev/sda2 と /dev/sdb2 とで RAID-1 するので「2」を残して /dev/md2 としてますが、この辺は各自の好みなので好きに変更してやって下さい。
(変更したときはそれ以降も読み替えが必要)
apt-get install mdadm mdadm --create /dev/md2 --verbose --level=1 --raid-devices=2 /dev/sdb2 missing mdadm --detail --scan >> /etc/mdadm/mdadm.conf
ソフトRAID の定番たる mdadm をインストし、エラー状態の RAID-1 ボリュームを作って、mdadm.conf を更新して、という風です。
フォーマットもしときます。
mkfs.vfat -v -F 32 /dev/sdb1 mkfs.ext4 /dev/md2
次に initramfs の準備を始めます。
nano /etc/initramfs-tools/modules
末尾に
raid1 md_mod
を追加して保存して下さい。
initramfs を作ります。
kernel7 に倣って initrd7 という名前にすることにします。
mkinitramfs -o /boot/initrd7
これを読み込むよう config.txt を設定します。
nano /boot/config.txt
して末尾に以下を追加
kernel=kernel7.img initramfs initrd7 followkernel
この辺で各ボリュームの UUID を確認しときます。
blkid
本当は 固有ID とかは伏せたいマンなんですが、伏せると理解しにくくなるのであえて生値を。
赤枠で括ったところを次に使うので、メモ帳か何かに貼り付けて両端の "(ダブルクォーテーション)だけ消しておいて下さい。
nano /boot/cmdline.txt
root=の右側にあった元々の値を消して、さっきメモ帳に取った UUID= 以下を貼り付けて保存します。
いよいよ最後、fstab を弄ります。
nano /etc/fstab
まずデフォルトの PARTUUID= ・・・で始まる行(たぶん2行あると思う)に # を付けてコメント化し、最後に以下を追加します
/dev/sda1 /boot vfat defaults 0 2 /dev/sdb1 /mnt/sdb1 vfat nofail 0 0 UUID=e58c6a48-3442-47f3-9be0-f2ac196f727a / ext4 defaults,noatime 0 1
UUID= のところは、上は私の環境値であって、皆さんのは絶対に違います。
さっきメモ帳に避けておいたあれを使って下さい。
これで RAID-1 の前準備は完了しました。
データ類を移動させて、いよいよ佳境に入ります。
/dev/sdb1 → /mnt/sdb1、/dev/md2→/mnt/md2 にそれぞれマウントして作業します。
mkdir /mnt/sdb1 mount /dev/sdb1 /mnt/sdb1 rsync -avxHAXS --delete --progress /boot/ /mnt/sdb1/
mkdir /mnt/md2 mount /dev/md2 /mnt/md2 rsync -avxHAXS --delete --progress / /mnt/md2
さあ、すべて終わりましたか?
実稼働環境を使ってここまで辿り着いた人はいないと思うので、全ての工程においてバックアップを取るとか省いてますし、遠回りしたほうがいい手順も最短ルートで書きましたため、何か手違いがあってブートしなかったら Etcher まで戻ります。
本当にいいですか。やっちゃいますよ??
reboot
ラズパイにモニターを繋げていない人は戦々恐々かと思いますが(笑)
無事にコンソールに入れたら成功したようなもんです。(失敗したら漏れなくコンソールに入れない)
df
ラズパイ歴の浅い私としては /dev がこれでいいのか?って疑問が少々残るのですが、きっとラベルを付けずにフォーマットしたせいだろう、と思うことにしているので気にしない気にしない。
肝心なのはそこじゃなくて、/(ルート)が /dev/md2 になってることを確認して下さい。
そして次に、2枚目の USBメモリー なのですが、/mnt/sdb1 にマウントされていることも確認して下さい。
そう頻繁に /boot が変わることはないと思いますが、時々気が向いたら
rsync -avxHAXS --delete --progress /boot/ /mnt/sdb1/
して同期を取っておきましょう。
cron とかで回すべきかどうかは詳しい方に判断を仰ぎたいところですが、/mnt/sdb1 のところは1枚目が壊れるまでは使われないので、過剰に気にしすぎる必要はないと思います。
この時点で最初のルート /dev/sda2 は全く仕事をしていません。
欠落状態にしてあった RAID-1 に追加します。
mdadm --add /dev/md2 /dev/sda2
何の確認もなく、いきなり RAID-1 に組み込まれ再同期が開始します。
数分おきに
mdadm --misc --detail /dev/md2
で進行状態をチェックし、無事に Status:clean になったら大成功です。
USB を抜いて起動テスト・・・とかに入る前に。
apt-get update / upgrade をしないで・・・って最初に書きましたが、いまそのテストを行います。
これから実運用に入ると apt-get update / upgrade を日常的にやっていきますが、ここで RAID 情報が崩れたりして起動できないという事態が起きないか、まだ環境がまっさらなうちに試しておきます。
apt-get update apt-get upgrade
機種にも依るとは思いますが、特に USB2.0 だったりすると死ぬほど遅いですが、そこは耐えて下さい。
すべて更新ができたら
reboot
うまく起動できましたか?
今後もずっと成功し続ける保証はないですが、カーネルのマイナーチェンジくらいは大丈夫だろう・・・という淡い期待を抱かせる展開になったかと思います。
もし失敗された方がおられたら、それはそれで貴重(いずれ起きる災害を前もって体験した)なので、情報共有させてもらえたらと思います。
samba 入れてファイル共有とか、あとは好きにやって下さいませ〜
もし /boot に変更が加わるようなことやったら、
rsync -avxHAXS --delete --progress /boot /mnt/sdb1
も忘れずに!
(補足)
障害時の挙動ですが、USBメモリー の2枚目(/dev/sdb)が壊れたときは、degraded な状態で通常どおり起動します。
1枚目(/dev/sda)が壊れたとき(/boot つまり /dev/sda1が読めないとき)は、自動で2枚目に滑ってくれることなく起動不能に陥ります。
自動フェールオーバーしてくれると最高なんですが、そこは ラズパイの grub に相当する部分が対応してくれないと無理でしょう。
fstab の /boot マウントは UUID じゃなくて敢えて /dev/sda1 とした理由はそこにあるのですが、壊れた1枚目を抜いて、その場所に2枚目を差し替えてやると、その2枚目が /dev/sda1 と認識され、そこを /boot と見なして起動します。
よって、fstab の /boot を UUID 指定にすることは決してやらないで下さい。