2015年1月2日金曜日

ソフトウェアRAIDのMDADMでRAID1を復旧する

みなさん、明けましておめでとうございます。


先月、会社で使用しているメールサーバーが突然ダウンしてしまいました。
電源ユニットの異常によるものです。
スペアの電源ユニットに交換して無事に起動はできたのですが、RAID構成しているHDDがその際に故障してしまったらしく、同期が出来ていない状態です。
幸いにも故障したのは、sdb側(ミラー側)なので当面片肺起動で凌ぐこととし、暇ができたら年末年始の休暇中にRAIDの復旧を試みることとしました。


で、年末のとある休日

まずは故障したHDDを外した状態の同期状況を確認。

net:/proc# cat mdstat
Personalities : [raid1]
md1 : active (auto-read-only) raid1 sda5[0]
      2634560 blocks [2/1] [U_]
md0 : active raid1 sda1[0]
      153613376 blocks [2/1] [U_]
unused devices: <none>

sdbがない片肺状態なので、この状態で何かトラブルがあったらお終いです(^^;
まずは、作業前にsdaのバックアップを取っておきたいので、ネットでツールを探してみます。
 EaseUS Todo Backup Free か AOMEI Backupper Standard がディスクイメージごと抜けて良さそうです。
今回は AOMEI Backupper Standard でバックアップをとりました。


いよいよ作業の開始です。
sdaがどういう構成になっているか確認をします。

net:/proc# fdisk -l /dev/sda
Disk /dev/sda: 160.0 GB, 160000000000 bytes
255 heads, 63 sectors/track, 19452 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Disk identifier: 0x000778ba
   Device Boot      Start         End      Blocks   Id  System
/dev/sda1   *           1       19124   153613498+  fd  Linux raid autodetect
/dev/sda2           19125       19452     2634660    5  Extended
/dev/sda5           19125       19452     2634628+  fd  Linux raid autodetect


sda2の拡張パーティション上にsda5が構築されてます。

同様に今回追加するディスクの状況も確認します。

net:/proc# fdisk -l /dev/sdb
Disk /dev/sdb: 160.0 GB, 160041885696 bytes
255 heads, 63 sectors/track, 19457 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Disk identifier: 0xed61aa6f
   Device Boot      Start         End      Blocks   Id  System
/dev/sdb1               1       19458   156288000    7  HPFS/NTFS


sdbはWindowsServerからぶっこ抜いたHDDなので、ファイルシステムがHPFS/NTFSになっちゃってますね(^^;
sdbをsdaと同じ構成にしなければならないのですが、まずはNTFSのパーティションを削除しなければなりません。

net:/proc# fdisk /dev/sdb
The number of cylinders for this disk is set to 19457.
There is nothing wrong with that, but this is larger than 1024,
and could in certain setups cause problems with:
1) software that runs at boot time (e.g., old versions of LILO)
2) booting and partitioning software from other OSs
   (e.g., DOS FDISK, OS/2 FDISK)
Command (m for help): d ← 削除します
Selected partition 1 ← パーティションを選択、sdb1を選ぶので1を入力
Command (m for help): w ← 書き込みします
The partition table has been altered!
Calling ioctl() to re-read partition table.
Syncing disks.


さて、上手く削除できたか確認してみます。

net:/proc# fdisk -l
Disk /dev/sda: 160.0 GB, 160000000000 bytes
255 heads, 63 sectors/track, 19452 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Disk identifier: 0x000778ba
   Device Boot      Start         End      Blocks   Id  System
/dev/sda1   *           1       19124   153613498+  fd  Linux raid autodetect
/dev/sda2           19125       19452     2634660    5  Extended
/dev/sda5           19125       19452     2634628+  fd  Linux raid autodetect
Disk /dev/sdb: 160.0 GB, 160041885696 bytes
255 heads, 63 sectors/track, 19457 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Disk identifier: 0xed61aa6f
   Device Boot      Start         End      Blocks   Id  System


sdb1のパーティションがなくなっていますので削除できました。

ではいよいよsdbのパーティションをsdaと同じ様に作成していきます。

net:/proc# fdisk /dev/sdb
The number of cylinders for this disk is set to 19457.
There is nothing wrong with that, but this is larger than 1024,
and could in certain setups cause problems with:
1) software that runs at boot time (e.g., old versions of LILO)
2) booting and partitioning software from other OSs
   (e.g., DOS FDISK, OS/2 FDISK)
Command (m for help): n ← パーティションの新規作成
Command action
   e   extended
   p   primary partition (1-4)
p ← primary partitionを選択
Partition number (1-4): 1 ← sdb1にするので1を入力
First cylinder (1-19457, default 1): 1 ← sda1のStartのシリンダ数と一緒にする
Last cylinder or +size or +sizeM or +sizeK (1-19457, default 19457): 19124 ← sda1のEndのシリンダ数と一緒にする
Command (m for help): t ← 領域のシステム ID を変更する
Selected partition 1
Hex code (type L to list codes): fd ← sda1のSystemと同じfdを入力する
Changed system type of partition 1 to fd (Linux raid autodetect)
Command (m for help): a ← boot可能フラグをつける
Partition number (1-4): 1 
Command (m for help): p ← 作成した領域テーブルを表示して確認する
Disk /dev/sdb: 160.0 GB, 160041885696 bytes
255 heads, 63 sectors/track, 19457 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Disk identifier: 0xed61aa6f
   Device Boot      Start         End      Blocks   Id  System
/dev/sdb1   *           1       19124   153613498+  fd  Linux raid autodetect


sdb1は上手く作成できそうです。
続いてsdb2を作成します。

Command (m for help): n ← パーティションの新規作成
Command action
   e   extended
   p   primary partition (1-4)
e ← 拡張領域として確保します。
Partition number (1-4): 2 ← sdb2にするので2を入力
First cylinder (19125-19457, default 19125):
Using default value 19125 ← 19125がデフォルトで選択されます。
Last cylinder or +size or +sizeM or +sizeK (19125-19457, default 19457): 19452 ← sda2のEndのシリンダ数と一緒にする(ミラー側なので19457でも問題はないけど、安心の為同じにしておく)
Command (m for help): t ← 領域のシステム ID を変更する
Partition number (1-5): 2
Hex code (type L to list codes): 5 ← Extendedは5です。
 
Command (m for help): p ← 作成した領域テーブルを表示して確認する
Disk /dev/sdb: 160.0 GB, 160041885696 bytes
255 heads, 63 sectors/track, 19457 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Disk identifier: 0xed61aa6f
   Device Boot      Start         End      Blocks   Id  System
/dev/sdb1   *           1       19124   153613498+  fd  Linux raid autodetect
/dev/sdb2           19125       19452     2634660    5  Extended


続いてsdb5をsdb2上に作成します。

Command (m for help): n ← パーティションの新規作成
Command action
   l   logical (5 or over)
   p   primary partition (1-4)
l ← logicalを選択します。
First cylinder (19125-19452, default 19125): 19125 ← 論理領域なのでsdb2と同じに
Last cylinder or +size or +sizeM or +sizeK (19125-19452, default 19452): 19452 ← 論理領域なのでsdb2と同じに
Command (m for help): t ← 領域のシステム ID を変更する
Partition number (1-5): 5
Hex code (type L to list codes): 83 ← swap領域なので83を選択、でもこれ間違い
Command (m for help): p ← 作成した領域テーブルを表示して確認する
Disk /dev/sdb: 160.0 GB, 160041885696 bytes
255 heads, 63 sectors/track, 19457 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Disk identifier: 0xed61aa6f
   Device Boot      Start         End      Blocks   Id  System
/dev/sdb1   *           1       19124   153613498+  fd  Linux raid autodetect
/dev/sdb2           19125       19452     2634660    5  Extended
/dev/sdb5           19125       19452     2634628+  83  Linux
Command (m for help): w ← 今までの作業を書き込み
The partition table has been altered!
Calling ioctl() to re-read partition table.
Syncing disks.


さてここまでの作業内容を確認

net:/proc# fdisk -l
Disk /dev/sda: 160.0 GB, 160000000000 bytes
255 heads, 63 sectors/track, 19452 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Disk identifier: 0x000778ba
   Device Boot      Start         End      Blocks   Id  System
/dev/sda1   *           1       19124   153613498+  fd  Linux raid autodetect
/dev/sda2           19125       19452     2634660    5  Extended
/dev/sda5           19125       19452     2634628+  fd  Linux raid autodetect
Disk /dev/sdb: 160.0 GB, 160041885696 bytes
255 heads, 63 sectors/track, 19457 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Disk identifier: 0xed61aa6f
   Device Boot      Start         End      Blocks   Id  System
/dev/sdb1   *           1       19124   153613498+  fd  Linux raid autodetect
/dev/sdb2           19125       19452     2634660    5  Extended
/dev/sdb5           19125       19452     2634628+  83  Linux


ありゃ、sdb5のファイルシステムが間違ってしまったようでsda5と同じになってません。
修正します。

net:/proc# fdisk /dev/sdb
The number of cylinders for this disk is set to 19457.
There is nothing wrong with that, but this is larger than 1024,
and could in certain setups cause problems with:
1) software that runs at boot time (e.g., old versions of LILO)
2) booting and partitioning software from other OSs
   (e.g., DOS FDISK, OS/2 FDISK)
Command (m for help): t ← 領域のシステム ID を変更する
Partition number (1-5): 5 ← sdb5を選択
 
Hex code (type L to list codes): fd ← sda5のSystemと同じfdを入力する
 
Changed system type of partition 5 to fd (Linux raid autodetect)
Command (m for help): p ← 作成した領域テーブルを表示して確認する
Disk /dev/sdb: 160.0 GB, 160041885696 bytes
255 heads, 63 sectors/track, 19457 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Disk identifier: 0xed61aa6f
   Device Boot      Start         End      Blocks   Id  System
/dev/sdb1   *           1       19124   153613498+  fd  Linux raid autodetect
/dev/sdb2           19125       19452     2634660    5  Extended
/dev/sdb5           19125       19452     2634628+  fd  Linux raid autodetect
Command (m for help): w ← 今までの作業を書き込み
The partition table has been altered!
Calling ioctl() to re-read partition table.
Syncing disks.


もう一度確認してみましょう。

net:/proc# fdisk -l
Disk /dev/sda: 160.0 GB, 160000000000 bytes
255 heads, 63 sectors/track, 19452 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Disk identifier: 0x000778ba
   Device Boot      Start         End      Blocks   Id  System
/dev/sda1   *           1       19124   153613498+  fd  Linux raid autodetect
/dev/sda2           19125       19452     2634660    5  Extended
/dev/sda5           19125       19452     2634628+  fd  Linux raid autodetect
Disk /dev/sdb: 160.0 GB, 160041885696 bytes
255 heads, 63 sectors/track, 19457 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Disk identifier: 0xed61aa6f
   Device Boot      Start         End      Blocks   Id  System
/dev/sdb1   *           1       19124   153613498+  fd  Linux raid autodetect
/dev/sdb2           19125       19452     2634660    5  Extended
/dev/sdb5           19125       19452     2634628+  fd  Linux raid autodetect


これでsdbはsdaと同じ構成になりました。
mdadmでraidに追加します。

net:/proc# mdadm --manage /dev/md0 --add /dev/sdb1
mdadm: added /dev/sdb1
net:/proc# mdadm --manage /dev/md1 --add /dev/sdb5
mdadm: added /dev/sdb5


同期状況を確認してみます。

net:/proc# cat mdstat
Personalities : [raid1]
md1 : active raid1 sdb5[2] sda5[0]
      2634560 blocks [2/1] [U_]
        resync=DELAYED
md0 : active raid1 sdb1[2] sda1[0]
      153613376 blocks [2/1] [U_]
      [>....................]  recovery =  1.6% (2509888/153613376) finish=42.3min speed=59406K/sec
unused devices: <none>


md0は同期が始まりましたが、md1はresync=DELAYEDの状態。
md0が終わってからmd1は同期が始まります。

同期が終わるのをひたすら待ちますが、実はこの状態ではsdbからのブートが出来ません。
ブートローダーのGRUBをsdbにインストールしなければなりません。

net:/proc# cat mdstat
Personalities : [raid1]
md1 : active raid1 sdb5[1] sda5[0]
      2634560 blocks [2/2] [UU]
md0 : active raid1 sdb1[1] sda1[0]
      153613376 blocks [2/2] [UU]
unused devices: <none>


同期が終わりました。
sdbからもbootが出来るようにします。

net:/proc# grub ← GRUBシェルモード起動
    GNU GRUB  version 0.97  (640K lower / 3072K upper memory)
[ Minimal BASH-like line editing is supported.  For the first word, TAB
   lists possible command completions.  Anywhere else TAB lists the possible
   completions of a device/filename.]
grub> root (hd1,0) ← sdbをrootにする
Filesystem type is ext2fs, partition type 0xfd
grub> setup (hd1) ← sdbへGRUBインストール
Checking if "/boot/grub/stage1" exists... no
Checking if "/grub/stage1" exists... yes
Checking if "/grub/stage2" exists... yes
Checking if "/grub/e2fs_stage1_5" exists... yes
Running "embed /grub/e2fs_stage1_5 (hd1)"...  15 sectors are embedded.
succeeded
Running "install /grub/stage1 (hd1) (hd1)1+15 p (hd1,0)/grub/stage2
/grub/grub.conf"... succeeded
Done.
grub> quit ← GRUBシェルモード終了


これでsdbにもブートローダーがインストールされました。

sdaが故障してもsdbをsdaの場所に繋ぎなおせばシステムは起動できます。

GRUBのメニューリストを修正してリストから起動ドライブを選択出きる様にするのも可能ですが、今回はこの手法はとりません。


ではでは~☆ミ