Raspberry PiでUSBメモリを使ってRAID1を構築する

# はじめに
作業メモです。

## 用意
- Raspberry Pi 3 Model B
- microSDカード 8GB
- USBメモリ 2本

## 目標・ゴール
- USBメモリ 32GB 2本をRAID1:ミラーリングで構築する。
- 書き込みが多いと思われる/tmp, /var, /homeをUSBメモリのボリュームに移動する

# セットアップとインストール

## 作業の前にUSBメモリをチェック

### `dd`で書き込みテスト

基本的にエラーは出ないはずですが、念の為に書き込みテストします。最後まで`dd`コマンドが完走すれば問題ありません。もしエラーが発生する場合、USBメモリの状態がよろしくない(物理ディスク容量と論理ディスク容量が一致しない)ので、SDメモリカードフォーマッターで上書きフォーマットします。

```shell
$ sudo dd if=/dev/zero of=/dev/sdc bs=128M status=progress
```

`bs`オプションをつけたほうがよいですよ！と@hidaoさんにアドバイスもらいコマンド実行しました。`status=progress`で`dd`の進捗表示できます。

USBメモリの状態がよろしくない状態で作業を進めていくと、RAIDの構築中にエラーメッセージが出て止まります。このときのエラーメッセージはざっくりとしたもので原因特定できるものでは無かったです。(もしかして、`/var/log/`あたりにログファイルができているのかもしれない。)

### SDメモリカードフォーマッターで上書きフォーマット

`dd`コマンドが完走できなかったなどの問題があった場合、[SDメモリカードフォーマッター](https://www.sdcard.org/jp/downloads/formatter_4/)を使って上書きフォーマット初期化します。ちょっと時間がかかるのでRaspberry Piのパッケージアップデートと平行作業で進めるといいかもしれません。

## OS:raspbianの準備
### microSDカードにraspbianを書き込む
公式サイトからイメージをダウンロードして、2018-03-13-raspbian-stretch-lite.imgをmicroSDカード書き込む。

### microSDカードのbootドライブに"ssh"ファイルを置く
ssh接続ができるようになります。

### パッケージのアップデート
```shell
$ sudo apt update
$ sudo apt upgrade
$ sudo reboot
```

### IPアドレスの固定

LAN内のみの利用のためIPv4のみ設定してIPv6は設定しない。

```diff:/etc/dhcpcd.conf
# Example static IP configuration:
- #interface eth0
- #static ip_address=192.168.0.10/24
+ interface eth0
+ static ip_address=192.168.110.32/24
#static ip6_address=fd51:42f8:caae:d92e::ff/64
- #static routers=192.168.0.1
- #static domain_name_servers=192.168.0.1 8.8.8.8 fd51:42f8:caae:d92e::1
+ #static routers=192.168.110.1
+ #static domain_name_servers=192.168.110.1 8.8.8.8
```

## Raspberry PiにUSBメモリを挿してから

### ディスクの状態確認

```shell
$ sudo fdisk -l
```

作業前

```shell
Disk /dev/sda: 29.4 GiB, 31541166080 bytes, 61603840 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0xc3072e18

Device     Boot Start      End  Sectors  Size Id Type
/dev/sda1         480 61603839 61603360 29.4G  c W95 FAT32 (LBA)


Disk /dev/sdb: 29.4 GiB, 31576817664 bytes, 61673472 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0xc3072e18

Device     Boot Start      End  Sectors  Size Id Type
/dev/sdb1         224 61673471 61673248 29.4G  c W95 FAT32 (LBA)
```

同じメーカーのUSBメモリの別ロットを買いましたが、大体おなじ容量ですが、細かい数字でみると微妙に容量が違うようです。容量が違うディスクをRAID1:ミラーリングすることができないので、容量を揃えて置く必要があるかな？と思ったけど、そのままでも大丈夫なようです。

## USBメモリの初期化(fdisk)

USBメモリのデバイスをそれぞれ初期化します。今回の対象は`/dev/sda`と`/dev/sdb`。USBメモリのサイズは2TB未満なので、fdiskで初期化しました。2TB以上(HDD？)を対象とするときは、こちらの[Raspberry PiにUSBメモリ4本でRAID10を組む](https://qiita.com/wakisuke/items/16fee0e5604b3dafa355)を参照するといい感じに。

```shell
$ sudo fdisk /dev/sda

Welcome to fdisk (util-linux 2.29.2).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

Command (m for help): d
Selected partition 1
Partition 1 has been deleted.

Command (m for help): n
Partition type
   p   primary (0 primary, 0 extended, 4 free)
   e   extended (container for logical partitions)
Select (default p): 

Using default response p.
Partition number (1-4, default 1): 
First sector (2048-61603839, default 2048): 
Last sector, +sectors or +size{K,M,G,T,P} (2048-61603839, default 61603839): 

Created a new partition 1 of type 'Linux' and of size 29.4 GiB.

Command (m for help): t
Selected partition 1
Partition type (type L to list all types): fd
Changed type of partition 'Linux' to 'Linux raid autodetect'.

Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.
```

上記のパーテーション設定作業を、USBメモリの数だけ繰り返します。

もう一回、ディスクの状況確認。

```shell
sudo fdisk -l
```

実行結果

```shell
Disk /dev/sda: 29.4 GiB, 31541166080 bytes, 61603840 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0xbece4ca8

Device     Boot Start      End  Sectors  Size Id Type
/dev/sda1        2048 61603839 61601792 29.4G fd Linux raid autodetect


Disk /dev/sdb: 29.4 GiB, 31576817664 bytes, 61673472 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x066b3594

Device     Boot Start      End  Sectors  Size Id Type
/dev/sdb1        2048 61673471 61671424 29.4G fd Linux raid autodetect
```

初期化されました。

## ソフトウェアRAIDツールのインストール

```shell
$ sudo apt update
$ sudo apt install mdadm
```

## ソフトウェアRAIDツールの実行

```shell
$ sudo mdadm --create --verbose /dev/md0 --level=mirror --raid-devices=2 /dev/sd[ab]1
mdadm: array /dev/md0 started.
```

進捗確認。USBメモリ32GB 2本のミラーリング、大体30分くらいかかります。

```shell
$ sudo watch -n5 cat /proc/mdstat
```

### ソフトウェアRAIDの設定を保存する

```shell
$ sudo mdadm --detail --scan >> /etc/mdadm/mdadm.conf
```

### 初期化してマウント

```shell
$ sudo mkfs -t ext4 /dev/md0
$ sudo mkdir /mnt/usbmemory
$ sudo mount /dev/md0 /mnt/usbmemory
```

### 起動時に自動マウントするために

RAIDボリュームのUUIDを確認。

```shell
$ sudo blkid
/dev/md0: UUID="0a70920a-279e-46e8-8e0f-3690c118ffd3" TYPE="ext4"
```

`/dev/md0`のUUIDをメモします。UUIDを`/etc/fstab`に記録

```diff:/etc/fstab
+ UUID=0a70920a-279e-46e8-8e0f-3690c118ffd3  /mnt/usbmemory    ext4   defaults,nofail 0 0
```

## データのコピー

シングルユーザーモードに切り替えて`rsync`する。

```shell
$ sudo init 1
$ sudo rsync -aAXv --exclude={"/boot/*","/dev/*","/proc/*","/sys/*","/tmp/*","/run/*","/mnt/*","/media/*","/lost+found"} / /mnt/usbmemory
```

参考：[Rsync によるフルシステムバックアップ - ArchWiki](https://wiki.archlinux.jp/index.php/Rsync_%E3%81%AB%E3%82%88%E3%82%8B%E3%83%95%E3%83%AB%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0%E3%83%90%E3%83%83%E3%82%AF%E3%82%A2%E3%83%83%E3%83%97)

### 後作業
お好みで /var, /tmp, /home などを新しいボリュームにシンボリックリンクを作成する

# 最後に

下記のパターンをやろうとしたのですが、いろいろチャレンジしてみたところ、うまくいかなかったので諦めました。

- SDカードを抜いてUSBメモリから起動
- USBメモリから起動してRAID1を構築

コマンドを見直したら全コマンドで`sudo`していたので、`su`でrootユーザーで作業をしてもよかったかもしれない。