ref: http://www.linux-ha.org/DRBD/FAQ#head-ac2d92db0450b941fe9d9873ce13613f49897f55
/dev/drbd0へmkfsしないといけないのはdrbd 8系でも同じなんだけど、8系だと手順をすっ飛ばすと途中でdrbd構築途中でエラーが出る(はず)。それに対して、0.7だとスルーされるので。ということでスーパーチョンボをしてしまったので反省エントリ。
kernelが吐いたエラー
ずーっと前に作ったdrbd 0.7で作ったサーバで、/dev/drbd0でマウントしてたディレクトリに書き込みしてたら、突然こんなログが出てreadonlyになった。
kernel: attempt to access beyond end of device kernel: drbd0: rw=0, want=16515080, limit=16509440 kernel: EXT3-fs error (device drbd0): read_block_bitmap: Canno t read block bitmap - block_group = 63, block_bitmap = 2064384 kernel: Aborting journal on device drbd0. kernel: EXT3-fs error (device drbd0) in ext3_ordered_writepage: IO failure kernel: ext3_abort called. kernel: EXT3-fs error (device drbd0): ext3_journal_start_sb: Detected aborted journal kernel: Remounting filesystem read-only
umount/mountでとりあえず書き込み可能な状態になったけど
# tune2fs -l /dev/drbd0 | grep state Filesystem state: clean with errors
となって、ext3もおかしくなっている。
DRBDのFAQを読むと
If you did mkfs /real/device, then later mount through DRBD, the file system either recognized size mismatch in superblock vs. tual block device size on the spot and refuse to mount (xfs does this, iirc).
the file system mounts alright, because it skips the check for block device size (ext3, at least certain version of it, apareny do this; it is ok for a file system to assume that its superblock contains valid data) and then thinks it could use the now n available space which is occupied by IMD.
(中略)
When the file system will start using that area is nearly impossible to pretict. So it may appear to work fine for month, and tn suddenly break again and again.
まさにこれずら。
DRBDの基本
- 特定のパーティション(/dev/sdb1とか)を/dev/drbd0とかに割り当てる
- そのパーティションにdrbdのメタデータを(今回はinternalに)作成
- 作成した/dev/drbd0を使いたいファイルシステムでフォーマット(mkfs.ext3とかで)
このとき、うっかり3番の手順をすっ飛ばして利用してたのでエラーが出た。internalでメタデータを作成すると、パーティションの後ろにdrbd用メタデータが作成されるから。なのに、/dev/sdb1をext3でフォーマットした状態(OSインストール直後だったので)で、そのまま使ってたから。
DRBDのメタデータ
- http://www.drbd.jp/documentation/drbd8-howto.html
- http://www.drbd.org/users-guide-emb/ch-internals.html#s-metadata
ガイドを読むかぎり、メタデータは外部パーティションに設定することを推奨してる?特にメタデータを別ディスクにすると、ディスクシークの関係で書き込み性能があがるようんたらかんたらっていう。
internalだと特別な設定が不要なので管理は楽かな。
間違えた経緯
もう忘れてもうたけど、たぶんこんな感じ。
- OSインストール時にとりあえず/dev/sdb1をext3でパーティション作成
- DRBD インストール
- DRBD メタデータ作成 # drbdadm adjust drbd0 (drbdsetup)でmeta-dataをinternalに作成
- ### 本当はここでmkfs.ext3 /dev/drbd0が必要 !!
- mkfsを忘れて、/dev/drbd0をext3としてマウント (/mntとかに)
- OSインストール時にext3で作成してたからか、特にエラーも出ずマウント出来る
- /mnt をディスクぎりぎりまで使ったときにメタデータに干渉して冒頭のエラー
というみじめなな結果に。
DRBD v8の場合
drbd 8.3.6でテストしてみた。↑のdrbd7と同じような手順でやってみたけど、メタデータの作成のとこでエラーがでるので、普通にやってたらどこかで間違いに気づくかな。
- OSインストール時にとりあえず/dev/sdb1をext3でパーティション作成
- DRBD インストール
- DRBD メタデータ作成 # /etc/drbd.conf書いて、drbdadm create-md drbd0を実行
すると、こんなエラーが。
# drbdadm createmd drbd0 md_offset 246718464 al_offset 246685696 bm_offset 246677504 Found ext3 filesystem 240940 kB data area apparently used 240896 kB left usable by current configuration Device size would be truncated, which would corrupt data and result in 'access beyond end of device' errors. You need to either * use external meta data (recommended) * shrink that filesystem first * zero out the device (destroy the filesystem) Operation refused. Command 'drbdmeta 0 v08 /dev/sdb1 internal create-md' terminated with exit code 40 drbdadm create-md drbd0: exited with code 40
- "(destroy the filesystem)"とあるので、/dev/sdb1の先頭を0で埋めて壊して、メタデータ作成
# dd if=/dev/zero of=/dev/sdb1 bs=1M count=1 # drbdadm create-md drbd0
# mkfs.ext3 /dev/drbd0 # mount -t ext3 /dev/drbd0 /mnt
と、こうなるのでdrbd 0.7でmkfsし忘れた、みたいな状況はたぶん起きない。
おまけ
わざと間違って/dev/sdb1にmkfsしてみた。
# /etc/init.d/drbd stop # mkfs.ext3 /dev/sdb1 # /etc/init.d/drbd start Starting DRBD resources: [ d(drbd0) 0: Failure: (119) No valid meta-data signature found. ==> Use 'drbdadm create-md res' to initialize meta-data area. <== [drbd0] cmd /sbin/drbdsetup 0 disk /dev/sdb1 /dev/sdb1 internal --set-defaults --create-device --on-io-error=pass_on failed - ntinuing!
その後、drbdを起動しようとするけど、メタデータが壊れている(dev/sdb1にmkfsしたから当然)のでエラーで起動できない。
おまけ2: drbdデバイスにmkfs.ext3 してるか調べる方法
drbd 0.7はメタデータサイズが128M固定なので、これを利用して調べれる。比較するのは
- /proc/partitions
- tune2fs -l /dev/drbd0
の値。
OSインストール直後を想定して/dev/sdb1をext3でフォーマットして、sdb1にメタデータ作成。最後にmkfs.ext3 /dev/drbd0をするかしないかで値を比較。240Mぐらいのパーティションで試してみた。
/proc/partitionsの値
# egrep 'blocks|sdb1|drbd0' /proc/partitions major minor #blocks name 202 18 240975 sdb1 147 0 109900 drbd0 # python >>> (240975 - 109900) / 1024 128
メタデータを作成した時点でdrbd0で使用できるblockサイズが128M減っている。(drbd0にmkfsしてるかどうかは関係ない)
tune2fs -l
sdb1、drbd0どっちでもいいのでtune2fs -lして、blockサイズ計算する。(DRBDのFAQに載っている計算)
Block count * Block size / 1024
- 正しく mkfs.ext3 /dev/drbd0をした場合
# tune2fs -l /dev/drbd0 | awk '/^Block.size: / { bs=$NF } /^Block.count: / { bc=$NF } END { print bc * bs / 1024 }' 109900
/proc/partitionsのdrbd0のとこと値が一致する
- うっかり mkfs.ext3 /dev/drbd0を忘れた場合
# tune2fs -l /dev/drbd0 | awk '/^Block.size: / { bs=$NF } /^Block.count: / { bc=$NF } END { print bc * bs / 1024 }' 240975
/proc/partitionsのsdb1のとこと値が一致する。つまりメタデータ分が除外されてファイルシステムのサイズが認識されているので、このまま使い出すといつか冒頭のエラーになる。実際、この状態でパーティションをフルに使うと
# mount /dev/drbd0 /mnt # dd if=/dev/zero of=/mnt/hoge bs=1M count=1000 dd: writing `hoge': Read-only file system 102+0 records in 101+0 records out 106532864 bytes (107 MB) copied, 1.23778 seconds, 86.1 MB/s # df -h | egrep 'Size|drbd' Filesystem Size Used Avail Use% Mounted on /dev/drbd0 228M 109M 109M 50% /data
となってdfで見たら128M(メタデータのサイズ)ほど容量は空いてるけど、readonlyになってext3がおかしくなる。