LinuxのRAID6復旧について

RAIDはバックアップではない。
ということを雑談で話しながら自分はバックアップ領域を作っていなかった。

そして痛い目に会い、再度、肝に銘じる。
繰り返す。RAIDはバックアップではない。

何があったのか

趣味の自鯖をRAID6を8台で構成していた。
ある日突然、RAID領域にアクセスできなくなったので調べてみると、8台中、4台が不調。
/proc/mdstatを見ると

[_UUUU___]

こりゃあかん。

ポートマルチプライヤできるeSATAインターフェースの2口から、裸族の集合住宅5BayというHDDが5台入ることができる製品を2台使って、4台・4台で分けている。どうやら、この1つに所属していたHDDがRAIDから外れているようだ。辛い。

状況を確認する

まず、一通りのSMART情報を確認する。特にSMART上では8台とも問題はないようだ。

SMART情報に問題がないようなら、RAIDを再結成してもよさそうなので

# mdadm -A --scan

などを実行する。が、うまくいかない。うち3台にてpossibly out of dateというエラーが出る。たぶん、時代遅れっすか。

雑に[a-z]指定でRAIDでスーパーブロックの中にある情報を読みに行く。これによってsdaからsdzまで読む。

# mdadm -E /dev/sd[a-z] | grep Events
         Events : 1797391
         Events : 1797391
         Events : 1797391
         Events : 1797391
         Events : 1797391
         Events : 1797381
         Events : 1548613
         Events : 1797381

なるほど。sdbからsdiまでの8台のうち、sdbからsdfまでは同期がとれているが、sdg,sdh,sdiが同期がとれていない。
というか、sdh。お前いつから外れていたんだ...。

幸いなことに、sdg,sdhはそのほかのHDDとそれほどEventsが離れていない。
RAID6は最低限、n-2台が生きていればいい。8台のうち6台が近いイベント数である。
これが意味するところは、復旧できる可能性が高いということである。

ところでsdhに関しては、以下の結果を見ると、Oh...20日以上前に外れてますやん...ということが分かり、「縮退したらメール出すようにしよう」という決意を新たにした。

# mdadm -E /dev/sd[a-z] | grep Update
    Update Time : Wed Nov  2 09:00:20 2016
    Update Time : Wed Nov  2 09:00:20 2016
    Update Time : Wed Nov  2 09:00:20 2016
    Update Time : Wed Nov  2 09:00:20 2016
    Update Time : Tue Nov  1 21:24:57 2016
    Update Time : Tue Nov  1 21:24:57 2016
    Update Time : Mon Oct 10 07:47:37 2016
    Update Time : Tue Nov  1 21:24:57 2016

ちなみにArray Stateを並べてみると

# mdadm -E /dev/sd[a-z] | grep "Array State"
   Array State : .AAAA... ('A' == active, '.' == missing, 'R' == replacing)
   Array State : .AAAA... ('A' == active, '.' == missing, 'R' == replacing)
   Array State : .AAAA... ('A' == active, '.' == missing, 'R' == replacing)
   Array State : .AAAA... ('A' == active, '.' == missing, 'R' == replacing)
   Array State : AAAAAA.A ('A' == active, '.' == missing, 'R' == replacing)
   Array State : AAAAAA.A ('A' == active, '.' == missing, 'R' == replacing)
   Array State : AAAAAAAA ('A' == active, '.' == missing, 'R' == replacing)
   Array State : AAAAAA.A ('A' == active, '.' == missing, 'R' == replacing)

となっていた。まずsdhが外れて、その後、sdhと同じ側の3台が外れたようだ。

状況を整理する。
RAID6で組んでいた8台のうち、4台が外れた状態になっている。
中身のデータは8台中、5台は完璧に、2台はギリギリセーフ、1台はアウト。
ギリギリセーフのうちの1台を完璧5台と組み合わせれば、多くのデータは救えるだろうと考えられる。

RAIDスーパーブロックの再作成

前章でmdadm -A(--assemble) --forceを実行してダメだった。
これはもう再作成(mdadm -C, --create)しかない。

とはいえ、再作成は怖いので、HDDの先頭部分をファイルに落として、ループデバイスから再作成の実験を行う。

# dd if=/dev/sdb of=/mnt/sdb.img bs=1G count=1

上記のようなコマンドで先頭1GBずつイメージファイルに落とす。これを8台分。
先頭1GBなのでファイルは取り出さず、アレイが再構成できるかどうかまでを検証する。
1GBもいらないが、アレイが修復できてファイルも取り出せたらラッキー感覚で1GB。

実験を何回かする予定なので、tmpに一度コピーしてループデバイスを作成する。

cp /mnt/sd* /tmp
losetup /dev/loop0 /tmp/sdb.img
losetup /dev/loop1 /tmp/sdc.img
losetup /dev/loop2 /tmp/sdd.img
losetup /dev/loop3 /tmp/sde.img
losetup /dev/loop4 /tmp/sdg.img
losetup /dev/loop5 /tmp/sdh.img
losetup /dev/loop6 /tmp/sdi.img
losetup /dev/loop7 /tmp/sdj.img

これをシェルスクリプトに書いておき、何度も実験。

これによって、loop[0-7]に8台分のデバイスができている。

# mdadm -E /dev/loop0

したら、RAIDのスーパーブロックの情報がそのまま出てくるはず。

このループデバイスを使ってRAID構成の再作成を行う。

RAID構成の再作成を行うには、デバイスの順番が重要であり、これを間違うとデータが壊れる。
あらかじめ、以下のコマンドを実行して、何番のデバイスだったのかを確認する。

# mdadm -E /dev/loop[0-7] | grep "Role"
   Device Role : Active device 2
   Device Role : Active device 3
   Device Role : Active device 1
   Device Role : Active device 4
   Device Role : Active device 0
   Device Role : Active device 5
   Device Role : Active device 6
   Device Role : Active device 7

この情報によると、4,2,0,1,3,5,6,7の順番に/dev/loopを構成しなくてはならないことが分かる。

この8台のうち6台を使って復旧する予定なので、実際は4,2,0,1,3,5までを利用することとする。この順番通りに記述する。
2台足りないが、これはmissingを記述すれば縮退運転となる。(missingの場所は重要で例えばloop4をmissingとする場合はloop4の場所にてmissingを書く必要がある。)

# mdadm -C -l6 -n8 /dev/md0 /dev/loop4 /dev/loop2 /dev/loop0 /dev/loop1 /dev/loop3 /dev/loop5 missing missing
mdadm: /dev/loop4 appears to be part of a raid array:
       level=raid6 devices=8 ctime=Sat Nov  1 21:44:51 2014
mdadm: partition table exists on /dev/loop4 but will be lost or
       meaningless after creating array
mdadm: /dev/loop2 appears to be part of a raid array:
       level=raid6 devices=8 ctime=Sat Nov  1 21:44:51 2014
mdadm: partition table exists on /dev/loop2 but will be lost or
       meaningless after creating array
mdadm: /dev/loop0 appears to be part of a raid array:
       level=raid6 devices=8 ctime=Sat Nov  1 21:44:51 2014
mdadm: partition table exists on /dev/loop0 but will be lost or
       meaningless after creating array
mdadm: /dev/loop1 appears to be part of a raid array:
       level=raid6 devices=8 ctime=Sat Nov  1 21:44:51 2014
mdadm: partition table exists on /dev/loop1 but will be lost or
       meaningless after creating array
mdadm: /dev/loop3 appears to be part of a raid array:
       level=raid6 devices=8 ctime=Sat Nov  1 21:44:51 2014
mdadm: /dev/loop5 appears to be part of a raid array:
       level=raid6 devices=8 ctime=Sat Nov  1 21:44:51 2014
mdadm: partition table exists on /dev/loop5 but will be lost or
       meaningless after creating array
Continue creating array? yes
mdadm: Defaulting to version 1.2 metadata
mdadm: array /dev/md0 started.

# mount /dev/md0 /mnt2
mount: unknown filesystem type 'zfs_member'

このmdadm -Cではメタデータがあるが上書きしてもよろしいかと聞かれるのでyesとする。
成功したら、mountしてみる。

が、うまくいかない。

どうもファイルシステムzfs_memberと認識されてしまう。そりゃ確かにzfsは使ったことがあるが...もともとのファイルシステムはxfsを使っていたことがfstabから分かっている。

どうしたもんかなと、作成されたアレイのスーパーブロックを過去のスーパーブロックと見比べていると気になる箇所が出てきた。
当初のバックアップ時のメタデータでは、以下のように

# mdadm -E /dev/loop[0-7] | grep "Data Offset"
    Data Offset : 262144 sectors
    Data Offset : 262144 sectors
    Data Offset : 262144 sectors
    Data Offset : 262144 sectors
    Data Offset : 262144 sectors
    Data Offset : 262144 sectors
    Data Offset : 262144 sectors
    Data Offset : 262144 sectors

データオフセットは262144セクタなのだが、新しく構成したアレイでは、

t# mdadm -E /dev/loop[0-7] | grep "Data Offset"
    Data Offset : 2048 sectors
    Data Offset : 2048 sectors
    Data Offset : 2048 sectors
    Data Offset : 2048 sectors
    Data Offset : 2048 sectors
    Data Offset : 2048 sectors
    Data Offset : 262144 sectors
    Data Offset : 262144 sectors

という風に2048セクタになっている。

あー、なるほど。もともとは262144セクタからデータが始まっていたんだが、新しく構成したアレイでは2048セクタから始まっている。
そのため、もともと何も書いていない領域を読みに行き、ファイルシステムを誤認識してzfs_memberと表示されてしまっている、と。

これはmdadmのバージョンによって異なるのか?良くわからない。よくわからないが、mdadm -C時に--data-offsetを指定できるようだ。

# mdadm -C -l6 -n8 --data-offset=262144s /dev/md0 /dev/loop4 /dev/loop2 /dev/loop0 /dev/loop1 /dev/loop3 /dev/loop5 missing missing

改めて、data-offsetを指定しての作成。うまくいったので、マウント。

# mount /dev/md0 /mnt2
mount: wrong fs type, bad option, bad superblock on /dev/md0,
       missing codepage or helper program, or other error

       In some cases useful info is found in syslog - try
       dmesg | tail or so.

Oh、失敗。

# dmesg | tail
[126834.393569]  disk 0, o:1, dev:loop4
[126834.393571]  disk 1, o:1, dev:loop2
[126834.393572]  disk 2, o:1, dev:loop0
[126834.393574]  disk 3, o:1, dev:loop1
[126834.393576]  disk 4, o:1, dev:loop3
[126834.393577]  disk 5, o:1, dev:loop5
[126834.393591] md/raid456: discard support disabled due to uncertainty.
[126834.393593] Set raid456.devices_handle_discard_safely=Y to override.
[126834.393632] md0: detected capacity change from 0 to 5637144576
[126842.935838] XFS (md0): Filesystem has duplicate UUID d3003f02-563b-44fb-a15e-9b41bd6f6f82 - can't mount

dmesgによると、XFSを一応理解してくれている様子。良かった。補足するとmdadm -Cするときに順番を間違えると、XFSとすら認識されなかった。こういった間違いを犯すのでddしたイメージ上で作業すると非常に気が楽。

# xfs_repair /dev/md0
Phase 1 - find and verify superblock...
error reading superblock 1 -- seek to offset 187528904704 failed
couldn't verify primary superblock - attempted to perform I/O beyond EOF !!!

attempting to find secondary superblock...
......................................................................................

xfs_repairしてみるが、ファイルシステムのスーパーブロックが見つからない、と来たか。

ここで、ファイルシステムの復元までの道筋がついた。
本来であれば、HDDのすべてのバックアップを取って、ループデバイス上でxfsをマウントしたいところだが、そうもいかない。

ということでギャンブルの時間。自己責任。ちなみに、このときはsdfに別のHDDが割り込んでしまったので、sdfとsdgがズレてsdgとsdhになっている。

# mdadm -C -l6 -n8 --data-offset=262144s /dev/md3 /dev/sdg /dev/sdd /dev/sdb /dev/sdc /dev/sde /dev/sdh missing missing
mdadm: /dev/sdg appears to be part of a raid array:
       level=raid6 devices=8 ctime=Sat Nov  1 21:44:51 2014
mdadm: partition table exists on /dev/sdg but will be lost or
       meaningless after creating array
mdadm: /dev/sdd appears to be part of a raid array:
       level=raid6 devices=8 ctime=Sat Nov  1 21:44:51 2014
mdadm: partition table exists on /dev/sdd but will be lost or
       meaningless after creating array
mdadm: /dev/sdb appears to be part of a raid array:
       level=raid6 devices=8 ctime=Sat Nov  1 21:44:51 2014
mdadm: partition table exists on /dev/sdb but will be lost or
       meaningless after creating array
mdadm: /dev/sdc appears to be part of a raid array:
       level=raid6 devices=8 ctime=Sat Nov  1 21:44:51 2014
mdadm: partition table exists on /dev/sdc but will be lost or
       meaningless after creating array
mdadm: /dev/sde appears to be part of a raid array:
       level=raid6 devices=8 ctime=Sat Nov  1 21:44:51 2014
mdadm: /dev/sdh appears to be part of a raid array:
       level=raid6 devices=8 ctime=Sat Nov  1 21:44:51 2014
mdadm: partition table exists on /dev/sdh but will be lost or
       meaningless after creating array
Continue creating array? yes
mdadm: Defaulting to version 1.2 metadata
mdadm: array /dev/md3 started.

結果はうまくいってそう。

[122820.636434] md: bind
[122820.636659] md: bind
[122820.636855] md: bind
[122820.637074] md: bind
[122820.637307] md: bind
[122820.637532] md: bind
[122820.641063] md/raid: md3: device sdh operational as raid disk 5
[122820.641069] md/raid: md3: device sde operational as raid disk 4
[122820.641072] md/raid: md3: device sdc operational as raid disk 3
[122820.641075] md/raid: md3: device sdb operational as raid disk 2
[122820.641078] md/raid: md3: device sdd operational as raid disk 1
[122820.641080] md/raid: md3: device sdg operational as raid disk 0
[122820.642333] md/raid: md3: allocated 8606kB
[122820.642410] md/raid: md3: raid level 6 active with 6 out of 8 devices, algorithm 2
[122820.642415] RAID conf printout:
[122820.642419]  --- level:6 rd:8 wd:6
[122820.642421]  disk 0, o:1, dev:sdg
[122820.642424]  disk 1, o:1, dev:sdd
[122820.642426]  disk 2, o:1, dev:sdb
[122820.642428]  disk 3, o:1, dev:sdc
[122820.642430]  disk 4, o:1, dev:sde
[122820.642432]  disk 5, o:1, dev:sdh
[122820.642557] created bitmap (22 pages) for device md3
[122820.648666] md3: bitmap initialized from disk: read 2 pages, set 44711 of 44711 bits
[122820.678865] md3: detected capacity change from 0 to 18002749685760
[122821.015625] XFS (md3): Mounting V4 Filesystem
[122821.363476] XFS (md3): Starting recovery (logdev: internal)
[122823.302916] XFS (md3): Ending recovery (logdev: internal)

手動でマウントする前に、勝手にマウントされた。
正しくデータが読めている。

データが読めるので、おとなしくバックアップ用のHDDに大事なデータからバックアップ中。

バックアップが終わったら、残りの2台を追加してRAID6構成に戻す予定。
8台ではなく6台で再構成したのは、resyncが走るのを嫌って。間違った構成でresyncが走ると、もう戻せなそうだったから。
resyncが走らずアレイ構成できるギリギリの台数で縮退運転。
何はともあれよかった。

まとめ

行ったこと。

  • SMARTの確認
  • mdadm -A(assemble)による復旧
  • mdadm -EによるEventsの確認
  • dd, losetupを使ってループデバイスでmdadm -C(--create)を実験
  • ループデバイス上でmdadm -Cによる再構成
  • ループデバイス上でmdadm -Cによって作成されたアレイのメタデータをmdadm -Eで確認してバックアップと比較
  • ループデバイス上でmdadm -Cによる再構成をデータオフセットを指定して行う
  • 物理デバイス上でmdadm -Cによる再構成
  • 内部データのバックアップ

今後行うこと。

  • 縮退時にメールを飛ばす
  • バックアップをデイリーかウィークリーで組む
  • 裸族の集合住宅+eSATA構成を今後どうするか検討

補足

復旧天使というRAID6構成にもXFSにも対応するソフトがあるらしく、より事態が悪くなった場合はこれを購入することを考えた。

参考文献

462 :login:Penguin:2011/05/28(土) 17:48:01.24 ID:17piUe8k
>>460
-A sd[bcd]1が無理なら--createする時に縮退で組めば
resyncが発生せずにメタデータ上書きだけでデータ本体はそのまま残る。
--createするときはチャンクサイズとかレイアウトとかも要設定。
まずは仮想マシンで手順とか確認。