自分は、生まれも育ちもWindowsな人間なので、Linuxサーバを使い始めたあとでもしディスク障害なんておきようものなら、絶対に復旧できないと考えた。Windowsならデータのバックアップも再インストールにも慣れてるんだけど、ただでさえよくわかんないLinuxが死んだら困る(ぉ
そこで、Linuxでサーバ立てるならRAID構成にしようとかねてから考えていたわけである。
RAIDとは、複数のディスクで論理的に1つのディスクを構成する技術で、複数のディスクを使うことによってディスクアクセスを高速化したり(たとえば2台のディスクに半分ずつデータを書き込めば、ディスクの性能による書き込み速度の限界は2倍高速になる)、ディスクの信頼性を上げたり(2台のディスクに同じデータを書き込めば、どちらかのディスク装置が故障してもデータが失われない)する技術である。
RAIDにはいくつかの種類があり、主なものとしては以下の4つがある。
複数のディスクにデータを分散して書き込むことにより、ディスクアクセスを高速化する。ストライピングともいう。RAID0を構成するディスク装置のうち、どれか一つでも故障すると全体が使用できなくなるので、耐障害性はディスクを単体で使用するよりも低くなる。
複数のディスクに同じデータを書き込み、ディスクの信頼性を向上させる。ミラーリングともいう。複数のディスクに同じデータを書き込むため、単体使用時よりも書き込み時の処理が重くなるが、読み込み時には複数のディスクからデータを読むことができるので高速化できることもある。2台構成の場合、ディスク2台で1台分の容量しか使えないため、容量対コストはよくない。
ストライピングしたディスクをさらにミラーリングすることで、RAID 0の高速性とRAID 1の信頼性をともに生かす使い方。最小構成でも4台必要だが、その場合でももちろん2台分の容量しか使えない。
複数のディスクにデータを分散書き込みする点はRAID 0と同じだが、最後の1台(または数台)にパリティコードを書き込むことによって、どの装置が故障しても元のデータを復元できるようにしておくやり方。信頼性を向上させる点ではRAID 1と同じだが、n台構成のとき、最大でn-1台分の容量が使用できる(パリティ用ディスクが1台のとき)のでコスト効率がいい。
今回は、メールサーバなどとして今後重要に働いてもらうLinuxマシンに使用するわけなので、RAID 1を構成する。
RAIDを実現する処理をハードウェアで行うか、ソフトウェアで行うかによって2方式がある。ハードウェアRAIDは、OSやアプリケーションの変更を必要とせずにRAIDの恩恵が受けられ、CPUに負荷をかけないというような利点があるが、追加投資が必要になる。逆に、ソフトウェアRAIDには投資を行わないでRAIDを実現できる利点がある一方、設定が面倒であったり、RAID処理のためにCPUに負荷がかかったりする。特に、RAID5のパリティ計算などでは負荷が重くなるらしい。
タイトルにあるとおり、ここではソフトウェアRAIDを使用する。設定は一度行ってしまえばあとは置いておくだけだし、RAIDの構築作業(実際にHDD間の同期を取る作業)を、サーバーを稼動させながらバックグラウンドで行える点がハードウェアRAID(手が届く範囲のもの)にはない魅力だったからである。
今稼動しているシステムを生かしたまま、RAIDを構築し、システムを移植する。方法として、RAID1の縮退モードというものを利用する。片方のドライブにはシステムが稼動していないといけないので、いきなり完全なRAIDを構築するのは不可能だからである。

そこで、まずシステムで使ってないほうのディスク(hdc)に、「RAID1なんだけど、片方のディスクが故障して切り離されてしまった」状態を仮想的に作る。


その後、そちらにシステムを移植して、「不完全なRAID」からシステムが起動する状態に持っていく。そのあとで、改めて今までシステムディスクだったほう(hda)をRAIDに加えて、完全なRAIDを完成させるのである。

今回やりたいのは、RAID上で、しかもReiserFSというファイルシステムを使用することなので、それらをKernelでサポートしていないといけない。それは、前回のカーネル再構築のときに済ませてあるのでここでは割愛する。
Kernelのサポートがあっても、実際に使用するソフトが必要なので、それは別途インストールする必要があるが、RAIDツールもReiserFSツールもDebianパッケージになっているので別に苦労はない。aptでインストールする。
root@host# apt-get install raidtools2 reiserfsprog
rootでcfdiskを実行して、次のようにパーティションを切った。
マウントポイント(予定) 容量(MB) デバイス名
/boot 256 hdc1
/ 512 hdc2
/usr 8192 hdc5
/home 2048 hdc6
/var 1024 hdc7
さらに、すべてのパーティションのタイプを0xfdに設定しておく(重要)。画面上では種別が「Linux raid autodetect」と出るようになった。
/etc/raidtab を、こんな感じで作成。
raiddev /dev/md1
raid-level 1
nr-raid-disks 2
nr-spare-disks 0
chunk-size 32
persistent-superblock 1
device /dev/hdc1
raid-disk 0
device /dev/hda1
failed-disk 1
raiddev /dev/md0
raid-level 1
nr-raid-disks 2
nr-spare-disks 0
chunk-size 32
persistent-superblock 1
device /dev/hdc2
raid-disk 0
device /dev/hda2
failed-disk 1
raiddev /dev/md2
raid-level 1
nr-raid-disks 2
nr-spare-disks 0
chunk-size 32
persistent-superblock 1
device /dev/hdc5
raid-disk 0
device /dev/hda5
failed-disk 1
raiddev /dev/md3
raid-level 1
nr-raid-disks 2
nr-spare-disks 0
chunk-size 32
persistent-superblock 1
device /dev/hdc6
raid-disk 0
device /dev/hda6
failed-disk 1
raiddev /dev/md4
raid-level 1
nr-raid-disks 2
nr-spare-disks 0
chunk-size 32
persistent-superblock 1
device /dev/hdc7
raid-disk 0
device /dev/hda7
failed-disk 1
raidアレイの構築
root@host# mkraid /dev/md0
root@host# mkraid /dev/md1
root@host# mkraid /dev/md2
root@host# mkraid /dev/md3
root@host# mkraid /dev/md4
そしてフォーマット
root@host# mke2fs /dev/md1
root@host# mkreiserfs /dev/md0
root@host# mkreiserfs /dev/md2
root@host# mkreiserfs /dev/md3
root@host# mkreiserfs /dev/md4
今にして思えば別に必要はなかったが、とりあえず再起動してRAIDアレイがうまく動作するか調べた。どう調べたかというと、/proc/mdstat の中身を確認し、すべてのデバイスがactiveかどうか見ることである。
いま /dev/hda* 上にあるファイルを、そっくり /dev/md* にコピーしたうえで、RAIDデバイス上のシステムが起動するようにブートローダ(ここでは、lilo)の設定を行う。
出来るだけ起動しているプロセスが少ないほうがいいと思い、シングルユーザーモードで作業をすることにした。もう一度再起動し、liloの画面のところで
boot: linux single
と入力する。しばらくするとrootのパスワードを聞かれ、シングルユーザーモードで起動できる。
コピー先のRAIDアレイをマウント
root@host# mkdir /mnt/raid
root@host# mount /dev/md0 /mnt/raid
root@host# mkdir /mnt/raid/boot /mnt/raid/usr /mnt/raid/home /mnt/raid/var
root@host# mount /dev/md1 /mnt/raid/boot
root@host# mount /dev/md2 /mnt/raid/usr
root@host# mount /dev/md3 /mnt/raid/home
root@host# mount /dev/md4 /mnt/raid/var
ざっくりファイルをコピーする
root@host# cd /
root@host# cp -a /bin /mnt/raid/
root@host# cp -a /dev /mnt/raid/
root@host# cp -a /sbin /mnt/raid/
(その他、 /cdrom /floppy /mnt /proc 以外のディレクトリをすべてコピーする)
マウントポイントを作成
root@host# mkdir /mnt/raid/cdrom /mnt/raid/floppy /mnt/raid/mnt /mnt/raid/proc
起動したシステムがRAID領域をマウントするように /mnt/raid/etc/fstab を編集する。
/dev/md0 / reiserfs defaults 0 0
/dev/md1 /boot ext2 defaults 1 1
/dev/md2 /usr reiserfs defaults 0 0
/dev/md3 /home reiserfs defaults 0 0
/dev/md4 /var reiserfs defaults 0 0
(後略)
ミラーリンク構成では、どちらかのHDDが故障しても起動もうまくいかないと困る。そこで、1台目と2台目の両方のMBR(マスターブートレコード)に起動に関する情報を格納しておき、また、万一に備えて1台目のHDDによる起動メニューから2台目のHDDの起動メニューが呼び出せるようにしておく。
ということで、まず1台目のHDDのメニューから2台目のHDDが呼べるように、以下の設定を /etc/lilo.conf に追加した。
other=/dev/hdc
label=Secondary
lilo.confを変更したら、忘れずにMBRに情報を登録する。
root@host# lilo -v
これで、1台目のHDDから表示されるメニューに、2台目のHDDを呼ぶ項目が追加されるはず。次に、2台目のHDDには、RAIDを認識してシステムを起動するための設定が必要である。fdiskでドライブの情報を調べて、
root@host# fdisk -ul /dev/hdc
Disk /dev/hdc: 16 heads, 63 sectors, 77557 cylinders
表示されたパラメータを使って /mnt/raid/etc/lilo.conf.hdc を作成する。
lba32
disk=/dev/md0
bios=0x81
sectors=63
heads=16
cylinders=77557
partition=/dev/md1
start=63
boot=/dev/hdc
install=/boot/boot-menu.b
map=/boot/map
prompt
timeout=50
vga=normal
default=Linux
image=/boot/vmlinuz
label=Linux
read-only
root=/dev/md0
こちらも、忘れずにMBRに情報を登録する。
root@host# lilo -v -C /mnt/raid/etc/lilo.conf.hdc
アンマウントし、RAIDアレイを止めて再起動してみる。
root@host# umount /mnt/raid/boot
root@host# umount /mnt/raid/usr
root@host# umount /mnt/raid/home
root@host# umount /mnt/raid/var
root@host# umount /mnt/raid
root@host# raidstop /dev/md0
root@host# raidstop /dev/md1
root@host# raidstop /dev/md2
root@host# raidstop /dev/md3
root@host# raidstop /dev/md4
root@host# shutdown -r now
この時点での/dev/hdcの状態は以下のとおり。
hdc1 Primary Linux raid autodetect 255.99
hdc2 Primary Linux raid autodetect 511.97
hdc5 Logical Linux raid autodetect 8192.00
hdc6 Logical Linux raid autodetect 2047.87
hdc7 Logical Linux raid autodetect 1023.94
再起動して、追加された「Secondary」から起動できるかどうかテスト。できなければ通常起動して問題を解決する必要がある。
無事にRAIDで起動したら、続きへ。まだこの時点ではRAIDの意味がないので、/dev/hdaのパーティションを切りなおしてちゃんとしたRAID1アレイにしよう。
/dev/hda2にはスワップパーティションがあるので、まずスワップを解除する。
root@host# swapoff -a -v
このあと、cfdiskを使ってパーティションを切りなおしたのだが、容量を入力するときにまったく同じ数値(たとえば、/dev/hda1なら"256")を入力しても厳密には同じ容量にならなかったので、ちょっとずつ大きめのサイズにして確保した。大きくしないと既存のRAIDアレイに参加させることは出来ない。
切った結果は以下のとおり。領域が一つ多いのはswap用にするため。以前はRAID領域にswapを置くと、「メモリが足りなくなる」→「swap確保命令が発動」→「RAID処理のためメモリ要求」→「さらにメモリ不足」という悪循環が起きて大変だった(というか、RAIDにswap置くのは不可だった)らしいが、最近のやつは改善されているらしいので気にせずRAID上swapなシステムにした。気になる人は、本当に大丈夫か調べたほうがいいと思う。
hda1 Primary Linux raid autodetect 263.21
hda2 Primary Linux raid autodetect 518.20
hda5 Logical Linux raid autodetect 8200.61
hda6 Logical Linux raid autodetect 2048.10
hda7 Logical Linux raid autodetect 1028.16
hda8 Logical Linux raid autodetect 863.66
ここで、ついでに /dev/hdc の残り容量を切りなおしてswap用の領域を作成しておきたいところだが、いま /dev/hdc のパーティションテーブルを操作してはいけない。RAIDに参加しているパーティションが含まれているディスクにそんなことをするとデータが破壊されてしまうのである。
ていうわけで後回し。
次に、/etc/raidtab を編集。failed-disk のところを raid-disk に変更する。また、swap用の /dev/md5 の設定を追加する。以下は追加部分だけ。
# swap
raiddev /dev/md5
raid-level 1
nr-raid-disks 2
nr-spare-disks 0
persistent-superblock 1
chunk-size 32
device /dev/hda8
raid-disk 0
device /dev/hdc8
failed-disk 1
swap領域については、まだ /dev/hdc8 を切っていないので、おなじみの failed-disk である。
設定ファイルを保存したら、早速ディスクをRAIDアレイに追加する。再構築はすべてバックグラウンドで行われるし、再構築中にRAIDアレイに対して読み書きすることも可能。つまり、RAID再構築中でも普通に使えるし、待っていれば勝手に2重化が完了するということ。
root@host# raidhotadd /dev/md0 /dev/hda2
/proc/mdstat を見ると、再構築の様子が見える
root@host# cat /proc/mdstat
md0 : active raid1 hda2[2] hdc2[0]
499904 blocks [2/1] [U_]
[===>.................] recovery = 15.9% (80192/499904) finish=0.6min speed=11456K/sec
同じように、他のRAIDアレイも再構築する
root@host# raidhotadd /dev/md1 /dev/hda1
root@host# raidhotadd /dev/md2 /dev/hda5
root@host# raidhotadd /dev/md3 /dev/hda6
root@host# raidhotadd /dev/md4 /dev/hda7
そして、swap用のRAIDアレイを作成
root@host# mkraid /dev/md5
/etc/fstabを修正。swap領域を /dev/hda2 から /dev/md5 に変更する。
そして、スワップを有効にする。ところが…
root@host# swapon -a -v
swapon on /dev/md5
swapon: /dev/md5: Invalid argument
と怒られたので調べると、スワップ領域も初期化が必要ならしいことがわかった。
root@host# mkswap /dev/md5
として、再度 swapon を実行すると今度はうまくいった。
しばらく /proc/mdstat の様子を見る。さすがに8GB割り当てた /usr のアレイの再構築にはそこそこ時間がかかっていたようだが、ものの数十分でアレイの再構築がすべて終わった。
すべての作業が完了したのを見計らって、/etc/lilo.conf.hda を作成。/etc/lilo.conf.hdc をコピーして、ディスクのパラメータ部分と、boot=/dev/hdc のところを boot=/dev/hda とを、それぞれ書き換えて、2台目のHDDメニューを呼び出す記述を書き加えればよい。
root@host# lilo -v -C /etc/lilo.conf.hda
これで1台目のHDDからもRAIDで起動できるはず。ここでもう一回再起動して、うまく起動できるかどうか調べる。出来なければ2台目から起動して直す。
もはやRAIDの大部分が完成してしまっているので、それぞれのHDDのパーティションを切りなおすことは出来ない。やった瞬間にデータが死ぬ。そこで、レスキューフロッピーから起動して作業をする。
/dev/hda8 よりもちょっと大きめに /dev/hdc8 を切る。
またHDDから起動して、/etc/raidtab を書き換え(swap用の /dev/md5 の failed-disk を raid-disk に書き換えた)、hotaddする。
root@host# raidhotadd /dev/md5 /dev/hdc8
しばらく待てば完了。
/dev/hda8 を切ったついでに、残りの領域に /dev/hdc9 を切っておいたので、それも使えるようにする。とりあえずは公開用の領域という位置づけという意味で /home/pub にわり当てることにした。
root@host# mkreiserfs /dev/hdc9
root@host# mkdir /home/pub
root@host# mount /dev/hdc9 /home/pub
次回以降は自動的にマウントされるように、/etc/fstab を編集して
/dev/hdc9 /home/pub reiserfs defaults 0 0
という行を追加し、システムのディスク構成がようやく終わった。
再起動しても無事にRAIDを認識して起動するのを見るのは気分がいいものである。