起動用パーティションを含むRAID環境を復旧し、起動用パーティションを冗長化する

起動用パーティションを含むハードディスクが故障した時の、以下の作業についての備忘録です。

* RAID 環境の復旧手順
* 起動用パーティションの復旧手順
* 起動用パーティションの冗長化手順

# RAIDを停止する

RAID1 な領域は、以下のように degraded mode に移行。

```shell-session
# mdadm --manage /dev/md0 --fail /dev/sda2
# mdadm --manage /dev/md2 --fail /dev/sda4
```

RAID0 のスワップ用領域については、完全に停止。

```shell-session
# swapoff
# mdadm --stop /dev/md1
```

復旧作業で必要になるので、ハードディスクを交換する前にパーティション情報を取り出しておく。

```shell-session
# fdisk -l /dev/sda
Disk /dev/sda: 1.8 TiB, 2000398934016 bytes, 3907029168 sectors
Disk model: ST2000DM006-2DM1
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disklabel type: dos
Disk identifier: 0xf1df28a1

Device     Boot     Start        End    Sectors   Size Id Type
/dev/sda1  *         2048    1050623    1048576   512M  6 FAT16
/dev/sda2         1050624  501051391  500000768 238.4G fd Linux raid autodetect
/dev/sda3       501051392  751050751  249999360 119.2G fd Linux raid autodetect
/dev/sda4       751050752 3907029167 3155978416   1.5T fd Linux raid autodetect
```

原因をまだ調査できていないが、2019年12月の故障交換の際、2018年7月に設定したはずの冗長化が無効になっていた。再起動する前に、`efibootmgr` コマンドを実行して、冗長化が有効になっていることを確認しておくべき。

# 起動用パーティションを復旧する

最初[^regret]に、ディスク[^disk]を交換。

[^disk]: 物理的に一番上に設置されていたディスクが /dev/sda だろうと思って作業していたら、実は /dev/sdd だったので、しばらく悩みましたが。

[^regret]: 復旧が完了した時点から振り返ってみると、ディスクを交換するためにシャットダウンする前に、[起動用パーティションを冗長化する](#起動用パーティションを冗長化する)操作を行なっておくべきでした。今回、部品が届いてから復旧するまでの所要時間は28時間（実際に作業した時間は6時間ほど）でしたが、この段階できちんと冗長化していれば、復旧所要時間4時間（実作業時間2時間）で復旧できただろうと思います。

当然ながら、起動用ディスクを交換してしまったので、起動できない。なので、インストーラの rescue mode を利用する。まず、[Debian 公式サイト](https://www.debian.org/CD/netinst/index.ja.html)から、ネットワークインストール用 iso イメージをダウンロード。インストール用 USB メモリを用意。

```
# cp debian-9.1.0-amd64-netinst.iso /dev/sdb
```

次に、インストール用 USB メモリを使って起動し、advanced options から rescue mode で起動を選ぶ。適当にキーマップなどを選択した後で、まずシェルを起動し、partition を作成する。

```
# fdisk /dev/sda
```

今回の場合は、RAID1 の相棒となるのが /dev/sdb なので、/dev/sdb のパーティション構成を見ながら、まったく同じに切る。

次に、/dev/sda1 を起動用パーティションとして復旧する。まず、ファイルシステムを作成し、適切な場所に mount した上で、grub-install を呼び出す。

```shell-session
# mkfs.vfat /dev/sda1
# mount -t vfat /dev/sda1 /boot/efi
# grub-install --efi-directory /boot/efi --bootloader-id debian
```




# RAIDを復旧する


シェルから抜けて rescue mode の menu に戻る。そこで「Detect disks」を選択し、さらに「Ansemble RAIDs」を選ぶ。すると、片系が停止したままの状態ではあるけれども、RAID が動き出す。その状態で、まず RAID を復旧する。

```shell-session
# mdadm --manage /dev/md0 --add /dev/sda2
# mdadm --manage /dev/md2 --add /dev/sda4
```

進行状況は /proc/mdstat を見れば分かる。

# 

先の「Ansemble RAIDs」した状態で、root partition（今回の場合は /dev/md0 ）を指定して、root partition 配下で shell を起動する。


# 起動用パーティションを冗長化する

今回、起動用パーティションが冗長化されていなかったので、インストール用 USB メモリを用意するなどの手間がかかった。これを機会にきちんと冗長化しておくことにする。

/dev/sda1 上に起動用パーティションを復旧した時と、手順はほぼ同じ。マウントポイントのディレクトリ名称と、grub-install のインストール先ディレクトリ名のみ異なる。

```shell-session
# mkfs.vfat /dev/sdb1
# mkdir /boot/efi_sub
# mount -t vfat /dev/sdb1 /boot/efi_sub
# grub-install --efi-directory=/boot/efi_sub --bootloader-id="debian (sub)"
```

正しく冗長化されていれば、以下のように efibootmgr コマンドの結果に2つのエントリが現れるはず。

```shell-session
# efibootmgr
BootCurrent: 000A
Timeout: 0 seconds
BootOrder: 000A,0000,0009,0001,0002,0003,0004,0005,0006,0007,0008
Boot0000* debian
(中略)
Boot000A* debian (sub)
```

今回のトラブルでは、/etc/fstab に /boot/efi に関するエントリが存在しなかったため、判断を誤って回り道をした。そのため、これも修正しておく。まず、以下のコマンドで UUID を調査。

```shell-session
# blkid|grep /dev/sda1
# blkid|grep /dev/sdb1
```

以下のエントリを /etc/fstab に追加。

```conf:/etc/fstab
UUID=ABCD-ABCD	/boot/efi       vfat	umask=0077	0	1
UUID=ABCD-ABCD	/boot/efi_sub	vfat	umask=0077	0	1
```

# スワップ用パーティションを復旧する

従来は RAID0 な領域を作成してから、その領域を swap として使っていた。しかし、これは迂遠な設定であり、[単に複数のパーティションを swap として指定し、優先度を等しくしておけば良いらしい](https://uc2.h2np.net/index.php/Linux%E3%81%AEswap%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6%E7%A7%81%E3%81%8C%E7%9F%A5%E3%81%A3%E3%81%A6%E3%81%84%E3%82%8B%E4%BA%8C%E3%80%81%E4%B8%89%E3%81%AE%E4%BA%8B%E6%9F%84)。

まず、スワップ用にパーティションを初期化する。

```shell-session
# mkswap -L SWAP0 /dev/sda3
# mkswap -L SWAP1 /dev/sdb3
```

次に、/etc/fstab のスワップ用パーティションの設定を書き換える。

```conf:/etc/fstab
LABEL=SWAP0     none    swap    defaults,pri=0  0       0
LABEL=SWAP1     none    swap    defaults,pri=0  0       0
```

最後に、スワップを有効化する。

```shell-session
# swapon -a
```

/proc/swaps の内容を調べて、2つのパーティションが有効化されており、かつ、2つのパーティションの優先度が等しいことを確認しておく。

```shell-session
# cat /proc/swaps 
Filename        Type            Size            Used    Priority
/dev/sda3       partition       124999676       0       0
/dev/sdb3       partition       124999676       0       0
```

# 復旧用メモ

以下は、筆者の環境の復旧用メモ。ハードディスクが故障するとパーティションテーブルすら取り出せなくなることがあったので、パーティションテーブルの情報だけは正常時にメモっておく方が良いと言われていました。そこまで酷い故障は、筆者の観測範囲では、最近数年間は遭遇したことはないのですが、一応念のために。

```
# fdisk -l /dev/sda|grep ^/
/dev/sda1        2048    1050623    1048576   512M EFI System
/dev/sda2     1050624 1001050111  999999488 476.9G Linux RAID
/dev/sda3  1001050112 1251049471  249999360 119.2G Linux swap
/dev/sda4  1251049472 7814035455 6562985984   3.1T Linux RAID
# fdisk -l /dev/sdb|grep ^/
/dev/sdb1        2048    1050623    1048576   512M EFI System
/dev/sdb2     1050624 1001050111  999999488 476.9G Linux RAID
/dev/sdb3  1001050112 1251049471  249999360 119.2G Linux swap
/dev/sdb4  1251049472 7814035455 6562985984   3.1T Linux RAID
# fdisk -l /dev/sdc|grep ^/
/dev/sdc1   2048 7814035455 7814033408  3.7T Linux RAID
# fdisk -l /dev/sdd|grep ^/
/dev/sdd1   2048 7814035455 7814033408  3.7T Linux RAID
```

（2020年7月31日追記）以前のマシンでは、上記の手順で普通にブートパーティションが冗長化できたのだが、新しいマシンでは冗長化したパーティションからは自動的にブートできず、以下のような grub のプロンプトが表示されるだけだった。

```
grub>
```

この場合、`/boot/efi/efi/debian/grub.cfg` などに記載されている内容を手動で入力すれば起動できる。筆者の環境の場合は root は `(md0)` として grub から見えていたので、以下のように grub コマンドを実行すると起動できた。

```
grub> configfile (md0)/boot/grub/grub.cfg
```