アシアルブログ

アシアルの中の人が技術と想いのたけをつづるブログです

DRBD+heartbeat+LVM(on Fedora Core10)によるクラスタリング

こんにちは、亀本です。

今回は、PHPとかから少し離れて、サーバのクラスタリングのお話です。
ちょっと仕事で冗長化システムを組む必要があったので、せっかくなので記事にまとめました。


さて、ここで目指すのは、DRBDを使ったデータレプリケーションサーバ( Master / Slave 構成 )の自動フェイルオーバークラスタ( 非フェイルバック構成 )です。

ネットワーク構成としては、ルータから結ばれるLAN(eth0に接続)とは別に、eth1で1対1のLAN接続を行います。
また、heartbeatでのクラスタ構成後は、eth0に仮想IPとして192.168.1.100を割り振るようにします。

eth1の設定は、



# vi /etc/sysconfig/network-scripts/ifcfg-eth1
DEVICE=eth1
HWADDR=00:00:00:00:00:00
ONBOOT=yes
BOOTPROTO=static
IPADDR=192.168.50.1
NETMASK=255.255.255.0


のような感じになります。

また、他にもheartbeat用にttyS0 (RS-232Cのシリアル) をクロスで結んでいます。
こちらは特に設定の必要はありませんし、付けなくてもシステムは組めます。


1. サーバ構築時のパーティション設定

ハードディスク構成は、Hardware RAID 1+0 ベースの1 Logical Drive でやってます。
作成するパーティション構成としては、最終的に



○物理レイヤ
/dev/cciss/c0d0
     c0d0p0 LVM Volume
     c0d0p1 /boot     # ブートローダ

○LVM
/dev/LVMVol1/lv_root /
/dev/LVMVol1/lv_var  /var  # なんとなく分けた。このあたりはご自由に。。
/dev/LVMVol1/lv_data /data # drbdによるレプリケーション対象ドライブ。あとから/dev/drbd0でラッピングされます。
/dev/LVMVol1/lv_meta (none) # drbdのmetaデータ格納用ドライブ


という構成を目指します。LVMVol1がLVMのボリュームグループ名、lv_rootなどはLV名です。

この構成を作成するにあたり、OSのインストール時に注意すべき事として、lv_metaに相当するmetaデータ用パーティションの取り扱いがあります。
この領域は、DRBDがメタデータを作成する際に独自ファイルシステムを作成しようとするので、OS側でフォーマットされてしまっているとエラーが発生する事があります。
なので、OSインストール時には作成せず、領域だけ残すようにして、root,var,data領域を作成しましょう。
また、後々サーバ名も必要になるので、localhost.localdomainなどではなく、ちゃんとしたサーバ名をつけておくようにしてください。

なお、もし構築済みのサーバでLVM領域をめいっぱい使いきってしまっている場合には、LVM領域の変更をする必要があります。
その方法についても、あとで少しふれておきます。


2. DRBDのインストール

ここでは、最小構成(Base + Vimぐらい) でインストールした前提で話を進めます。
なお、yumの設定やyum updateはやってある前提です。

2.1 コンパイルに必要なツールの準備

Fedora CoreではDRBDのrpmパッケージは用意されておらず、自前でコンパイルする必要があります。
そのため、まずDRBDのrpm作成に必要なツール類をインストールします。



# yum install make gcc glibc flex rpm-build


自分の環境ではmake,glibcは入っていたので、gccflexrpm-buildとその関連パッケージがインストールされました。

また、DRBDのコンパイルにはカーネルのソース等も必要になるので、それらも入手しておきます。



# yum install kernel-devel
# yumdownloader --source kernel
# rpm -ivh kernel-2.6.27.29-170.2.78.fc10.src.rpm


rpmのインストールではユーザ/グループのwornが出ますが気にしなくて大丈夫です。

2.2 DRBDのコンパイルとインストール

次に、DRBDのソースを取得してきて、DRBDをコンパイルします。
DRBDのソースは、http://oss.linbit.com/drbd/ からダウンロードできます。



# wget http://oss.linbit.com/drbd/8.3/drbd-8.3.2.tar.gz


あとは、以下のようにソースを展開してmakeすれば、rpmの作成まで一括でやってくれます。



# tar xvzf drbd-8.3.2.tar.gz
# cd drbd-8.3.2
# make rpm


make終了後に以下のように作成したrpmの一覧が出れば成功です。



You have now:
-rw-r--r-- 1 root root  220334 2009-08-14 02:09 dist/RPMS/x86_64/drbd-8.3.2-3.x86_64.rpm
-rw-r--r-- 1 root root 1079065 2009-08-14 02:09 dist/RPMS/x86_64/drbd-km-2.6.27.29_170.2.78.fc10.x86_64-8.3.2-3.x86_64.rpm


あとは、このrpmを展開すれば、インストールは完了です。



# cd dist/RPMS/x86_64/
# rpm -ivh *.rpm


2.3 DRBDインストール後の注意点

DRBDは、カーネルモジュール作成時にカーネルのソースを利用しているため、カーネルのバージョンが変わってしまうと動かなくなってしまう場合があります。
そのため、カーネルのバージョンアップがかかるようなアップデートをかける場合には、DRBDの再構築も忘れずに行うようにしてください。
cronでyum のアップデートを行うように設定している場合は、アップデート対象からkernelを除外しておくなどの対応をしておき、kernelのメンテナンスだけは手動で行うようにするとよいでしょう。



# vi /etc/yum.conf
exclude=kernel*


3. DRBDのセットアップ

続けて、DRBDを動作させるためのセットアップを行っていきます。

3.1 DRBDのmetaデータについて

DRBDは、実際に共有されるデータ以外にも、変更データ管理用のmetaデータを作成しますが、そのmetaデータの管理方法には「データ領域に含める(internal)」「外部領域を利用する(external)」の2種類の方法が用意されています。

どちらが良いのか、というのは一概には言えないようなのですが、internalでやり方を書いてあるものは多くてもexternalでやっているドキュメントがあまり見当たらなかったので、今回は外部領域を利用する方法を紹介します。


3.2 metaデータ用LVの作成

まずはmetaデータを格納する領域を確保します。
どのくらい領域が余っているかは、以下のようにして確認できます。



# vgdisplay |grep Free
  Free  PE / Size       209 / 6.53 GB


自分の環境では、端数を残しておいたらこのくらいになりましたが、metaデータにはさすがにちょっと6Gは多い気もしますね。まぁ今回はこれで行きます。
次のようにして、LVを作成します。



# lvcreate -l 209 -n lv_meta LVMVol1
  Logical volume "lv_meta" created


容量をバイトサイズで指定したい場合には、-l 209の代わりに -L 6G などと指定してあげればOKです。

3.3 領域を使いきっていた場合

OSインストール時に領域を残してあれば上記の操作だけで大丈夫ですが、LVMの領域を使いきっていた場合には、何かしらのLVをリサイズして縮小し、使用領域を確保する必要があります。
/dev/LVMVol1/lv_data (ext3)を縮小する場合には



# lvdisplay -C |grep lv_data
  lv_data LVMVol1 -wi-ao 292.97G

# umount /data
# resize2fs /dev/LVMVol1/lv_data 290G
# lvreduce -L 290G /dev/LVMVol1/lv_data
# mount /data


とします。なお、リサイズに伴ってデータが欠損する危険はついて回りますので、そこは自己責任でお願いします。
(よほど使いこんでいなければ、大丈夫そうですが。。。)

これで、2Gちょっとぐらいの領域が新たに確保できるようになるので、あとは3.2で紹介した方法でmetaデータ用のLVを作ってください。

3.4 drbd.confの設定

ここまででmetaデータ用の領域が確保できたので、続けてDRBDの設定drbd.confを以下のように作成しましょう。



# vi /etc/drbd.conf

resource r0 {
  protocol B;

  handlers {
    pri-on-incon-degr "halt -f";
  }

  startup {
    wfc-timeout 120;
    degr-wfc-timeout 120;
  }

  syncer {
    rate 100M;
  }

  disk {
    on-io-error detach;
  }

  net {
    cram-hmac-alg "sha1";
    shared-secret "HogeHoge";
    after-sb-0pri disconnect;
    after-sb-1pri disconnect;
    after-sb-2pri disconnect;
    rr-conflict    disconnect;
  }

  on db1.example.com {
    device     /dev/drbd0;
    disk       /dev/LVMVol1/lv_data;
    address    192.168.50.1:7788;
    flexible-meta-disk /dev/LVMVol1/lv_meta;
  }

  on db2.example.com {
    device     /dev/drbd0;
    disk       /dev/LVMVol1/lv_data;
    address    192.168.50.2:7788;
    flexible-meta-disk /dev/LVMVol1/lv_meta;
  }
}


各項目の細かい説明は、man drbd.confや 邦訳( http://www.drbd.jp/documentation/drbd.conf.html )を参照してください。

ここでは、環境に合わせて必ず変更が必要な on句の説明をしておきます。

まず、on db1.example.com となっているonの後の名前は、uname -nで出てくる各サーバのホスト名である必要があります。それぞれの対象サーバで設定を行いましょう。
また、addressではそれぞれのサーバのIP、およびDRBDの通信に使うポート番号を指定します。

次にdiskとdeviceですが、diskが実際にDRBDが書き込みを行うデバイス本体で、deviceがDRBDのデバイス名です。
この設定では、/dev/drbd0というデバイスに対しての書き込みが、DRBDを経由してそれぞれのサーバの/dev/LVMVol1/lv_dataに書き込まれることになります。

こう設定すると、lv_dataデバイスはDRBDの支配下に置かれることになります。
そのため、今までlv_dataをマウントしていた/dataディレクトリは今後/dev/drbd0をマウントするようにシステムの設定を変更する必要があります。

最後に、flexible-meta-diskですが、これが先ほど作ったメタデータ格納用のデータ領域の指定です。

3.5 DRBDボリュームの作成

以上でdrbd.confの設定が終わったので、実際にDRBDのリソースを作成します。



# drbdadm create-md r0
md_offset 0
al_offset 4096
bm_offset 36864

Found some data
 ==> This might destroy existing data! <==

Do you want to proceed?
[need to type 'yes' to confirm]


ここで、yesとタイプして進めれば、metaデータの作成が完了し、DRBDを起動する準備が整います。
なお、create-mdの後に指定しているのはresourceの後ろに書いたリソース名で、この名前は自由に変えられます。

3.6 internalでやる場合の注意

metaデータ領域をinternalにする場合には、flexible-meta-diskの指定を[ internal ]変更する事で可能です。
共有対象となる領域内(今回で言えば/dev/LVMVol1/lv_data)にmetaデータを保存する領域を作成するので、この領域が何かしらのFileSystemでフォーマットされていると、こちらのFAQで参照できるようなエラーに当たる事があります。

その場合はFAQにしたがい、ボリュームを作り直すなりしてトライしてみてください。

4 DRBDの起動と同期

これまでの作業を、2台のサーバで設定し終えたら、DRBDの起動準備が整います。
あとは、DRBDを起動して同期作業を行いましょう。

4.1 モジュールのロード

まずは、DRBDのカーネルモジュールをロードします。



# modprobe drbd


以下のようになればOKです。



# lsmod|grep drbd
drbd                  225992  0


4.2 DRBDの起動

いよいよDRBDの起動です。以下のようにして、起動させてください。



# /etc/init.d/drbd start


2台のサーバのうち、最初に起動したサーバの方では以下のような警告が出ますので、yesとタイプして先に進み、もう1台も起動してください。



Starting DRBD resources: [ d(r0) s(r0) n(r0) ]..........
***************************************************************
 DRBD's startup script waits for the peer node(s) to appear.
 - In case this node was already a degraded cluster before the
   reboot the timeout is 120 seconds. [degr-wfc-timeout]
 - If the peer was available before the reboot the timeout will
   expire after 120 seconds. [wfc-timeout]
   (These values are for resource 'r0'; 0 sec -> wait forever)
 To abort waiting enter 'yes' [  52]:yes


各サーバのDRBDを起動したら、以下のようにして状態を確認してみましょう。



# cat /proc/drbd
version: 8.3.2 (api:88/proto:86-90)
GIT-hash: dd7985327f146f33b86d4bff5ca8c94234ce840e build by root@db1.example.com, 2009-08-14 02:09:08
 0: cs:Connected ro:Secondary/Secondary ds:Inconsistent/Inconsistent B r----
    ns:0 nr:0 dw:0 dr:0 al:0 bm:0 lo:0 pe:0 ua:0 ap:0 ep:1 wo:b oos:307200000


となり、cs:Connected ro:Secondary/Secondary と、両方ともセカンダリで接続されているのが分かります。
この状態ではまだ、/dev/drbd0はマウントする事ができません。


4.3 プライマリの設定とデータ同期

では、1台をプライマリに昇格し、/dev/drbd0をマウントしてデータ同期できるようにしましょう。
プライマリにしたいサーバで、以下のコマンドを実行します。



# drbdadm -- --overwrite-data-of-peer primary r0


これで、実行した側のサーバがプライマリに切り替わり、同時にデータの同期が開始されます。
セカンダリ側では何もする必要はありません。

初回同期の際には、差分の同期ではなく全データの完全同期が行われます。
その様子も、/proc/drbd をみる事で把握する事が出来ます。



# cat /proc/drbd
version: 8.3.2 (api:88/proto:86-90)
GIT-hash: dd7985327f146f33b86d4bff5ca8c94234ce840e build by root@db1.example.com, 2009-08-14 02:09:08
 0: cs:SyncSource ro:Primary/Secondary ds:UpToDate/Inconsistent B r----
    ns:8887460 nr:0 dw:0 dr:8888236 al:0 bm:542 lo:1710 pe:31 ua:1886 ap:0 ep:1 wo:b oos:298312664
        [>....................] sync'ed:  2.9% (291320/300000)M
        finish: 0:38:00 speed: 130,412 (80,064) K/sec


この同期が100%になれば、晴れてDRBDのレプリケーションが完成です。

4.4 DRBDボリュームのマウントと 設定変更

この時点で、プライマリ側では/dev/drbd0を利用する事が出来るようになり、書き込んだ内容はすべて同期されるようになります。



# mount -t ext3 /dev/drbd0 /data/


さて、これでDRBDは使えるようになりましたが、最後にrebootなどした際に謝ってlv_dataが/dataにマウントされてしまわないよう、fstabを変更して、以下のようにlv_dataの項目をコメントアウトしておきます。



# vi /etc/fstab

/dev/LVMVol1/lv_root    /                       ext3    defaults        1 1
#/dev/LVMVol1/lv_data    /data                   ext3    defaults        1 2
/dev/LVMVol1/lv_var     /var                    ext3    defaults        1 2
.
.
.


これで、誤ってlv_dataがマウントされてしまう事もなくなります。
なお、今回は最終的にheartbeatがDRBDの面倒を見ることになるので、ここではfstabに新しい設定などは加えていませんが、自分でマウントする場合などは



/dev/drbd0    /data                   ext3    defaults        1 0


のような設定を追加しておくと便利でしょう。

5. heartbeatのインストールとDRBD連携

DRBDの設置が完了したので、続けてheartbeatをインストールし、DRBDと連携させてみます。

5.1 インストール

Fedora Core 10では、heartbeatはyumでインストール可能です。



# yum install heartbeat


以上でインストール完了です。

5.2 設定とDRBD連動

では、これを2台のサーバで連動するように、設定します。

heartbeatの動作には、/etc/ha.d/ディレクトリの中に、
・authkeys
・ha.cf
・haresources
の3つを作成する必要があります。
多くの設定項目がありますが、付属のサンプルがあるのでこれをコピーして使うとよいでしょう。



# cp /usr/share/doc/heartbeat-2.1.3/authkeys /etc/ha.d/
# cp /usr/share/doc/heartbeat-2.1.3/ha.cf /etc/ha.d/
# cp /usr/share/doc/heartbeat-2.1.3/haresources /etc/ha.d/


これらを順に設定して行きます。
まず、authkeysは、以下の2行をコメントアウト解除します。



# vi /etc/ha.d/authkeys
auth 1
1 crc


また、パーミッションも次のように変更しておく必要があります。



# chmod 600 /etc/ha.d/authkeys


次にha.dは、以下のように項目を設定して行きます。
ほとんどがコメントアウトを解除するだけですが、一部値が違うものは変更してください。



# vi /etc/ha.d/ha.cf
keepalive 2
deadtime 30
warntime 10
initdead 120

udpport 694
baud    19200
serial  /dev/ttyS0 
ucast eth1 192.168.50.2

auto_failback off

node    db1.example.com
node    db2.example.com


ここで、ucastはeth1から192.168.50.2に向けてユニキャストでheartbeatの確認をする、という意味の設定で、192.168.50.2に該当するサーバでは
ucast eth1 192.168.50.1
のような設定になります。
また、node はheartbeatの対象となるサーバの、uname で取得できるサーバ名を設定します。

なお、baudとserialはシリアルケーブル用の設定なので、シリアルケーブルをつながない場合には必要ありません。

最後にharesourcesには、以下の1行を追加してください。



# vi /etc/ha.d/haresources

db1.example.com 192.168.1.100/24 drbddisk::r0 Filesystem::/dev/drbd0::/data::ext3


これらを設定したのに、heartbeatを再起動しましょう。(install時に自動的に起動しているので、再起動になります)

以上で、設定はすべて完了です。
heartbeatが正常にフェイルオーバーするかを確認するには、ifconfigやdfなどで設定情報を確認した後、現在プライマリとして動作しているサーバのheartbeatwをstopするなどして、セカンダリサーバがきちんと仮想IPを持ったり、/dataディレクトリに/dev/drbd0がマウントされていたりするかチェックすればよいでしょう。

また、stopしたheartbeatを再度startしても、自動フェイルバックせずにそのまま稼働し続けます。


だいぶ長くなってしまいましたが、これでベースシステムとしてのheartbeat + DRBD (+ LVM)の自動フェイルオーバークラスタの出来上がりです。

DRBD + heartbeatはちゃんと設定すると色々と細かい制御ができていい感じなので、ぜひぜひ活用していきたいですね。