勝手訳

今回の復旧作業で手順がまとまっていて、非常に役立った記事を勝手訳。原題は”Recovery of RAID and LVM2 Volumes”

RAIDとLogical Volume Managersは素晴らしい、データを失うまでは。

最近のLinuxOSで提供されるLinuxのソフトウェアRAID(Redundant Array of Inexpensive Disks)とLVM2(Logical Volume Manager, version 2)の組み合わせは、強固さと柔軟性を実現するが、複雑さという犠牲を払って、ソフトウェアRAIDとLVM2のパーティションでフォーマットされたドライブからデータを復旧する必要がある。これが実は非常に難しいことだと痛感したのは、最近、異なるコンピュータのRAIDとLVM2で作成されたシステムディスクをマウントしようとしてみたからだ。まず、ディスク上のファイルシステムを読もうとしたところ、いらいらする結果に終わった。

まず試みたのは、2台のハードディスクを、スモール・フォーム・ファクタ(訳注:小さなデスクトップPC)、元々1台のハードディスクしか搭載できない設計のマシンに突っ込んでミラーされたRAID 1のボリュームとして走らせた(このシステムを便宜上raidboxと呼ぶ)。この試みは全然だめだった。数時間動かしたところ、熱暴走で自動的に電源が落ちた。システムを分離して1台のディスクだけで再インストールを開始したのは、復旧したい古いRAIDボリュームにいくつかのファイルが存在することに気づいた時だった。

もしシステムがRAIDやLVM2を用いてなければ、データの復旧は簡単なはずだった。手順としては、古いドライブを別のコンピュータに接続し、ファイルシステムをマウント、壊れたボリュームからファイルをコピーするだけだ。私もまずはその方法をやってみた。私がrecoveryboxと呼ぶコンピュータを使ったが、失敗に終わった。

なぜそんなに難しいのか?

データにたどり着くのが難しいことは証明された。理由は2つあって、データがRAIDデバイスに隠れている論理ボリューム上にあることと、RAIDデバイスのボリュームグループは復旧用のシステム上のボリュームグループと同じ名前を持っていることだ。

普及している最近のOS(例えば、Red Hat Enterprise Linux 4やCentOS 4、Fedora Core 4など)は、インストール時に自動的にディスクパーティションを作成できる。その際には、rootデバイス用にLVMを利用したパーティションが割り当てられる。通常、VolGroup00というボリュームグループを作成され、2つの論理ボリューム、LogVol00とLogVol01からなる。前者はrootディレクトリとして、後者はswapとなる。リスト1を参照してほしい。

リスト1.典型的なLVMのディスク設定

[root@recoverybox ~]# /sbin/sfdisk -l /dev/hda
Disk /dev/hda: 39560 cylinders, 16 heads, 63 sectors/track
Warning: The partition table looks like it was made
  for C/H/S=*/255/63 (instead of 39560/16/63).
For this listing I'll assume that geometry.
Units = cylinders of 8225280 bytes, blocks of 1024 bytes, counting from 0
   Device Boot Start     End   #cyls    #blocks   Id  System
/dev/hda1   *      0+     12      13-    104391   83  Linux
/dev/hda2         13    2481    2469   19832242+  8e  Linux LVM
/dev/hda3          0       -       0          0    0  Empty
/dev/hda4          0       -       0          0    0  Empty
[root@recoverybox ~]# /sbin/pvscan
  PV /dev/hda2   VG VolGroup00   lvm2 [18.91 GB / 32.00 MB free]
  Total: 1 [18.91 GB] / in use: 1 [18.91 GB] / in no VG: 0 [0   ]
[root@recoverybox ~]# /usr/sbin/lvscan
  ACTIVE            '/dev/VolGroup00/LogVol00' [18.38 GB] inherit
  ACTIVE            '/dev/VolGroup00/LogVol01' [512.00 MB] inherit

元々の設定では、ソフトウェアRAIDデバイスは3つのRAID 1デバイス、md0、md1、md2で構成されていて、それぞれ、/boot、swap、/となっていた。LVM2のボリュームグループは最大の容量のRAIDデバイス、md2にあり、VolGroup00という名前だった。その時はこれは良い考えだと思っていた。つまり、このパーティションの設定が意味するのは、Linuxディストリビューションがデフォルトで行うものと同じように見えるからだ。リスト2にソフトウェアRAIDアレイが、ちゃんと動いている間はどう見えていたかを示している。

リスト2.ソフトウェアRAIDのディスク設定

[root@raidbox ~]# /sbin/sfdisk -l /dev/hda
Disk /dev/hda: 9729 cylinders, 255 heads, 63 sectors/track
Units = cylinders of 8225280 bytes, blocks of 1024 bytes, counting from 0
   Device Boot Start     End   #cyls    #blocks   Id  System
/dev/hda1   *      0+     12      13-    104391   fd  Linux raid
autodetect
/dev/hda2         13      77      65     522112+  fd  Linux raid
autodetect
/dev/hda3         78    9728    9651   77521657+  fd  Linux raid
autodetect
/dev/hda4          0       -       0          0    0  Empty
[root@raidbox ~]# cat /proc/mdstat
Personalities : [raid1]
md2 : active raid1 hdc3[1] hda3[1]
      77521536 blocks [2/2] [UU]
md1 : active raid1 hdc2[1] hda2[1]
      522048 blocks [2/2] [UU]
md0 : active raid1 hdc1[1] hda1[1]
      104320 blocks [2/2] [UU]

もし、2つのボリュームグループに同じ名前を付けると、ちょっとした拍子に、同じ問題に直面することになるだろう。名前が衝突することは非常にあり得ることで、不幸にも、OSがデフォルトでプライマリボリュームグループの名前とするのもVolGroup00だからだ。

RAIDアレイのメンバーにアクセスできるように直す

復旧の最初にすることは、ドライブを別のマシンに移すことだ。これは非常に簡単で、USB2のハードディスクのケースに入れれば良い。復旧用のコンピュータにつなげば、SCSIのハードディスクデバイス、例えば/dev/sdaとして見えるようになるはずだ。この方法なら、元々のコンピュータからハードウェアを移植しようとする間に、復旧するマシンにダメージを与える危険性を減らすことが出来る。

次のチャレンジは、RAIDの設定を認識させ、その中にある論理ボリュームにアクセスできるようにすることだ。sfdisk -l /dev/sdaコマンドで古いドライブ上にパーティションがまだあることをチェックできる。

RAIDの設定を認識させるには、mdadmコマンドを使ってRAIDボリュームのUUIDをドライブから探し出すことになる。リスト3を参照。

リスト3.RAIDアレイのメンバをディスクから探し出す

[root@recoverybox ~]# mdadm --examine --scan  /dev/sda1 /dev/sda2 /dev/sda3
ARRAY /dev/md2 level=raid1 num-devices=2 
 UUID=532502de:90e44fb0:242f485f:f02a2565
   devices=/dev/sda3
ARRAY /dev/md1 level=raid1 num-devices=2 
 UUID=75fa22aa:9a11bcad:b42ed14a:b5f8da3c
   devices=/dev/sda2
ARRAY /dev/md0 level=raid1 num-devices=2 
 UUID=b3cd99e7:d02be486:b0ea429a:e18ccf65
   devices=/dev/sda1

このフォーマットは、mdadmツールが使う/etc/mdadm.confファイルに非常によく似ている。mdadmの出力をファイルにリダイレクトし、device行をARRAY行の上にくっつけて、RAID 1の設定を得るために存在しない2つ目のデバイスに入れる必要がある。degradedモードのmdアレイが見えれば、データの復旧が可能だ:

[root@recoverybox ~]# mdadm --examine --scan  /dev/sda1 
 /dev/sda2 /dev/sda3 >> /etc/mdadm.conf
[root@recoverybox ~]# vi /etc/mdadm.conf

/etc/mdadm.conを編集するのは、ARRAYステートメントと同じように、デバイスの状態が同じ行にあるようにするためだ。リスト4を参照。”missing”デバイスをそれぞれのアレイメンバーのdevicesエントリーに加えて、アレイごとに2つのデバイスを持つRAID 1となるようにする。もし、復旧するコンピュータの/etc/mdadm.confに、既にmdのdevicesとARRAYステートメントがあるなら、mdエントリーに番号を振り直し忘れてはいけない。

リスト4./etc/mdadm.conf

DEVICE partitions
ARRAY /dev/md0 level=raid1 num-devices=2 
 UUID=b3cd99e7:d02be486:b0ea429a:e18ccf65 
 devices=/dev/sda1,missing
ARRAY /dev/md1 level=raid1 num-devices=2 
 UUID=75fa22aa:9a11bcad:b42ed14a:b5f8da3c 
 devices=/dev/sda2,missing
ARRAY /dev/md2 level=raid1 num-devices=2 
 UUID=532502de:90e44fb0:242f485f:f02a2565 
 devices=/dev/sda3,missing

ここまでやったら、新しいmdデバイスを、mdadm -A -sコマンドでアクティブにし、/proc/mdstatをチェックしてRAIDアレイがアクティブであることを確かめる。リスト5に、RAIDアレイがどのように見えるかを示した。

リスト5.RAIDアレイをアクティブにし直す

[root@recoverybox ~]# mdadm -A -s
[root@recoverybox ~]# cat /proc/mdstat
Personalities : [raid1]
md2 : active raid1 sda3[1]
      77521536 blocks [2/1] [_U]
md1 : active raid1 sda2[1]
      522048 blocks [2/1] [_U]
md0 : active raid1 sda1[1]
      104320 blocks [2/1] [_U]
unused devices: <none>

もしmdデバイスが/proc/mdstatに見えて、すべてうまくいっているなら、引き続き、LVMボリュームを再度マウントできるはずだ。

LVM2ボリュームを復旧して名前を変更する

次のハードルはシステムがlvm2ディスクのセットを2つ持っていることだ。普通は、vgchange -a yコマンドでLVM2に新しいボリュームグループを認識させられるだろうが、もし全く同じボリュームグループ名を含む複数のデバイスがあると、うまくいかない。vgchange -a yを実行すると、VolGroup00が不一致だと返ってきて、RAIDデバイス上のVolGroup00は見えないままだろう。直すには、システム上にまさにマウントしようとしているボリュームグループの名前を変更する必要があり、lvmの設定ファイルを手でいじらないとならない。

raidboxの/etcにあるファイルをバックアップしていれば、/etc/lvm/backup/VolGroup00ファイルのコピーを編集でき、結果的にVolGroup01やRestoreVGや任意の名前を復旧しようとしているシステムで使えるようになるが、ファイルそのものを編集しないとその中にあるボリュームグループの名前を変更出来ないことは確実だ。

もし、バックアップがなければ、LVM2のバックアップファイルと同じものを再生することが出来る。ディスクにあるLVM2のヘッダを調べて、バイナリのゴミを取り除けば良い。LVM2は一般にメタデータによる設定のコピーをディスクの初めのあたりに保持していて、ディスクの先頭1セクタ=パーティションテーブルに続く255セクタにある。この点については/etc/lvm/lvm.confとlvm.confのmanを見れば詳細が分かる。それぞれのディスクのセクタは通常512バイトなので、この領域を読み取ると128KBのファイルが作り出される。LVM2はパーティションそのものの最初の128KBに保持している設定とはことなるテキスト形式で保持している可能性がある。以下のように通常のファイルとして抽出し、ファイルを編集する:

dd if=/dev/md2 bs=512 count=255 skip=1 of=/tmp/md2-raw-start
vi /tmp/md2-raw-start

わけの分からないバイナリがみえるかもしれないが、プレインテキストのいくつかも見てとれるはずだ。LVMはメタデータの領域をリングバッファとして扱うので、結果的にディスクには複数の設定エントリーがあるかもしれない。私のディスクでは、最初のエントリーには物理ボリュームとボリュームグループの詳細しかなく、次のエントリーには論理ボリュームの情報が含まれていた。最も新しいタイムスタンプのあるテキストブロックを探して、LVMの定義を含むプレインテキストブロック以外を消去する。ここには論理ボリュームの情報を含むボリュームグループの定義がある。物理デバイスの定義を修正する必要があるかもしれない。ディスク上ではテキストエントリーはきちんとフォーマットされていない、あるいは通常のバックアップファイルと順番が異なるかもしれないが、そういうものだ。整形した設定をVolGroup01として保存する。リスト6のようなものだ。

リスト6.修正したボリュームグループの設定ファイル

VolGroup01 {
id = "xQZqTG-V4wn-DLeQ-bJ0J-GEHB-4teF-A4PPBv"
seqno = 1
status = ["RESIZEABLE", "READ", "WRITE"]
extent_size = 65536
max_lv = 0
max_pv = 0
physical_volumes {
pv0 {
id = "tRACEy-cstP-kk18-zQFZ-ErG5-QAIV-YqHItA"
device = "/dev/md2"
status = ["ALLOCATABLE"]
pe_start = 384
pe_count = 2365
}
}
# Generated by LVM2: Sun Feb  5 22:57:19 2006

ボリュームグループの設定ファイルが手に入れば、ボリュームグループをvgcfgrestoreコマンドでリスト7のようにシステムに取り込める。

リスト7.復旧したLVM2ボリュームをアクティブにする

[root@recoverybox ~]# vgcfgrestore -f VolGroup01 VolGroup01
[root@recoverybox ~]# vgscan
  Reading all physical volumes.  This may take a while...
  Found volume group "VolGroup01" using metadata type lvm2
  Found volume group "VolGroup00" using metadata type lvm2
[root@recoverybox ~]# pvscan
  PV /dev/md2    VG VolGroup01   lvm2 [73.91 GB / 32.00 MB free]
  PV /dev/hda2   VG VolGroup00   lvm2 [18.91 GB / 32.00 MB free]
  Total: 2 [92.81 GB] / in use: 2 [92.81 GB] / in no VG: 0 [0   ]
[root@recoverybox ~]# vgchange VolGroup01 -a y
  1 logical volume(s) in volume group "VolGroup01" now active
[root@recoverybox ~]# lvscan
  ACTIVE            '/dev/VolGroup01/LogVol00' [73.88 GB] inherit
  ACTIVE            '/dev/VolGroup00/LogVol00' [18.38 GB] inherit
  ACTIVE            '/dev/VolGroup00/LogVol01' [512.00 MB] inherit

この時点で、古いボリュームを新しいシステムにマウントでき、その中にあるファイルにもアクセスできるはずだ。リスト8を参照。

リスト8.復旧したボリュームをマウントする

[root@recoverybox ~]# mount /dev/VolGroup01/LogVol00 /mnt
[root@recoverybox ~]# df -h
Filesystem            Size  Used Avail Use% Mounted on
/dev/mapper/VolGroup00-LogVol00
                       19G  4.7G   13G  28% /
/dev/hda1              99M   12M   82M  13% /boot
none                  126M     0  126M   0% /dev/shm
/dev/mapper/VolGroup01-LogVol00
                       73G  2.5G   67G   4% /mnt
# ls -l /mnt
total 200
drwxr-xr-x   2 root root  4096 Feb  6 02:36 bin
drwxr-xr-x   2 root root  4096 Feb  5 18:03 boot
drwxr-xr-x   4 root root  4096 Feb  5 18:03 dev
drwxr-xr-x  79 root root 12288 Feb  6 23:54 etc
drwxr-xr-x   3 root root  4096 Feb  6 01:11 home
drwxr-xr-x   2 root root  4096 Feb 21  2005 initrd
drwxr-xr-x  11 root root  4096 Feb  6 02:36 lib
drwx------   2 root root 16384 Feb  5 17:59 lost+found
drwxr-xr-x   3 root root  4096 Feb  6 22:12 media
drwxr-xr-x   2 root root  4096 Oct  7 09:03 misc
drwxr-xr-x   2 root root  4096 Feb 21  2005 mnt
drwxr-xr-x   2 root root  4096 Feb 21  2005 opt
drwxr-xr-x   2 root root  4096 Feb  5 18:03 proc
drwxr-x---   5 root root  4096 Feb  7 00:19 root
drwxr-xr-x   2 root root 12288 Feb  6 22:37 sbin
drwxr-xr-x   2 root root  4096 Feb  5 23:04 selinux
drwxr-xr-x   2 root root  4096 Feb 21  2005 srv
drwxr-xr-x   2 root root  4096 Feb  5 18:03 sys
drwxr-xr-x   3 root root  4096 Feb  6 00:22 tftpboot
drwxrwxrwt   5 root root  4096 Feb  7 00:21 tmp
drwxr-xr-x  15 root root  4096 Feb  6 22:33 usr
drwxr-xr-x  20 root root  4096 Feb  5 23:15 var

これで、データにアクセスできるようになったが、最後に用心のためにボリュームグループの情報をvgcgfbackupコマンドでバックアップする。リスト9を参照。

リスト9.復旧したボリュームグループの設定をバックアップする

[root@teapot-new ~]# vgcfgbackup
Volume group "VolGroup01" successfully backed up.
Volume group "VolGroup00" successfully backed up.
[root@teapot-new ~]# ls -l /etc/lvm/backup/
total 24
-rw-------  1 root root 1350 Feb 10 09:09 VolGroup00
-rw-------  1 root root 1051 Feb 10 09:09 VolGroup01

結論

LVM2とLinuxのソフトウェアRAIDは、経済的で信頼性の高いストレージソリューションを一般的なハードウェアで実現できる。トレードオフの1つは不具合から復旧する手順が明確でないことだ。古いボリュームグループ情報をディスクから直接復旧できる信頼性の高いツールがあれば、復旧作業はより簡単になるはずだ。幸運なことに、LVM2システムの設計者が賢明だったので、プレインテキストの設定のバックアップコピーをディスクそのものに保持されている。ちょっとした努力と調査をすれば、私は無くなったと思った論理ボリュームにアクセスできるようになった。あなたのLVM2とRAIDのインストールが成功しますように。