いろいろ管理しているサーバーのログを手元のワークステーションにコピーする仕組みを考えている中で、DRBDを試す事にしました。
これはDRBDがベストだろうという目論見ではなく、keepalivedやLVSを試していた時の流れで、いつか試そうと考えていたからです。
そこでメインマシンのUbuntu 8.04 LTSとalixのDebian lennyの間で、DRBDを試す事にしました。
ファイルシステムレベルでの同期を取るために、ocfs2を試しています。
最終的にはocfs2のバージョンの問題で同期がうまくとれない、ということがわかりました。
そのためこの構成ではブロックデバイスレベルの同期に問題はありませんが、ファイルシテムを共有するという目的については、最終的に失敗しました。
Ubuntu 8.04 LTSへのDRBDの導入
適当なパッケージがないなぁと思っていたところ 技評のUbuntu関連の記事の中に、DRBDが9.10からサポートされるようになり、8.04 LTSを含む 各バージョン用のパッケージがPPAに準備されている事を知りました。
さっそく sources.list.d/drbd.listファイルを作成しました。
/etc/apt/sources.list.d/drbd.listファイル
deb http://ppa.launchpad.net/ubuntu-ha/drbd/ubuntu hardy main
deb-src http://ppa.launchpad.net/ubuntu-ha/drbd/ubuntu hardy main
apt-keyスクリプトの使い方
これをベースに導入しようとapt-getを使ったのですが、エラーが表示されてしまいました。
$ sudo apt-get update
表示されたメッセージ
...
取得:18 http://dl.google.com stable Release [2540B]
取得:19 http://dl.google.com stable/non-free Packages [1025B]
178kB を 2min4s で取得しました (1433B/s)
パッケージリストを読み込んでいます... 完了
W: GPG error: http://ppa.launchpad.net hardy Release: 公開鍵を利用できないため、以下の署名は検証できませんでした: NO_PUBKEY 8F63FC3CB64F0AFA
W: これらの問題を解決するためには apt-get update を実行する必要があるかもしれません
もちろん"apt-get update"で問題が発生したので、実行する必要があるのはapt-keyコマンドです。
とりあえず keyserver.ubuntu.com から該当するキーファイルを取ってくることにしました。
$ sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 8F63FC3CB64F0AFA
コマンド実行時のメッセージ
Executing: gpg --ignore-time-conflict --no-options --no-default-keyring --secret-keyring /etc/apt/secring.gpg --trustdb-name /etc/apt/trustdb.gpg --keyring /etc/apt/trusted.gpg --keyserver keyserver.ubuntu.com --recv-keys 8F63FC3CB64F0AFA
gpg: 鍵B64F0AFAをhkpからサーバーkeyserver.ubuntu.comに要求
gpg: 鍵B64F0AFA: 公開鍵“Launchpad ubuntu-ha”を読み込みました
gpg: 処理数の合計: 1
gpg: 読込み: 1 (RSA: 1)
結果としては問題なかったのですが、時々keyserver.ubuntu.comでキーファイルがみつからない場合がある事です。
また90年代のpgpの頃からキーサーバといえば、MITのサーバですが、最近の動向を調べてみるとキーサーバ間の同期が取れていない状況が続いているようです。
OpenPGPキーサーバについて
OpenPGPはRFC4880としてまとまっているスタンダードを指します。
使っているgnupg(gpg)コマンドはOpenPGPの実装という関係にあります。
日本語で読める情報は OpenPKSDのサイトがまとまっているようです。少し古い情報で止まっているようですけどね。
先ほどのキーサーバ間の情報の食い違いなどは、「次世代 OpenPGP Public Keyserver (OpenPKSD) 平成14年度報告」の中でOpenPKSDが必要な背景の一つとして記述があります。
例えば先ほどの鍵ファイル"8F63FC3CB64F0AFA"は、pgp.mit.eduには登録されていますが、openpksd.orgなど他のサーバには、だいたいないようです。
DRBDパッケージの導入続き
途中で止まってしまったapt-get updateを再度、実行します。
続けて、drbd8-utilsパッケージと推奨パッケージに含まれていたdebconf-utils、共有FSを構築するためにocfs2-toolsを導入します。
$ sudo apt-get update
$ sudo apt-get install drbd8-utils debconf-utils ocfs2-tools
alixのdebian lenny側でも同様に、ただ"drbd8-utils"と"ocfs2-tools"をインストールすることにします。
$ sudo apt-get install drbd8-utils ocfs2-tools
Ubuntuでは必要なかったのですが、カーネルモジュールが自動的に入らなかったので、現在使っているカーネル(-686)に応じたモジュールも導入します。
どういうモジュールが存在するのかは、$ apt-cache search drbd8-modulesで確認できます。
$ sudo apt-get install drbd8-modules-2.6-686
ファイルシステムのセットアップ
パッケージは入ったので、これを動かしていきます。
そもそもの目的はalix側のログをWSなUbuntu側にも保存したいということでした。
とはいえ、DRBDはブロックデバイス(/dev/sd*, /dev/hd*, etc...)のミラーリングツールなので、デバイスを準備しないといけません。
WS側はLVM2が動いているので、ブロックデバイスを増やす事は問題なさそうです。
alix側のCFカードは単一のパーティションですから、USBメモリを追加することにしました。
まずはUbuntu 8.04側にLVMを準備します。
VGはtmpvgでLV名は任意ですが、ゲートウェイにしているサーバのloglvという意味で"gwloglv.drbd"としました。
$ sudo /sbin/lvcreate -L 4GB -n gwloglv.drbd tmpvg
コマンド成功時のメッセージ
Logical volume "gwloglv.drbd" created
次はFATでフォーマットされているUSBメモリをalixに差して、/dev/sdb1として認識されているところからの作業です。
パーティションIDを変更する必要はなさそうですが、まぎらわしいので83に変更しておきます。
sudo /sbin/fdisk /dev/sdb
Command (m for help): p
Disk /dev/sdb: 4009 MB, 4009754624 bytes
32 heads, 32 sectors/track, 7648 cylinders
Units = cylinders of 1024 * 512 = 524288 bytes
Disk identifier: 0x55ccabed
Device Boot Start End Blocks Id System
/dev/sdb1 1 7648 3915760 c W95 FAT32 (LBA)
Command (m for help): t
Selected partition 1
Hex code (type L to list codes): 83
Changed system type of partition 1 to 83 (Linux)
Command (m for help): p
Disk /dev/sdb: 4009 MB, 4009754624 bytes
32 heads, 32 sectors/track, 7648 cylinders
Units = cylinders of 1024 * 512 = 524288 bytes
Disk identifier: 0x55ccabed
Device Boot Start End Blocks Id System
/dev/sdb1 1 7648 3915760 83 Linux
Command (m for help): w
The partition table has been altered!
Calling ioctl() to re-read partition table.
WARNING: If you have created or modified any DOS 6.x
partitions, please see the fdisk manual page for additional
information.
Syncing disks.
DRBDを動かす
drbd.confファイルの作成
とりあえず/etc/drbd.confファイルを作成することにします。
デフォルトで配置されているファイルの中身は、ちょっと修正するには大変なボリュームなので名前を変えておきます。
$ sudo mv /etc/drbd.conf /etc/drbd.conf.original
またファイルを作成する前に両方のマシンでuname -nコマンドを実行して、ホスト名を確認しておきます。
192.168.1.1でのuname -n実行結果
gw
192.168.1.210でのuname -n実行結果
athlon
この結果を踏まえると、drbd.confファイルは次のようになります。
/etc/drbd.confファイル
global {
dialog-refresh 0;
}
common {
syncer {
rate 10M;
}
}
resource r0 {
protocol C;
startup {
become-primary-on both;
}
net {
cram-hmac-alg sha1;
shared-secret "FooFunFactory";
allow-two-primaries;
}
on gw {
device /dev/drbd0;
disk "/dev/disk/by-id/usb-SanDisk_Cruzer_Colors+_01180b20332200445284-0:0-part1";
address 192.168.1.1:7791;
meta-disk internal;
}
on athlon {
device /dev/drbd0;
disk /dev/disk/by-id/dm-name-tmpvg-gwloglv.drbd;
address 192.168.1.210:7791;
meta-disk internal;
}
}
ブロックデバイスの初期化
両方のマシンに/etc/drbd.confファイルを配置してから、次のコマンドをそれぞれ実行します。
$ sudo /sbin/drbdadm create-md r0
カーネルモジュールの起動
両方のサーバで、drbdプロセスを起動します。
/etc/init.d/drbd start
ここで次のようなメッセージが表示されます。
0: State change failed: (-2) Refusing to be Primary without at least one UpToDate disk
Command '/sbin/drbdsetup 0 primary' terminated with exit code 17
初期設定が出きていないだけのようなので、両方でdrbdプロセスを起動してから次のコマンドを実行します。
$ sudo /sbin/drbdadm -- -o primary r0
また最初に/etc/init.d/drbdを起動した側では、内部で/sbin/drbdadm wait-con-intコマンドが実行された段階で" To abort waiting enter 'yes' [ 10]:"というプロンプトが表示されます。
反対側のノードが起動するまで待ちますか、というメッセージですが、相手方がすぐに起動しないのであれば'yes'を入力します。
ここで気になったのは、本来はサーバのバックグラウンドで動くはずのスクリプトがユーザの入力待ちで止まるという違和感です。
深夜にマシントラブルでサーバファーム全体がダウン、その後片系だけ復旧したもののサーバがユーザの入力待ちで起動しない、そんなシナリオはあり得ないことではありません。
このスクリプトは大丈夫なのかなぁ。
まだ構成が終っていないから、どちらもPrimaryではないけれど、ちゃんと動くのかなぁ…。
ソースコードをみるとno_ttyな場合は/dev/consoleにattachするようになっていて、この場合はどうやってもユーザに入力させたいみたいです。
まぁ先に進めてから考える事にしましょう。
ここでステータスを確認しておきます。
$ sudo /etc/init.d/drbd status
drbd driver loaded OK; device status:
version: 8.3.2 (api:88/proto:86-90)
GIT-hash: dd7985327f146f33b86d4bff5ca8c94234ce840e build by root@athlon, 2010-03-24 00:43:08
m:res cs ro ds p mounted fstype
0:r0 Connected Primary/Primary UpToDate/UpToDate C
両方がプライマリで最新であるような状態を示す"Primary/Primary UpToDate/UpToDate"のメッセージを確認しておきます。
ocfs2を動かす
いよいよocfs2の操作に向います。
まずはプロセスの起動まで
まずは設定ファイルを両方のマシンで同じものを準備します。
UbuntuではDebian lenny側にあった/etc/ocfs2ディレクトリが準備されていなかったので、手動で作成しました。
/etc/ocfs2/cluster.confファイル
node:
name = gw
cluster = ocfs2
number = 0
ip_address = 192.168.1.1
ip_port = 7891
node:
name = athlon
cluster = ocfs2
number = 1
ip_address = 192.168.1.210
ip_port = 7891
cluster:
name = ocfs2
node_count = 2
ファイルを配置してからプロセスを起動します。
まずデフォルトでは無効にされているので、/etc/default/o2cbファイルを編集します。
これをしないと/etc/init.d/o2cbスクリプトが仕事をしてくれません。
/etc/default/o2cbファイルの変更個所
...
O2CB_ENABLED=true
...
これでスクリプトを実行すると、メッセージが出力されます。
$ sudo /etc/init.d/o2cb start
起動に成功した時のメッセージ
Loading filesystem "configfs": OK
Mounting configfs filesystem at /sys/kernel/config: OK
Loading stack plugin "o2cb": OK
Loading filesystem "ocfs2_dlmfs": OK
Creating directory '/dlm': OK
Mounting ocfs2_dlmfs filesystem at /dlm: OK
Setting cluster stack "o2cb": OK
Starting O2CB cluster ocfs2: OK
ocfs2ファイルシステムの作成
これはext3ファイルシステムを作る場合などとオプションが違うだけで、だいたい同じような操作になります。
まずはパラメータを考えずにデフォルトの状態で作成します。
既に/dev/drbd0は同期されているため、どちらか一方で次のようなコマンドを実行します。
sudo /sbin/mkfs.ocfs2 /dev/drbd0
いよいよファイルシステムのマウント
いろいろアプリケーションやらサービスやらが存在する環境になってくると、どうやって管理しようかディレクトリ構造から悩む事になります。
今回はログファイルを配置する場所を /app/logs/$(uname -n)/ocfs2
としました。
そこで両方のマシンで次のようなコマンドを実行します。
$ sudo mkdir -p /app/logs/$(uname -n)/ocfs2
$ sudo mount /dev/drbd0 /app/logs/$(uname -n)/ocfs2
ここで最終的にはエラーになってしまいました。
出力されたエラーメッセージ
mount.ocfs2: Transport endpoint is not connected while mounting /dev/drbd0 on /app/logs/athlon/ocfs2. Check 'dmesg' for more information on this error.
dmesgで確認したエラーメッセージ
[845863.471758] (10794,0):o2net_check_handshake:1197 node athlon (num 1) at 192.168.1.210:7891 advertised net protocol version 8 but 11 is required, disconnecting
どうやら原因を調べると、32bit版と64bit版のocfs2では 同期を取るためのプロトコルのバージョンが違うことによるものとのこと。
一次情報がないけど本当なのかな…。いやいやそんなはずはない。
カーネルのコードをみれば 原因はバージョンの違いでしょう。
定数"O2NET_PROTOCOL_VERSION"は32bit, 64bitとは関係ないところで定義されていますからね。
カーネルのバージョンを上げないと、どうしようもなさそうです。
それでも同時にマウントしなければ、交互にマウントはできてファイルができていることは確認できました。
負荷をかけたりはしていませんが、とりあえずocfs2が簡単に導入できることは分かりました。
ブロックデバイスレベルでの同期と、ファイルシステムレベルでの同期を考えなければいけない事がわかったのは収穫かな。
構成をもう一度考え直さなければ…。
他のalixマシンを中心に32bit版の共有ファイルシステムサーバを作るのがいいのかなぁ…。