Raidframe: ブートドライブを RAID 1 にする。

NetBSD のブートドライブを Raidframe (software RAID) の RAID 1 構成にすることが出来ます。 [1]

同様の説明は NetBSD.ORG にもある( "Root Filesystem on RAID-1 with NetBSD's RAIDframe" by Martti Kuparinen )のですが、本家の説明は長すぎますし、 やろうとしていることが複雑すぎるんじゃないかな? もっと簡単に、かつ短くなると思うのですがねぇ… というのが以下の手順です。

手順を、ざっと説明すると、次のようになります。 インストーラは RAID 1 の上へ直接インストールしたりしてくれないため、 (1) 一旦 sd0 へ(ごく普通に) NetBSD を入れ、 (2) sd1 の上に sd0 抜きの RAID1 (わざと sd0 抜きの欠陥品)を作り、 (3) RAID 1 を rebuild することで sd1 + sd0 の RAID 1 を作ります。

以下では、 SCSI DISK が2つ(sd0 と sd1)あるハードウエアのブートドライブを RAID 1 にすることを考えます。

ATA や SATA なら sd を wd へ読み変えて下さい。

なお、大きなディスクを使う場合、 LBA48 bug (128 G 境界での切替え間違い)が恐いので、 パーティションレイアウトでは 128G 部分を飛ばす(小さいパーティションを つくって飛ばしておく)と良いでしょう。セクタ番号でいうと

2^28 -1 = 268435455
です(このセクタを含むダミーの小さなパーティションを作り、それを使わない)。 Seagate [2] なら LBA48 quirk 入ってるじゃんという反論はあるでしょうが、 運用していくうちに違うメーカーの HDD と混在するかもしれないわけですから、 安全側に倒すのが運用というものです。

STEP 1: 一回 sd0 へ普通に NetBSD/i386 をインストールする

最初の一回は、sd0 へ普通に NetBSD/i386 をインストールしないといけません。 [3]

たとえば、こんな感じにパーティションを切ることにしましょう。

sd0a	/
sd0b	swap
sd0e	/other
なお sd0b と sd1b は普通に SWAP として使い、 sd0e と sd1e も普通の FFS として使うつもりの設定です。 [4]

初回の OS インストール手順 は省略します。 いつもの通りです。 くわしくは Chapter 4 を参照して下さい。 さて、sd0 へのインストール終了後、無事に起動しおわったとします。

STEP 2: sd1 に RAID1 を作る

まず、最初にするのは sd1 へ sd0 のディスク設定をコピーすることです。 手順は次の二段階からなります。

(1) MS-DOS 的なパーティションの設定
(2) Unix 的なパーティションの設定

まずは fdisk コマンドを使って sd0 と sd1 の情報を確認しましょう。

netbsd# fdisk /dev/sd0
Disk: /dev/sd0d
NetBSD disklabel disk geometry:
cylinders: 90774, heads: 2, sectors/track: 789 (1578 sectors/cylinder)
total sectors: 143374744

BIOS disk geometry:
cylinders: 1024, heads: 255, sectors/track: 63 (16065 sectors/cylinder)
total sectors: 143374744

Partition table:
0: NetBSD (sysid 169)
    start 63, size 143374681 (70007 MB, Cyls 0-8924/169/37), Active
1: <UNUSED>
2: <UNUSED>
3: <UNUSED>
Bootselector disabled.

netbsd# fdisk /dev/sd1
fdisk: primary partition table invalid, no magic in sector 0
Disk: /dev/sd1d
NetBSD disklabel disk geometry:
cylinders: 90774, heads: 2, sectors/track: 789 (1578 sectors/cylinder)
total sectors: 143374744

BIOS disk geometry:
cylinders: 1024, heads: 255, sectors/track: 63 (16065 sectors/cylinder)
total sectors: 143374744

Partition table:
0: <UNUSED>
1: <UNUSED>
2: <UNUSED>
3: <UNUSED>
Bootselector disabled.
sd1 には何も設定が”ないはず”です。

sd1 には何も設定が”ないはず”ですが、念のため消します。 具体的には、ディスクの先頭部分を 0 で上書きしておきます。

netbsd# dd if=/dev/zero of=/dev/rsd1d bs=8k count=1

次に fdisk で sd1 のパーティション 0 を active にします。

# fdisk -0ua /dev/sd1
いろいろ聞かれますが、よしなに答えて下さい。 RETURN たたくか yes と教えるだけで大丈夫です。

終ったら、念のため、 sd0 と sd1 の fdisk の内容を比べておきましょう。

netbsd# fdisk /dev/sd0 > /tmp/sd0 ; fdisk /dev/sd1 > /tmp/sd1 ; diff -ub /tmp/sd[01]
--- /tmp/sd0    2008-04-29 06:54:50.000000000 +0900
+++ /tmp/sd1    2008-04-29 06:54:50.000000000 +0900
@@ -1,4 +1,4 @@
-Disk: /dev/sd0d
+Disk: /dev/sd1d
 NetBSD disklabel disk geometry:
 cylinders: 90774, heads: 2, sectors/track: 789 (1578 sectors/cylinder)
 total sectors: 143374744
@@ -10,6 +10,7 @@
 Partition table:
 0: NetBSD (sysid 169)
     start 63, size 143374681 (70007 MB, Cyls 0-8924/169/37), Active
+        PBR is not bootable: All bytes are identical (0x00)
 1: <UNUSED>
 2: <UNUSED>
 3: <UNUSED>
「PBR (primary boot record) が違うよ」のメッセージは無視して下さい。 インストールすれば PBR が書かれます。

これで MS-DOS 的な設定が終りました。 次は Unix 的な設定(disklabel の設定)です。

netbsd# disklabel sd0
# /dev/rsd0d:
type: unknown
disk: netbsd-raid1-sd0
label: 
flags:
bytes/sector: 512
sectors/track: 789
tracks/cylinder: 2
sectors/cylinder: 1578
cylinders: 90774
total sectors: 143374744
rpm: 3600
interleave: 1
trackskew: 0
cylinderskew: 0
headswitch: 0           # microseconds
track-to-track seek: 0  # microseconds
drivedata: 0 

16 partitions:
#        size    offset     fstype [fsize bsize cpg/sgs]
 a:  70700000        63     4.2BSD   2048 16384     0  # (Cyl.      0*-  44803*)
 b:   1974681  70700063       swap                     # (Cyl.  44803*-  46054*)
 c: 143374681        63     unused      0     0        # (Cyl.      0*-  90858*)
 d: 143374744         0     unused      0     0        # (Cyl.      0 -  90858*)
 e:  70700000  72674744     4.2BSD   2048 16384     0  # (Cyl.  46054*-  90858*)
netbsd# 
私は disklabel -I -i でインタラクティブモードになるので、 これを愛用しています。 sd0 の disklabel と同じ設定(size offset)を sd1 に入れてください。 そして sd1a の fstype (ファイルシステムのタイプ)を RAID へ変更して下さい。
netbsd# disklabel -I -i sd1
	... snip ...
partition> P
16 partitions:
#        size    offset     fstype [fsize bsize cpg/sgs]
 a:  70700000        63       RAID                     # (Cyl.      0*-  44803*)
 b:   1974681  70700063       swap                     # (Cyl.  44803*-  46054*)
 c: 143374681        63     unused      0     0        # (Cyl.      0*-  90858*)
 d: 143374744         0     unused      0     0        # (Cyl.      0 -  90858*)
 e:  70700000  72674744     4.2BSD      0     0     0  # (Cyl.  46054*-  90858*)
partition> 
要点は sd0 の a パーティションは 4.2 BSD ですが、 sd1 の a パーティションは RAID であるところです。 よく確認して下さい。

もっとも次のようにやるのが一番楽ですね。

# disklabel sd0 | sed s/sd0/sd1/g > template
# disklabel -R sd1 template
# disklabel -I -i sd1
	... 4.2BSD から RAID へ変更 ...

STEP 3: sd1 に RAID1 を作る

sd1 に Raidframe で RAID 1 を作ります。 /etc ではなく [5] /tmp や /var/tmp に raid0.conf ファイルを作り、 ファイルの内容は次のようにしてください。

# cat > /var/tmp/raid0.conf << EOF
START array
1 2 0

START disks
absent
/dev/sd1a

START layout
128 1 1 1

START queue
fifo 100
EOF
ここで sd0a 分のところが absent になっていることに注意して下さい。 absent は「片方がない」ことが設定のうちだと Raidframe に教えるためのものです。

いつものように raid0 を構築して下さい。 意味の詳細は raidctl(8) に書いてありますので、そちらを御覧下さい。

# raidctl -C /var/tmp/raid0.conf raid0
# raidctl -I YYYYMMDD raid0
# raidctl -i raid0
# raidctl -s raid0
netbsd# raidctl -s raid0
Components:
          component0: failed
           /dev/sd1a: optimal
No spares.
component0 status is: failed.  Skipping label.
Component label for /dev/sd1a:
   Row: 0, Column: 1, Num Rows: 1, Num Columns: 2
   Version: 2, Serial Number: 20080428, Mod Counter: 7
   Clean: No, Status: 0
   sectPerSU: 128, SUsPerPU: 1, SUsPerRU: 1
   Queue size: 100, blocksize: 512, numBlocks: 70699904
   RAID Level: 1
   Autoconfig: No
   Root partition: No
   Last configured as: raid0
Parity status: DIRTY
Reconstruction is 100% complete.
Parity Re-write is 100% complete.
Copyback is 100% complete.
これで raid0 という仮想ディスクが出来ているような状態まで来ました。

raid0 ディスクに disklabel を書き、newfs します (注: ここで raid0a は RAID ではなく FFS ですよ、OK ?)。

# disklabel -I -i raid0
# newfs raid0a
注: あとで dump device を sd0b 等にするので raid0 全体を raid0a にして しまってかまいません(つまり size offset が raid0d と raid0a で同じ)。 また、raid0a はセクター番号 0 から全部とすることに注意 (変に気を使って 63 とかにするとブートセクタが書き込めません、 すでに raid0d == raid0a の 0 番値が、 ディスク全体のセクタ番号でいえば 63 にあたっています)。

STEP 4: sd1 に sd0 の中身をコピーする

sd1 上に RAID 1 が出来ました。 次に sd0 の中身を sd1 へコピーします。

この手順が必要なのは FFS の sd0a を raid0 化して、 その上の raid0a へ今の sd0a のデータを持っていく [6] 必要があるためです。 しかしながら、これはコマンド一発で出来ないので、次の手順が必要になります。

さて dump コマンドを使って sd0 の中身を raid0a へコピーしましょう。

# mount /dev/raid0a /mnt
# dump -0 -f - / | (cd /mnt && restore -x -f -)
-v (verbose) をつけると動作状況が表示されますがうるさすぎるかもしれません。
# dump -0 -f - / | (cd /mnt && restore -v -x -f -)

コピーの最後に重要な変更をします。raid0a 上の /etc/fstab を編集し / を raid0a にします(注: sd0a の /etc/fstab ではありません。 この後 sd0a の中身はリブートする際に消されるので関係ないです)。 あと sd0b を dump device にしておきましょう(sw を dp に変更)。

# ${EDITOR} /mnt/etc/fstab
	... snip ...
# cat /mnt/etc/fstab
/dev/raid0a     /               ffs     rw      1       1
/dev/sd0b       none            swap    dp      0       0
/dev/sd1b       none            swap    sw      0       0
あと swapoff=yes も仕込んでおきます。
# cat >> /mnt/etc/rc.conf << EOF
swapoff=YES
EOF

STEP 5: sd1 をブート可能にする

sd1 へブートブロックを書きこみます。

netbsd# cd /usr/mdec
netbsd# installboot -v -t raid -o console=com0 /dev/rsd1a bootxx_ffsv1
File system:         /dev/rsd1a
File system type:    raid (blocksize 16384, needswap 0)
Primary bootstrap:   bootxx_ffsv1
Preserving 51 (0x33) bytes of the BPB
Boot options:        timeout 5, flags 0, speed 9600, ioaddr 0, console com0
ファイルシステムタイプは RAID です。 ついでに(サーバ機なので)ここではシリアルコンソール化しています。

STEP 6: Raidframe を autoconfig にする

最後に、もう一つ重要な設定「Raidframe を autoconfig にする」をします。 これで次回起動時、よしなに Raidframe が raid0 を有効にしてくれます。

netbsd# raidctl -A root raid0
raid0: Autoconfigure: Yes
raid0: Root: Yes
raid0 の設定をやりなおしたいなら、
netbsd# raidctl -A no raid0
で autoconfig を off にして再起動すれば元の sd0 で起動します。

リブートして下さい。

# shutdown -r now

STEP 7: RAID 1 (/dev/raid0a) の再構築

リブートすると、 カーネルは、ファイルシステムをアタッチしていくときに bootable RAID 1 を認識し、そこへ boot device を持っていきます。

この動作がないと、最初の sd0a で起動してしまいます! Raidframe の autoconfig がポイントであることが分かりますね。

起動したら、raid0 を再構築します。

まずは現状(sd1 だけが RAID 1 化の状態)を確認し、

netbsd# raidctl -s raid0
Components:
          component0: failed
           /dev/sd1a: optimal
No spares.
component0 status is: failed.  Skipping label.
Component label for /dev/sd1a:
   Row: 0, Column: 1, Num Rows: 1, Num Columns: 2
   Version: 2, Serial Number: 20080429, Mod Counter: 46
   Clean: No, Status: 0
   sectPerSU: 128, SUsPerPU: 1, SUsPerRU: 1
   Queue size: 100, blocksize: 512, numBlocks: 70699904
   RAID Level: 1
   Autoconfig: Yes
   Root partition: Yes
   Last configured as: raid0
Parity status: DIRTY
Reconstruction is 100% complete.
Parity Re-write is 100% complete.
Copyback is 100% complete.
sd0 を RAID にくみこみます(component0 を /dev/sd0a へ変更する)。

sd0 の disklabel を sd1 へ合わせます (実質的には sd0a のタイプを FFS から RAID に変更するだけですね)。

# disklabel /dev/sd1 > disklabel.sd1
# disklabel -R -r /dev/sd0 disklabel.sd1
# disklabel /dev/sd0
sd0a を raid0 へ組み込み
netbsd#  raidctl -a /dev/sd0a raid0
Warning: truncating spare disk /dev/sd0a to 70699904 blocks (from 70699936)
netbsd# raidctl -s raid0
Components:
          component0: failed
           /dev/sd1a: optimal
Spares:
           /dev/sd0a: spare
component0 status is: failed.  Skipping label.
Component label for /dev/sd1a:
   Row: 0, Column: 1, Num Rows: 1, Num Columns: 2
   Version: 2, Serial Number: 20080429, Mod Counter: 46
   Clean: No, Status: 0
   sectPerSU: 128, SUsPerPU: 1, SUsPerRU: 1
   Queue size: 100, blocksize: 512, numBlocks: 70699904
   RAID Level: 1
   Autoconfig: Yes
   Root partition: Yes
   Last configured as: raid0
/dev/sd0a status is: spare.  Skipping label.
Parity status: DIRTY
Reconstruction is 100% complete.
Parity Re-write is 100% complete.
Copyback is 100% complete.

raid0 を rebuild します。

# raidctl -v -F component0 raid0
なお -v なしで実行してしまった場合、 後からでも実行中の様子は -S でわかります。
# raidctl -F component0 raid0
# raidctl -S raid0

rebuild が終ったら、raid0 のステータスを確認してみましょう。

# raidctl -s raid0

STEP 8: sd0 もブート可能にしておく

sd0 にもブートローダを書きこんでおきましょう。 コマンドオプションは sd1 の時と同じです(sd0 と sd1 が異なるだけ)。

netbsd# cd /usr/mdec
netbsd# installboot -v -t raid -o console=com0 /dev/rsd0a bootxx_ffsv1

終りです。おめでとう!

Notes

[1]

現在の fml.org のサーバ機は全てこの構成です。 Raidframe は、自宅で、データセンターで、 オフィス、fml.org 、商用サービスで十年近く運用してきました。 ディスク交換まで含めていろいろなシチュエーションを体験しましたが、 まったく問題ありません。 作者自身が今でも保守していてくれる Raidframe には絶大な信頼をおいています。

三千万のファイルサーバとかならよいのですが、 それが買えないなら、 つまり安いハードウエア RAID なんか使うくらいなら、 ソフトウエア RAID のほうがマシです。

ディスクなんて、はじめから予備を搭載しておくのが当然でしょうから、 ソフトウエア RAID であれば、 リモートから on the fly でどうとでも直せます。 うむ、やはりこうありたいと。

[2]

Seagate OK だったのはひと昔前の話、 2009 現在 HGST 以外の HDD なんて恐くて使えない。

でも HGST の 1T は 128G 境界で soft error と言いやがります。 念のため LBA48 bug を回避しておくべきです。

まぁ LBA48 bug 回避にはカーネルをハックするという案もアリですが。 アップグレードの際に忘れそうなんですよね、このハックを入れるの。

[3]

実のところ、disklabel 設定の際に RAID にすればよさそうなものですが、 これだとインストールさせてくれません ;-) 一回目は、普通に FFS とかにしておかないと、 インストーラ様が作業できないらしいです。

[4]

一方、NetBSD.ORG の説明は、全部を raid0 にのせてしまうために、 raid0 の上のスワップ設定をいじくりまわすなどといった 面倒なことになっています。

本章の説明は raid0 + その他はいつもの swap と FFS です。 raid0 + swap + raid1 + ffs でも OK です。 ただ、この場合には raidframe の kernel thread が2つ走ってしまうのがデメリットです。

なお boot device を設定する際に自動的に「raid0b を使うぜ!」とカーネル は叫ぶのですが、スワップも dump device も明示的に設定し直すので、 raid0b を用意しなくても問題ないと思われまする(とカーネルを斜め読みした 結果なのに断言:-)。まぁ、このタイミング〜再設定までの間にカーネルがこ けてダンプしたら困りますけど、そんな小さい可能性まで考えなくても〜と。

[5]

最終的に Raidframe 自動構築モードに設定するため 最後までいっても /etc/raid0.conf は不要です。 /etc/raid0.conf を作ってしまうと 「すでに raid0 あるよ!」と警告が出ちゃいます。 注意して下さい。

[6]

この後(OS リブート後) sd0 は Raidframe に組み込まれ、 sd1 上の raid0a の中身を sd0 上の raid0a 部分へコピーバックすることになります。 その時に sd0 の現在の中身は上書きされ、 今 sd1 へコピーした内容へ切り替わります。

my homepage is www.fml.org/home/fukachan/.
my free softwares are found at www.fml.org/software/.
fml 4.0 project homepage is www.fml.org/fml/menu.ja.html.
fml 8.0 (fml-devel) project homepage is www.fml.org/software/fml8/.
about one floppy bsd routers, see www.bsdrouter.org/.
USB bootable OS is www.fml.org/software/mkliveusb/.
my laboratory is www.nsrg.fml.org.
Also, visit nuinui's world :) at www.nuinui.net.
For questions about me, e-mail <fukachan@fml.org>.
Copyright (C) 1993-2010 Ken'ichi Fukamachi

Powered by IIJ (1996-2008) and Chitose Institute of Science _and_ Technology (2008-).

Powered by NetBSD (1993-).