2011-08-26

Linux (Ubuntu 11.04)で2TB超のHDをソフトウェアRAID化する (4)

(承前)

sdaをRAIDに参加させる

無事に/dev/md0からブートできただろうか?この時点でsdaは最早使われていない。あとはこのsdaを片肺飛行しているRAIDに加えればおしまいだ。まずsdaのパーティションのraidフラグを立てる。

$ sudo parted /dev/sda
(parted) toggle 2 raid
(parted) toggle 3 raid
(parted) toggle 4 raid
(parted) quit

さていよいよRAIDにsdaを参加させる。

$ sudo mdadm --add /dev/md0 /dev/sda2
$ sudo mdadm --add /dev/md1 /dev/sda3
$ sudo mdadm --add /dev/md2 /dev/sda4

これにより、参加させたsdaの同期が始まる。同期の様子を見るには以下のようにする。

$ watch cat /proc/mdstat

同期が終わったら再起動でもしておく。

$ sudo reboot

この時点では、以前に作った/etc/grub.d/09_raidによるgrubエントリの生成は必要がなくなっている。update-grubによってちゃんと作られるからだ。/etc/grub.d/09_raidを用意した時点ではsdaがマウントされている状態でmd0のブート用のエントリを作ろうとしたのに対し、いまはmd0がマウントされている状態でmd0のブート用のエントリを作ろうとしているからである。ついでにupgradeも行おう。

$ sudo apt-get update
$ sudo apt-get upgrade
$ sudo rm /etc/grub.d/09_raid
$ sudo update-grub
$ sudo update-initramfs -u
$ sudo grub-install /dev/sda
$ sudo grub-install /dev/sdb
$ sudo reboot

以上でゴールが実現できた。

References

検索するといっぱい出てくるが、どれも試すとなかなか最後まで行かない。最も近いところまで行き、内容も参考になったのが以下のページ(英語): [How To Set Up Software RAID1 On A Running System (Incl. GRUB2 Configuration) (Ubuntu 10.04) | HowtoForge - Linux Howtos and Tutorials]

GPTと2048セクタへのアラインについては以下のページが参考になった: [LinuxMania: RAIDボリュームからのブートとパーティション]

その他、以下のページ群から情報をつなぎ合わせて問題が解決した: [Linuxでmdadmを使ったソフトウェアRAIDの構築・管理メモ - nabeの雑記帳], [RAID1 on etch | qos webmaster's blog], [Ubuntu を BeyondRAID 環境へ移行する (1/2) - nigakyのメモ帳]

2011-08-25

Linux (Ubuntu 11.04)で2TB超のHDをソフトウェアRAID化する (3)

(承前)

sdbにRAID 1を構成

ソフトウェアRAIDの構築はmdadmコマンドを用いて行う。ログインしてからターミナルを開いてmdadmをインストールする。

$ sudo apt-get update
$ sudo apt-get install mdadm

依存関係によりpostfixがインストールされて何か質問されるので適当に答えておく。

RAID 1というのは2つのHDのうち1つが壊れても大丈夫というものだ。では実際に壊れたときにはどうすればいいのか?新しいHDを挿した状態でmdadmを実行できればいいのだ。このmdadmの実行をDVDでのレスキュー起動で行ってもよいが、1個のHDが壊れた状態でも起動できるようにすればもっと楽である。デフォルトでは壊れた状態では起動できなくなっている(これは壊れて起動した状態でもう1個が壊れると悲惨な状況になるからである)のでこれを修正する。

$ sudo vi /etc/initramfs-tools/conf.d/mdadm
BOOT_DEGRADED=true
$ sudo reboot

再起動後、sdbをsdaと全く同じようにパーティション分けする。

$ sudo parted /dev/sdb
(parted) mktable gpt
(parted) mkpart _ 1mib 2mib
(parted) toggle 1 bios_grub
(parted) mkpart _ 2mib 1gib
(parted) mkpart _ 1gib 3gib
(parted) mkpart _ 32gib 48gib

RAIDにするためにはパーティションのraidフラグを立てる必要がある。

(parted) toggle 2 raid
(parted) toggle 3 raid
(parted) toggle 4 raid
(parted) quit

いよいよRAID 1の作成だ。

$ sudo mdadm --create /dev/md0 --level=1 -n 2 --metadata=0.9 missing /dev/sdb2
$ sudo mdadm --create /dev/md1 --level=1 -n 2 --metadata=0.9 missing /dev/sdb3
$ sudo mdadm --create /dev/md2 --level=1 -n 2 --metadata=0.9 missing /dev/sdb4

ここで--metadataによってメタデータのフォーマットを0.9にしている点に注意してほしい。--metadataを省略すると1.2になるのだが、これでは後々問題が起こる。先回りして言うと、1.2でもほぼ問題なく最終段階まで設定が成功するのだが、apt-get upgradeでカーネルのアップデートが起こるとそれが失敗してしまうと言う致命的な問題が起こる。これはカーネルアップデートの際に実行されるupdate-grubが1.2フォーマットのメタデータを読めないために生じる問題である。ここでメタデータのフォーマットとして0.9を指定しなければならないというのを発見するのにはかなり苦労した。世のページでのソフトウェアRAIDの説明では古いバージョンのmdadmが使われており、その場合メタデータのフォーマット0.9がデフォルトとなるのでうまくいっていたのだ。

ソフトウェアRAIDの状況を確認しておく。

$ cat /proc/mdstat
Personalities : [linear] [multipath] [raid0] [raid1] [raid6] [raid5] [raid4] [raid10]
md2 : active raid1 sdb4[1]
      16777152 blocks [2/1] [_U]
      
md1 : active raid1 sdb3[1]
      2097088 blocks [2/1] [_U]
      
md0 : active raid1 sdb2[1]
      1046464 blocks [2/1] [_U]
      
unused devices:

パーティションをフォーマットする。

$ sudo mkfs -t ext4 /dev/md0
$ sudo mkfs -t ext4 /dev/md2
$ sudo mkswap /dev/md1

ソフトウェアRAIDの設定を保存する。

$ sudo mdadm --detail --scan | sudo tee -a /etc/mdadm/mdadm.conf
ARRAY /dev/md0 metadata=0.90 UUID=5f156622:2c294f4b:21de336c:78d7ee00
ARRAY /dev/md1 metadata=0.90 UUID=4e48e1ac:30d9556c:21de336c:78d7ee00
ARRAY /dev/md2 metadata=0.90 UUID=c9e99e19:4bd9a5d8:21de336c:78d7ee00

最近のLinuxでは、このまま再起動すると/dev/md0などの名前が変わってしまうので、初期ラムディスクの作り直しが必要である。

$ sudo update-initramfs -u
$ sudo reboot

再起動して/dev/md0などが存在することを確認する。

/dev/md0からブートできるように設定

fstabを編集して/dev/md?を用いてファイルシステムを組織するように設定する。blkidによって取得したUUIDを用いて/etc/fstabを書き換える。

$ sudo blkid /dev/md[012] | tee /tmp/uuid
/dev/md0: UUID="f45a96a8-8bcf-4a51-9cbe-76c2583ddd5d" TYPE="ext4"
/dev/md1: UUID="1e6eb27a-18d7-4735-9d78-f12c22be17eb" TYPE="swap"
/dev/md2: UUID="a0965d65-1de0-4876-8108-63ef9fe8e568" TYPE="ext4"
$ sudo vi /etc/fstab
UUID=a0965d65-1de0-4876-8108-63ef9fe8e568 /               ext4    noatime,user_xattr,errors=remount-ro  0  1
UUID=f45a96a8-8bcf-4a51-9cbe-76c2583ddd5d /boot           ext4    noatime,user_xattr  0   2
UUID=1e6eb27a-18d7-4735-9d78-f12c22be17eb none            swap    sw              0       0

次に/dev/md0からブートするようにgrubを設定する。

$ cd /etc/grub.d
$ sudo cp 40_custom 09_raid
$ sudo vi 09_raid
#!/bin/sh
exec tail -n +3 $0
# This file provides an easy way to add custom menu entries.  Simply type the
# menu entries you want to add after this comment.  Be careful not to change
# the 'exec tail' line above.
menuentry 'Ubuntu, with Linux 2.6.38-8-generic' --class ubuntu --class gnu-linux --class gnu --class os {
    recordfail
    insmod part_gpt
    insmod raid
    insmod mdraid09
    insmod ext2
    set root='(md0)'
    linux   /vmlinuz-2.6.38-8-generic root=UUID=a0965d65-1de0-4876-8108-63ef9fe8e568 ro   quiet splash vt.handoff=7
    initrd  /initrd.img-2.6.38-8-generic
}
$ sudo update-grub

09_raidファイルの内容は、/boot/grub/grub.cfgからコピーしてきたmenuentryをペーストして変更するとよいだろう。linux行のUUIDにはもちろん先ほどblkidで取得したrootパーティション/dev/md2のものを設定する。

ここの設定も正しいものを探り出すのに大変苦労した。まず、世のページではinsmod mdraidになっているものが多いが、メタデータのフォーマットによってmdraid1xmdraid09を使い分けなければならない。次に大苦労したのが(md0)という表現である。世のページでは(md/0)というのまで出てきて誤植かとも思ったのだが、実はメタデータが1.xのとき(md/0)で、0.9のとき(md0)を使うのだ!そんなことどこに書いてあるんだ!!

初期ラムディスクの再生成を忘れないように。

$ sudo update-initramfs -u

sdaからsdbへのコピー

rsyncの-xオプション(ファイルシステムの境界を越えない指定)を用いてコピーする。

$ sudo mkdir /mnt/md0 /mnt/md2
$ sudo mount /dev/md0 /mnt/md0
$ sudo mount /dev/md2 /mnt/md2
$ sudo rsync -ax / /mnt/md2
$ sudo rsync -ax /boot/ /mnt/md0

5行目の/boot/の終わりのスラッシュを忘れないように。

最後にgrubをインストールして再起動する。片方のHDが壊れてももう片方のHDで起動できるように両方のHDにgrubをインストールする必要がある。

$ sudo grub-install /dev/sda
$ sudo grub-install /dev/sdb
$ sudo reboot

あと一息。

(つづく)

Linux (Ubuntu 11.04)で2TB超のHDをソフトウェアRAID化する (2)

(承前)

パーティション分け

2TBを超えるHDでは従前のいわゆるDOSパーティションテーブルは利用できず、GUIDパーティションテーブル(GPT)を使わなくてはならない。今回のHDは2Tなので必ずしもGPTを使う必要はないが、新しく触れる技術なので使ってみたところはまり込んだ次第。

GPTによるパーティション分けはGNU partedというコマンドで行う。Ubuntu デスクトップインストーラで起動し、[Try Ubuntu] を選んでターミナルを開き、parted を実行すればよい。まずはパーティションテーブルの初期化だ(以下を実行するとHDの内容が全部読めなくなるので注意してほしい)。

$ sudo parted /dev/sda
(parted) mktable gpt

さて、説明は省くがGPTを起動ディスクに用いた場合、先頭にbiosgrub属性を持つ1Mのパーティションが必要である。また、Advanced Format Technology (Big Sector) 対応のため、パーティション境界を2048セクタにアラインした方がよいらしい。このためにはセクタ境界の指定にmibまたはgibを用いればいい。以下でbiosgrubパーティションを作成する。

(parted) mkpart _ 1mib 2mib
(parted) toggle 1 bios_grub

partedのhelpコマンドによるとmkpartコマンドの第一引数はprimaryとかextendedを指定しろと書いてあるのだが、これはおそらくDOSパーティション用で、GPTの場合第一引数は単なる名前になるようだ。この名前がどのように使われるかは私は知らない。この記事では名前は全部 _ で済ますことにする。

次にboot, swap, root用の各パーティションを作成する。

(parted) mkpart _ 2mib 1gib
(parted) mkpart _ 1gib 3gib
(parted) mkpart _ 32gib 48gib

DOSパーティションと違い、パーティションのタイプを指定する必要はない。また、3gib と 32gib の間の「穴」は、後々簡単に swap パーティションを拡大できるようにするための余地である。

(最後のパーティションをディスクいっぱいまで使いたい場合はmkpart _ 32gib -0gibとすればよい; ただし同期に長大な時間がかかる)

ここまでの作業でパーティションは以下のようになる。

(parted) unit mib
(parted) print free
Number  Start     End         Size         File system  Name  Flags
        0.02MiB   1.00MiB     0.98MiB      Free Space
 1      1.00MiB   2.00MiB     1.00MiB                   _     bios_grub
 2      2.00MiB   1024MiB     1022MiB                   _
 3      1024MiB   3072MiB     2048MiB                   _
        3072MiB   32768MiB    29696MiB     Free Space
 4      32768MiB  49152MiB    16384MiB                  _
        49152MiB  1907729MiB  11858577MiB  Free Space

確認してリブートする。

(parted) quit
$ sudo reboot

インストール

Ubuntuデスクトップインストーラで起動しインストールを開始する。[ディスク領域の割り当て] の場面では [それ以外] を選んで、手動で ext4 ファイルシステムや swap を設定し、マウントポイントも設定する。

(つづく)