created: 2022-10-29T09:13:47.849Z

RaspberryPi でソフトウェアRAIDを構成する

こちらの手順に従ってやってみる。

MBRでなくGPTを使う

アレイで使用する前にディスクをパーティションすることが強く推奨されます。ほとんどの RAID ユーザーは 2 TB 以上の HDD を選択するため、GPT パーティションテーブルが必須または推奨です。gptfdisk を使うことでディスクを簡単にパーティションすることができます。

ちょうど2TBのディスクを使おうとしていた。容量を拡張しようとするかもしれないし、せっかくなのでGPTパーティションを使うことにする。

パーティションタイプ

作成後、パーティションのタイプにはヘックスコード FD00 を指定してください。

gdisk コマンドでパーティションのタイプを設定するが、そのときの指定のこと。

Hex code or GUID (L to show codes, Enter = 8300): fd00

パーティションラベル

巨大なディスクアレイを用いる場合、ディスクを後で区別しやすくするためにディスクラベルやパーティションラベルを付けるようにしてください。

2個なので巨大でもないが、たしかにディスクの区別がついていないといざというときに厄介になるかもなと思うので、以下のように呼ぶことにする。

  • HDDスタンドのランプが点灯してる側に刺さっているディスクを hdsfront
  • 後ろ側に刺さってるディスクを hdsback

ディスクラベルをつける方法がパッとわからなかったので、パーティションラベルをつけることにする。

作業マニュアル

まずHDDスタンドにディスクを挿してから作業を開始。

$ sudo fdisk -l  # 挿したディスクが認識されていることを確認

ディスク2枚の両方ともにパーティションを作成

  • GPT でパーティションをつくりたいので gdisk でパーティションをつくる
  • パーティションタイプには Linux RAID (fd00) を指定
$ sudo gdisk /dev/sdb # すでに挿さってるのは hdsback と呼ぶ
$ sudo gdisk /dev/sdc

つくった2つのパーティションに対してラベルをつける

$ sudo e2label /dev/sdb1 hdsback
# フォーマット後じゃないとつけられないかも
$ sudo e2label /dev/sdc1 hdsfront

RAID1 を組む

$ sudo mdadm --create /dev/md0 --level=1 --raid-devices=2 /dev/sdb1 /dev/sdc1
$ sudo mdadm --detail /dev/md0  # 確認

フォーマットしてマウント

$ sudo mkfs --type=ext4 /dev/md0
$ sudo mkdir /mnt/hds
$ sudo mount /dev/md0 /mnt/hds
$ df -hT /mnt/hds # 確認

設定を出力して、initramfsを更新

$ sudo mdadm --examine -sv | sudo tee -a /etc/mdadm/mdadm.conf
# !NB! Run update-initramfs -u after updating this file.とのことなので
$ sudo update-initramfs -u

実施時のログ

基本的に↑のマニュアル通りに進行できた。(例外は 1か所だけ e2label コマンドが未フォーマットのHDDにはできなかったくらい)

まず1つめ。すでに挿さってるHDDの既存のパーティションを消して Linux RAID (fd00) にてフォーマット。

$ sudo gdisk /dev/sdb
GPT fdisk (gdisk) version 1.0.6

Warning: Partition table header claims that the size of partition table
entries is 0 bytes, but this program  supports only 128-byte entries.
Adjusting accordingly, but partition table may be garbage.
Warning: Partition table header claims that the size of partition table
entries is 0 bytes, but this program  supports only 128-byte entries.
Adjusting accordingly, but partition table may be garbage.
Partition table scan:
  MBR: MBR only
  BSD: not present
  APM: not present
  GPT: not present


***************************************************************
Found invalid GPT and valid MBR; converting MBR to GPT format
in memory. THIS OPERATION IS POTENTIALLY DESTRUCTIVE! Exit by
typing 'q' if you don't want to convert your MBR partitions
to GPT format!
***************************************************************


Warning! Secondary partition table overlaps the last partition by
33 blocks!
You will need to delete this partition or resize it in another utility.

Command (? for help): p
Disk /dev/sdb: 3907029168 sectors, 1.8 TiB
Model: 004-2E4164
Sector size (logical/physical): 512/512 bytes
Disk identifier (GUID): 9404C2BE-EE67-4B7D-AA1B-0F45FF44B9A6
Partition table holds up to 128 entries
Main partition table begins at sector 2 and ends at sector 33
First usable sector is 34, last usable sector is 3907029134
Partitions will be aligned on 2048-sector boundaries
Total free space is 2014 sectors (1007.0 KiB)

Number  Start (sector)    End (sector)  Size       Code  Name
   1            2048      3907029167   1.8 TiB     8300  Linux filesystem

Command (? for help): d
Using 1

Command (? for help): p
Disk /dev/sdb: 3907029168 sectors, 1.8 TiB
Model: 004-2E4164
Sector size (logical/physical): 512/512 bytes
Disk identifier (GUID): 9404C2BE-EE67-4B7D-AA1B-0F45FF44B9A6
Partition table holds up to 128 entries
Main partition table begins at sector 2 and ends at sector 33
First usable sector is 34, last usable sector is 3907029134
Partitions will be aligned on 2048-sector boundaries
Total free space is 3907029101 sectors (1.8 TiB)

Number  Start (sector)    End (sector)  Size       Code  Name

Command (? for help): n
Partition number (1-128, default 1):
First sector (34-3907029134, default = 2048) or {+-}size{KMGTP}:
Last sector (2048-3907029134, default = 3907029134) or {+-}size{KMGTP}:
Current type is 8300 (Linux filesystem)
Hex code or GUID (L to show codes, Enter = 8300): fd00
Changed type of partition to 'Linux RAID'

Command (? for help): w

Final checks complete. About to write GPT data. THIS WILL OVERWRITE EXISTING
PARTITIONS!!

Do you want to proceed? (Y/N): y
OK; writing new GUID partition table (GPT) to /dev/sdb.
The operation has completed successfully.
22:55:46-pi@fileserver:~ $

2つめのディスク、こちらはまっさらなので作成のみ。同様に Linux RAID (fd00) にてフォーマット。

$ sudo gdisk /dev/sdc
GPT fdisk (gdisk) version 1.0.6

Warning: Partition table header claims that the size of partition table
entries is 0 bytes, but this program  supports only 128-byte entries.
Adjusting accordingly, but partition table may be garbage.
Warning: Partition table header claims that the size of partition table
entries is 0 bytes, but this program  supports only 128-byte entries.
Adjusting accordingly, but partition table may be garbage.
Partition table scan:
  MBR: not present
  BSD: not present
  APM: not present
  GPT: not present

Creating new GPT entries in memory.

Command (? for help): p
Disk /dev/sdc: 3907029168 sectors, 1.8 TiB
Model: 004-2E4164
Sector size (logical/physical): 512/512 bytes
Disk identifier (GUID): 662429CD-2553-4709-AEEC-D0298571E8D2
Partition table holds up to 128 entries
Main partition table begins at sector 2 and ends at sector 33
First usable sector is 34, last usable sector is 3907029134
Partitions will be aligned on 2048-sector boundaries
Total free space is 3907029101 sectors (1.8 TiB)

Number  Start (sector)    End (sector)  Size       Code  Name

Command (? for help): d
No partitions

Command (? for help): n
Partition number (1-128, default 1):
First sector (34-3907029134, default = 2048) or {+-}size{KMGTP}:
Last sector (2048-3907029134, default = 3907029134) or {+-}size{KMGTP}:
Current type is 8300 (Linux filesystem)
Hex code or GUID (L to show codes, Enter = 8300): fd00
Changed type of partition to 'Linux RAID'

Command (? for help): w

Final checks complete. About to write GPT data. THIS WILL OVERWRITE EXISTING
PARTITIONS!!

Do you want to proceed? (Y/N): y
OK; writing new GUID partition table (GPT) to /dev/sdc.
The operation has completed successfully.

mdadm コマンドでRAIDデバイスを生成。

may not be suitable as a boot device などと言われ confirm を求められる。もちろん boot デバイスにはつかわないので y

$ sudo mdadm --create /dev/md0 --level=1 --raid-devices=2 /dev/sdb1 /dev/sdc1
mdadm: /dev/sdb1 appears to contain an ext2fs file system
       size=1953513560K  mtime=Thu Oct 27 11:18:20 2022
mdadm: Note: this array has metadata at the start and
    may not be suitable as a boot device.  If you plan to
    store '/boot' on this device please ensure that
    your boot-loader understands md/v1.x metadata, or use
    --metadata=0.90
Continue creating array? y
mdadm: Defaulting to version 1.2 metadata
mdadm: array /dev/md0 started.

コマンドを叩くとバックグラウンドで Resync という工程が開始される。

$ sudo mdadm --detail /dev/md0
/dev/md0:
           Version : 1.2
     Creation Time : Thu Oct 27 23:03:37 2022
        Raid Level : raid1
        Array Size : 1953381440 (1862.89 GiB 2000.26 GB)
     Used Dev Size : 1953381440 (1862.89 GiB 2000.26 GB)
      Raid Devices : 2
     Total Devices : 2
       Persistence : Superblock is persistent

     Intent Bitmap : Internal

       Update Time : Thu Oct 27 23:04:28 2022
             State : clean, resyncing
    Active Devices : 2
   Working Devices : 2
    Failed Devices : 0
     Spare Devices : 0

Consistency Policy : bitmap

     Resync Status : 0% complete

              Name : fileserver:0  (local to host fileserver)
              UUID : 004b7128:7dc6f3cf:2856c372:de98217d
            Events : 10

    Number   Major   Minor   RaidDevice State
       0       8       17        0      active sync   /dev/sdb1
       1       8       33        1      active sync   /dev/sdc1

/proc/mdstat を見ると3分くらいで0.2%の進捗とのこと。USB接続のHDDスタンドなのでIO性能が低いのかかなり時間がかかった。

$ cat /proc/mdstat
Personalities : [raid1]
md0 : active raid1 sdc1[1] sdb1[0]
      1953381440 blocks super 1.2 [2/2] [UU]
      [>....................]  resync =  0.2% (4921344/1953381440) finish=2025.5min speed=16032K/sec
      bitmap: 15/15 pages [60KB], 65536KB chunk

30時間くらいかかって完了した。

$ sudo mdadm --detail /dev/md0
/dev/md0:
           Version : 1.2
     Creation Time : Thu Oct 27 23:03:37 2022
        Raid Level : raid1
        Array Size : 1953381440 (1862.89 GiB 2000.26 GB)
     Used Dev Size : 1953381440 (1862.89 GiB 2000.26 GB)
      Raid Devices : 2
     Total Devices : 2
       Persistence : Superblock is persistent

     Intent Bitmap : Internal

       Update Time : Sat Oct 29 09:34:10 2022
             State : clean
    Active Devices : 2
   Working Devices : 2
    Failed Devices : 0
     Spare Devices : 0

Consistency Policy : bitmap

              Name : fileserver:0  (local to host fileserver)
              UUID : 004b7128:7dc6f3cf:2856c372:de98217d
            Events : 25038

    Number   Major   Minor   RaidDevice State
       0       8       17        0      active sync   /dev/sdb1
       1       8       33        1      active sync   /dev/sdc1

できたデバイスにファイルシステムを設定。

$ sudo mkfs --type=ext4 /dev/md0
mke2fs 1.46.2 (28-Feb-2021)
Creating filesystem with 488345360 4k blocks and 122093568 inodes
Filesystem UUID: a96bcf1b-a9f6-4b23-b08c-954a2eb173aa
Superblock backups stored on blocks:
	32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
	4096000, 7962624, 11239424, 20480000, 23887872, 71663616, 78675968,
	102400000, 214990848

Allocating group tables: done
Writing inode tables: done
Creating journal (262144 blocks):
done
Writing superblocks and filesystem accounting information: done

ディレクトリをつくってマウント。

$ sudo mkdir /mnt/hds
$ sudo mount /dev/md0 /mnt/hds
$ df -hT /mnt/hds
Filesystem     Type  Size  Used Avail Use% Mounted on
/dev/md0       ext4  1.8T   28K  1.7T   1% /mnt/hds

mdadm.conf を更新して update-initramfs。

$ sudo mdadm --examine -sv | sudo tee -a /etc/mdadm/mdadm.conf
ARRAY /dev/md/0  level=raid1 metadata=1.2 num-devices=2 UUID=004b7128:7dc6f3cf:2856c372:de98217d name=fileserver:0
   devices=/dev/sdc1,/dev/sdb1
$ sudo update-initramfs -u

参考

概要を知るのにわかりやすかった。

Linux RAID タイプでパーティションつくる方法が参考になった。

いちばん情報が多そう。

その他参考になった記事

Good Code, Bad Code ~持続可能な開発のためのソフトウェアエンジニア的思考
[ad] Good Code, Bad Code ~持続可能な開発のためのソフトウェアエンジニア的思考
Tom Long, 秋勇紀 (単行本(ソフトカバー))