Raspberry PI に USBメモリー×2 で RAID-1(3B+編)

(前置き)
 以下、「USBメモリー」は「USB-HDD」に置き換えても同じです。
 USB-HDD の場合でも同様にお試し下さい。



 一つ前の記事 では、ラズパイ2B を使って microSD から起動したのちに USBメモリー をデータ領域として使う風なイメージで RAID-1 を構築しましたが、なにもそんな古いの使わないで、実はラズパイ 3B+ を持ってたんでした!
http://dl.ftrans.etr.jp/?8877b2da5bc14ad1a6a7f6d0df2e22ce783d74a2.jpg

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 で焼いたあと、いったん外して刺し直ししないとパソコン側が認識しない場合があります。中が見れなかったら抜き差ししてみましょう。


http://dl.ftrans.etr.jp/?4909e57e69ad456a99cec476b086ed63f1a27cd2.png


 これをラズパイに挿して起動させますが、挿す場所は 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

http://dl.ftrans.etr.jp/?58fa6258523842ee9a862af494207952e6d2af13.png


 赤で囲ったところが 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

http://dl.ftrans.etr.jp/?150b480b2d9242329a79c7f23c5aec4c94c7c7f9.png


 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

を追加して保存して下さい。


http://dl.ftrans.etr.jp/?c6107bebba8544c490c813fb37bb4db55b419c4d.png


 initramfs を作ります。
 kernel7 に倣って initrd7 という名前にすることにします。

mkinitramfs -o /boot/initrd7

 これを読み込むよう config.txt を設定します。

nano /boot/config.txt

 して末尾に以下を追加

    kernel=kernel7.img
    initramfs initrd7 followkernel

http://dl.ftrans.etr.jp/?c3bce16a4942480188ef0b1128982a7165950733.png


 この辺で各ボリュームの UUID を確認しときます。

blkid

http://dl.ftrans.etr.jp/?e385a6c34c224492852e6eba8f580a1e9372ab8d.png


 本当は 固有ID とかは伏せたいマンなんですが、伏せると理解しにくくなるのであえて生値を。
 赤枠で括ったところを次に使うので、メモ帳か何かに貼り付けて両端の "(ダブルクォーテーション)だけ消しておいて下さい。

nano /boot/cmdline.txt

http://dl.ftrans.etr.jp/?1dac83d2a1ca438b9074834e7e4bda6bdef9ce75.png


 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= のところは、上は私の環境値であって、皆さんのは絶対に違います。
 さっきメモ帳に避けておいたあれを使って下さい。


http://dl.ftrans.etr.jp/?1893310006074ce89e5119463fe7e707d6708561.png


 これで 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


http://dl.ftrans.etr.jp/?ff825576f7b7458598413dab1c522a900b423a66.png


 ラズパイ歴の浅い私としては /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 になったら大成功です。


http://dl.ftrans.etr.jp/?e32bba20f9944ffa84a20f535bee1e286d14d764.png


 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

も忘れずに!


http://dl.ftrans.etr.jp/?8877b2da5bc14ad1a6a7f6d0df2e22ce783d74a2.jpg


(補足)
 障害時の挙動ですが、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 指定にすることは決してやらないで下さい。

Raspberry PI に USBメモリー×2 で RAID-1(前半)

 ゆる〜いファイルサーバーが必要になって、ちょうどヤマハ NVR500 のある場所だったもんで、そいつに備わってる ファイル共有機能 (NVR500限定機能) で茶を濁そうと思ったのですが

  • Windows 7 からだとファイル/フォルダの削除・リネームができない
  • Windows XP だと削除・リネームは一見できるように見えたが、漢字のフォルダは削除できない(半角にリネームしてからだと削除できた) (追記)普通に成功する XP マシンもあった
  • Windows 10 だと、AllowInsecureGuestAuth=1(後述)しても 0x80004005 でアクセスできない

みたいな、致命的な問題が発覚。
 ユーザーによるアクセス制限(簡易ACL)や同期(簡易ミラーリング)も搭載してて、「ゆる〜いファイルサーバー」には適任だったと思ったのですが・・・
 後継の NVR510 には同機能が搭載されていないことから、きっと「やる気なし」なのだろうと思い、さっさと見切りをつけて、定番の ラズパイ+Samba で立てることにしました。


 ノースピンドルということで耐久性を期待したいところなのですが、microSD ってそこまで寿命が長くないような気もしないでもなく・・・
 とりあえずデータさえ保全できればいいから、 microSD なんて消耗品として毎年交換すりゃあ、って割り切ってみます。


※ググった情報の集大成みたいなもんで、もっぱら自分用の備忘録
※対象ラズパイは3未満(USBブートできない前提)


■構成


 まずは普通どおりラズパイを作りますが、前半は Raspberry PI + Raspbian + Unbound 自分メモ と全く一緒です。
 が、一昨年くらいのイメージから SSH がデフォルトで無効になってしまったみたいで、キーボードやモニターを一度も繋げずにセットアップ完了させるということは不可能になってしまいました。


 パッケージ類を新しくします。

$ sudo rpi-update
$ sudo apt-get update
$ sudo apt-get upgrade
$ sudo reboot

 SSH を有効にします。

$ sudo touch /boot/ssh
$ sudo nano /etc/ssh/sshd_config

 以下のように追加することで、192.168.1.* の中のマシンからのみ ssh 接続を受け付けるようになります。

PasswordAuthentication no

Match Address 192.168.1.*
    PasswordAuthentication  yes

 いちおサーバーなので IP アドレスを固定します。

$ sudo nano /etc/dhcpcd.conf

 末尾に以下を追加

interface eth0
static ip_address=192.168.1.2/24
static routers=192.168.1.1
static domain_name_servers=192.168.1.1

 いったん再起動

$ sudo reboot

 いよいよ本題へ。
 USBフラッシュメモリーを USBポート に挿して以下

$ sudo fdisk /dev/sda
 d
 n
 t fd
 w
$ sudo fdisk /dev/sdb
 d
 n
 t fd
 w

 途中の d やら n やらは、たぶんやると分かるはず。
(ないところはデフォルトで進める)


 パーティション確保が済んだらボリュームを作りますが、このボリュームを RAID-1(mdadm を使ったソフトRAID)にします。

$ sudo apt-get install mdadm
$ sudo mdadm --create /dev/md1 --verbose --level=1 --raid-devices=2 /dev/sda1 /dev/sdb1
$ sudo mdadm --detail --scan >> mdadm.conf
$ sudo mkfs.ext4 /dev/md1
$ sudo mkdir /mnt/usb
$ sudo mount /dev/md1 /mnt/usb

 /mnt/usb が RAID-1 のボリュームです。


 このままだと起動の度に手動でマウント操作しないといけないので、自動マウントさせます。

$ sudo nano /etc/fstab
/dev/md1 /mnt/usb ext4 defaults 0 0

の1行を最後に追加したってください。


 これで単体として完成でして、こいつをファイル共有します。
(/mnt/usb の配下の shared を共有ポイントにする場合)

$ sudo mkdir /mnt/usb/shared
$ sudo chmod 777 /mnt/usb/shared

$ sudo apt-get install samba
$ sudo nano /etc/samba/smb.conf

 samba を入れて設定ファイル(smb.conf)の末尾に以下を追加

[shared]
path = /mnt/usb/shared
public = yes
writable = yes
guest ok = yes

 この例はガラガラのアクセスし放題な設定です。
 きちんとユーザー作ったりユーザーごとに権限付けたりする場合はググってやってください。


 最後に ext4 でジャーナル有効になっているので、少しでも microSD の寿命が延びることを祈願して、ジャーナル無効にしときます。

$ sudo tune2fs -O ^has_journal /dev/mmcblk0p2

http://dl.ftrans.etr.jp/?65908b2b4cb646639540714e4eacbfd35ee09bea.jpg
 以上です。


 さてこれを設置するのですが、万一にもフリーズしたときに備えて、遠隔で再起動かけられるようにしたいですね。
 ちょうどヤマハルーターの近傍に設置しますので、ヤマハルーターで電化製品を ON/OFF する の技が使えます。


 ちょっと繰り返しにはなりますが、後編では接続のハード周りを記事にしようと思います。


(追記)
 匿名ファイルサーバーにしたとき、Windows 10 のバージョンによっては接続できません。 (参考資料)


 レジストリを弄って匿名接続を許可にする必要があります。


HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\LanmanWorkstation\Parameters
AllowInsecureGuestAuth:(DWORD)1


(追記)2018/09/03
 ハード周りの続編を書く前に、USBブートが可能なラズパイ3B+向けに、USBメモリー(USB-HDD)を使って microSD なしに RAID-1 構築する方法を書きました。
 /boot も RAID-1 ではないものの冗長化させてます。
 詳しくは こちら をどうぞ。