USBメモリでRAID 5を構築・USBメモリの寿命差を作る
複数のUSBメモリが同時に壊れたりしないよう予防策を講じてみた
0. 何故こんな事をするのか?
現在は 64GB USBメモリ4本でRAID 5を構成しています。
# cat /proc/mdstat
Personalities : [raid6] [raid5] [raid4]
md0 : active raid5 sdd1[0] sda1[4] sdb1[3] sdc1[1]
185054208 blocks super 1.2 level 5, 256k chunk, algorithm 2 [4/4] [UUUU]
unused devices: <none>
# mdadm --detail /dev/md0
/dev/md0:
Version : 1.2
Creation Time : Sat Jul 30 11:24:03 2016
Raid Level : raid5
Array Size : 185054208 (176.48 GiB 189.50 GB)
Used Dev Size : 61684736 (58.83 GiB 63.17 GB)
Raid Devices : 4
Total Devices : 4
Persistence : Superblock is persistent
Update Time : Thu Sep 1 20:15:38 2016
State : clean
Active Devices : 4
Working Devices : 4
Failed Devices : 0
Spare Devices : 0
Layout : left-symmetric
Chunk Size : 256K
Name : RaspberryPi3:0 (local to host RaspberryPi3)
UUID : c26559b7:abb329b4:1960d0d5:7b9c8287
Events : 1027
Number Major Minor RaidDevice State
0 8 49 0 active sync /dev/sdd1
1 8 33 1 active sync /dev/sdc1
3 8 17 2 active sync /dev/sdb1
4 8 1 3 active sync /dev/sda1
|
Number 0, 1, 3 は一緒にまとめて購入、シリアル番号も極めて近いことから、同じ製造ロットか、殆ど同時期に製造された物と思われます。Number 4 のみ後から追加したものです。(何故 Number 2 が飛んでいるのかは不明。)
そもそもRAIDは、構成しているデバイスには個体差があり、故障が発生する時期にはバラつきがあることを前程にして可用性を持たせています。HDD ならばこの前程はある程度正しいと言えます。(それでも同じ製造ロットの HDDの寿命は近くなる傾向にある。そのため、RAIDを構成する HDDはある程度時期をずらして購入する方が好ましいとされている。)しかし、USBメモリの場合の製品寿命は、フラッシュメモリの記録セル(メモリセル)に対する書き込み回数と、一定の書き込み回数に達したメモリセルを代替するための余剰メモリセル量から決まる極めて論理的なものです。特定のメモリセルへの書き込みが集中しないよう全体に書き込みを平均化して製品寿命を延ばすウェアレベリングという仕組みも、メーカーや製品が異なれば、異なるアルゴリズム(このあたりは各製造メーカーの特許技術になっていたりする)が使用されていることで寿命差が生じると考えられますが、全く同じメーカーの同じ製品であれば寿命差が生じるとは考えにくいです。(まぁ素人考えですが・・・)
また、RAID 5では書き込むデータをチャンクサイズに分割して複数のデバイスに分散して書き込みます。その際、1台にはチェックサムが書き込まれますが、チェックサムに使用される量も他のデバイスと同じはずです。つまり書き込みの負荷はどのデバイスも殆ど同じはずで、唯一チャンクサイズで割りきれなかった余りの分だけがデバイスによって異なるかもしれないと言った程度だと考えられます。
今回は、そのような全く同じ寿命のデバイスをRAIDデバイスの構成デバイスとして同時に使用し始め、各デバイスに同じ負荷を与え続けているというわけですね。このまま使用を続けていると同時に寿命を迎えるデバイスが発生しても何ら不思議ではないわけです。RAID 5は1台の故障であればデータロストにはなりませんが、複数台が故障すればゲームセット。データは失われ、復旧できなくなります。
そこで、RAIDを構成している USBメモリデバイスに故意に寿命差を作ることで、複数のデバイスが同時に故障するという事態を予防したいと考えました。これは USBメモリを延命させるような作業ではなく、悲しいかな故意に余命を削る作業となります。
(それ以外にも USBメモリの故障から復旧する作業のリハーサルという意味もありますね。)
作業手順としては以下のようになります。
- バックアップ作成
/dev/md0 をアンマウント
- 1台のUSBデバイスを故障扱いにし、RAID構成デバイスから外す
- 外したUSBメモリに書き込み負荷をかける(例えばベンチマークや、全領域へのゼロ書き込みなど)
- USBメモリにパーティションを再作成し、RAID構成デバイスに組み込みRAIDを再構成する
- RAIDの再構成が完了したら、次のUSBデバイスについて同じように3〜5を実施する
これで最初にRAID構成した3台に寿命差が生じるようになると思います。(Number 0, 1 に比べ Number 3, 4 の方が長寿になる。Number 3 と 4 は使用開始した時期の分だけ寿命差が生じていると期待する。)
1. バックアップ作成
今さらではありますが「RAIDはバックアップに在らず」は常識です。まして今回はRAID構成デバイスを外して冗長性がない状態にするので、その間にUSBメモリが1台でも故障すればデータロストとなります。そのため、作業前にはRAIDに保存してあるデータのバックアップを作成しておきます。
2. /dev/md0 をアンマウント
マウントしたままでも作業は可能(動作を継続したまま故障したデバイスを交換するような活性保守が可能)ではありますが、安全のためにはアンマウントしておいた方が良いでしょう。
ウチの場合は/dev/md0 を/media にマウントしているので、
としてアンマウントしておきます。
3. 1台のUSBデバイスを故障扱いにし、RAID構成デバイスから外す
最初は Number 0 のデバイスを故障にしてみます。デバイス名は/dev/sdd1 になっていますが、udev でデバイス名を固定してありまして、これは/dev/usbma1 という名前のデバイスになります。
/dev/sd* というデバイス名は、OSがデバイスを認識した順に割り振るので、ブートの度に変わってしまうのです。そのため、現在は、こんな状態になっていました。
# ls -l /dev/usb*
lrwxrwxrwx 1 root root 3 8月 28 17:17 /dev/usbma -> sdd
lrwxrwxrwx 1 root root 4 8月 28 17:17 /dev/usbma1 -> sdd1
lrwxrwxrwx 1 root root 3 8月 28 17:17 /dev/usbmb -> sdc
lrwxrwxrwx 1 root root 4 8月 28 17:17 /dev/usbmb1 -> sdc1
lrwxrwxrwx 1 root root 3 8月 28 17:17 /dev/usbmc -> sdb
lrwxrwxrwx 1 root root 4 8月 28 17:17 /dev/usbmc1 -> sdb1
lrwxrwxrwx 1 root root 3 8月 28 17:17 /dev/usbmd -> sda
lrwxrwxrwx 1 root root 4 8月 28 17:17 /dev/usbmd1 -> sda1
|
寿命差を作りたいのは、最初にRAID構成した3台です。これは/dev/usbma, /dev/usbmb, /dev/usbmc の3台になります。最初の/dev/usbma は現在/dev/sdd になっているというわけです。デバイス名を固定しておいたおかげで、こんなややこしい状況でも作業対象の USBメモリを特定できます。
と言うことで、先ずは/dev/usbma を故障扱いにしてみます。
# mdadm --fail /dev/md0 /dev/usbma1
mdadm: set /dev/usbma1 faulty in /dev/md0
# mdadm --detail /dev/md0
/dev/md0:
Version : 1.2
Creation Time : Sat Jul 30 11:24:03 2016
Raid Level : raid5
Array Size : 185054208 (176.48 GiB 189.50 GB)
Used Dev Size : 61684736 (58.83 GiB 63.17 GB)
Raid Devices : 4
Total Devices : 4
Persistence : Superblock is persistent
Update Time : Sat Sep 3 09:13:37 2016
State : clean, degraded
Active Devices : 3
Working Devices : 3
Failed Devices : 1
Spare Devices : 0
Layout : left-symmetric
Chunk Size : 256K
Name : RaspberryPi3:0 (local to host RaspberryPi3)
UUID : c26559b7:abb329b4:1960d0d5:7b9c8287
Events : 1029
Number Major Minor RaidDevice State
0 0 0 0 removed
1 8 33 1 active sync /dev/sdc1
3 8 17 2 active sync /dev/sdb1
4 8 1 3 active sync /dev/sda1
0 8 49 - faulty /dev/sdd1
|
1台故障した状態になりました(*1)。これをRAID構成デバイスから外します。
# mdadm --remove /dev/md0 /dev/usbma1
mdadm: hot removed /dev/usbma1 from /dev/md0
# mdadm --detail /dev/md0
/dev/md0:
Version : 1.2
Creation Time : Sat Jul 30 11:24:03 2016
Raid Level : raid5
Array Size : 185054208 (176.48 GiB 189.50 GB)
Used Dev Size : 61684736 (58.83 GiB 63.17 GB)
Raid Devices : 4
Total Devices : 3
Persistence : Superblock is persistent
Update Time : Sat Sep 3 09:16:52 2016
State : clean, degraded
Active Devices : 3
Working Devices : 3
Failed Devices : 0
Spare Devices : 0
Layout : left-symmetric
Chunk Size : 256K
Name : RaspberryPi3:0 (local to host RaspberryPi3)
UUID : c26559b7:abb329b4:1960d0d5:7b9c8287
Events : 1030
Number Major Minor RaidDevice State
0 0 0 0 removed
1 8 33 1 active sync /dev/sdc1
3 8 17 2 active sync /dev/sdb1
4 8 1 3 active sync /dev/sda1
# cat /proc/mdstat
Personalities : [raid6] [raid5] [raid4]
md0 : active raid5 sda1[4] sdb1[3] sdc1[1]
185054208 blocks super 1.2 level 5, 256k chunk, algorithm 2 [4/3] [_UUU]
unused devices: <none>
|
意図したとおり、先頭のデバイスが構成デバイスから外されており、縮退(degraded)状態で動作しています。これで故障扱いにした USBメモリをハブから抜いても大丈夫なはずです。
USBメモリをハブから抜いてみて、もう一度確認。(万一抜くUSBメモリを間違えていたら、[_U_U]なんて状態になっているのではないかと思う。すぐ戻せば大丈夫かもしれないが、データロストになる可能性が高いと思う。怖いから試してないけど・・・)
# cat /proc/mdstat
Personalities : [raid6] [raid5] [raid4]
md0 : active raid5 sda1[4] sdb1[3] sdc1[1]
185054208 blocks super 1.2 level 5, 256k chunk, algorithm 2 [4/3] [_UUU]
unused devices: <none>
|
大丈夫ですね。
4. 外したUSBメモリに書き込み負荷をかける
外したUSBメモリを MacのUSBポートに挿します。Macでは使用できないパーティションになっているので、初期化、フォーマットしてしまいます。今回は、購入時と同じ「MS-DOS(FAT)」にフォーマットしなおしてマウントさせました。
これで USBメモリの中身は無い状態になりましたが、実際にはメモリセル上に記録されているデータは消去されずに残っています。パーティションの再作成とフォーマットで、OS上ファイルが無い状態になっただけです。ここから実際にI/O負荷をかけてメモリセルの書き換えを行います。今回はベンチマークをやってみました。
あまり寿命を削りすぎても困るので長時間はやっていませんが、Writeが14MB/s、Readが36MB/s程度の性能でした。ワタシの MacPro はUSB 2.0なので、まぁこんなモンでしょう。
5. USBメモリにパーティションを再作成し、RAID構成デバイスに組み込みRAIDを再構成する
Mac から USBメモリを抜いて、Raspberry Pi の USBハブに戻します。すると以前と同じ USBデバイス名が表れます。
# ls -l /dev/usbma*
lrwxrwxrwx 1 root root 3 9月 3 09:49 /dev/usbma -> sdd
lrwxrwxrwx 1 root root 4 9月 3 09:49 /dev/usbma1 -> sdd1
|
RAIDに組み込むために、以前やったのと同じようにパーティションを作り直します。
# fdisk /dev/usbma
〜以前と同じ手順なので省略〜
# fdisk -l /dev/usbma
Disk /dev/usbma: 58.9 GiB, 63199772672 bytes, 123437056 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: 0x00000000
Device Boot Start End Sectors Size Id Type
/dev/usbma1 2048 123437055 123435008 58.9G fd Linux raid autodetect
|
パーティションを作り直したので、このデバイスをRAIDに組み込みます。
# mdadm --add /dev/md0 /dev/usbma1
mdadm: added /dev/usbma1
# mdadm --detail /dev/md0
/dev/md0:
Version : 1.2
Creation Time : Sat Jul 30 11:24:03 2016
Raid Level : raid5
Array Size : 185054208 (176.48 GiB 189.50 GB)
Used Dev Size : 61684736 (58.83 GiB 63.17 GB)
Raid Devices : 4
Total Devices : 4
Persistence : Superblock is persistent
Update Time : Sat Sep 3 10:10:52 2016
State : clean, degraded, recovering
Active Devices : 3
Working Devices : 4
Failed Devices : 0
Spare Devices : 1
Layout : left-symmetric
Chunk Size : 256K
Rebuild Status : 0% complete
Name : RaspberryPi3:0 (local to host RaspberryPi3)
UUID : c26559b7:abb329b4:1960d0d5:7b9c8287
Events : 1032
Number Major Minor RaidDevice State
5 8 49 0 spare rebuilding /dev/sdd1
1 8 33 1 active sync /dev/sdc1
3 8 17 2 active sync /dev/sdb1
4 8 1 3 active sync /dev/sda1
|
RAIDに組み込まれて再構成しています。再構成には
# cat /proc/mdstat
Personalities : [raid6] [raid5] [raid4]
md0 : active raid5 sdd1[5] sda1[4] sdb1[3] sdc1[1]
185054208 blocks super 1.2 level 5, 256k chunk, algorithm 2 [4/3] [_UUU]
[>....................] recovery = 1.1% (707180/61684736) finish=113.1min speed=8981K/sec
unused devices: <none>
|
113分かかると言うので、制限速度を上げてみましたが、
# echo 500000 >/proc/sys/dev/raid/speed_limit_min
# echo 500000 >/proc/sys/dev/raid/speed_limit_max
# cat /proc/mdstat
Personalities : [raid6] [raid5] [raid4]
md0 : active raid5 sdd1[5] sda1[4] sdb1[3] sdc1[1]
185054208 blocks super 1.2 level 5, 256k chunk, algorithm 2 [4/3] [_UUU]
[>....................] recovery = 2.5% (1603116/61684736) finish=109.5min speed=9140K/sec
unused devices: <none>
|
全然速くならないですね。まぁいいや、このまま放置しておきましょう。おそらく 3台のUSBメモリから読み出して修復したデータを、組み込んだ 1台のUSBメモリにどんどん書き込んでいることでしょう。これだけでも結構な負荷になっていると思われます。これで1台めのUSBメモリの寿命を削ることができました。
6. RAIDの再構成が完了したら、次のUSBデバイスについて同じように3〜5を実施する
再構成が完了したら、次のUSBデバイス(/dev/usbmb) についても同じ作業を行います。(必ず再構成の完了後に行うこと。再構成完了前にやってしまうと、データロストになるので注意。)このとき、先に行ったのとは別の負荷にするか、負荷をかける時間を変えようにします。このUSBデバイスでは、全体をゼロ書き込みするという消耗が激しそうな負荷をかけてみました。64GBのゼロ書き込みに1時間以上かかりました。
/dev/md0 をマウントし、RAID構成デバイスの寿命差を作る作業は完了です。
(*1):メールもちゃんと届いていました。
Subject: Fail event on /dev/md0:RaspberryPi3
This is an automatically generated mail message from mdadm
running on RaspberryPi3
A Fail event had been detected on md device /dev/md0.
It could be related to component device /dev/sdd1.
Faithfully yours, etc.
P.S. The /proc/mdstat file currently contains the following:
Personalities : [raid6] [raid5] [raid4]
md0 : active raid5 sdd1[0](F) sda1[4] sdb1[3] sdc1[1]
185054208 blocks super 1.2 level 5, 256k chunk, algorithm 2 [4/3] [_UUU]
unused devices: <none>
|
|