harumaki.net

インフラ屋の覚書や、ラーメン食べある記とか。

オープンソースでのクラスタリング環境構築/DRBD

   


オープンソースでのクラスタリング環境構築/DRBD

ネットワークに接続されたホスト間でのディスクミラーリング機能を提供。
GNU GPLに準拠。
特徴としては

  • リアルタイムミラーリングでディスク共有
  • 書き込み時のノードの排他制御あり

なので、こんなときに便利かも。

  • NFSを使ったクラスタ構成のサーバを作りたいけど、共有ディスクが無い
  • 金をかけずに冗長構成をしたい

heartbeat?との親和性もあり、有用になるかも。
というよりは後述の理由により、heartbeat?との組み合わせは
はずすことが出来ないと思われ…

テスト環境

今回のテスト環境の設定は以下の通り。

  • プライマリ
    • ホスト名:test01
    • IPアドレス:192.168.0.12
  • セカンダリ
    • ホスト名:test02
    • IPアドレス:192.168.0.13

1)パッケージのビルド/インストール

使用バージョンは0.7.21。

1-1.パッケージのビルド

ソースアーカイブにspecファイルが含まれており、せっかくなので
RPMパッケージをビルドしてインストールする。

  1. ソースのダウンロード
    # cd /usr/local/src
    # wget http://oss.linbit.com/drbd/0.7/drbd-0.7.21.tar.gz
  2. RPMパッケージのビルド
    ソースアーカイブを所定のディレクトリへコピー

    # cp drbd-0.7.21.tar.gz /usr/src/redhat/SOURCE/
  3. ソースを展開し、specファイルを所定のディレクトリへ移動
    # tar -zxvf drbd-0.7.21.tar.gz
    # cd drdb-0.7.21/
    # cp drdb.spec.in /usr/src/redhat/SPEC/drdb.spec
  4. specファイルを編集
    # vi /usr/src/redhat/SPEC/drdb.spec
    [差分]
    22c22
    < Version: 
    ---
    > Version: 0.7.21
    29d28
    < Packager: 
  5. パッケージをビルド(リコンパイル用にソースRPMも同時にビルド)
    # rpmbuild -bb drdb.spec
  • ビルドしたパッケージの一覧
    /usr/src/redhat/SRPMS/drbd-0.7.21-1.src.rpm
    /usr/src/redhat/RPMS/i386/drbd-0.7.21-1.i386.rpm
    /usr/src/redhat/RPMS/i386/drbd-km-2.6.9_34.ELsmp-0.7.21-1.i386.rpm
    /usr/src/redhat/RPMS/i386/drbd-debuginfo-0.7.21-1.i386.rpm

1-2.インストール

ビルドされたパッケージをまとめてインストールするだけ。

  1. まずDRBD本体をインストール
    # rpm -ivh drbd-0.7.21-1.i386.rpm 
  2. 続けてDRBDのカーネルモジュールをインストール。
    # rpm -ivh drbd-km-2.6.9_34.ELsmp-0.7.21-1.i386.rpm

    同時にインストールしても問題なし。
    インストールが正常終了したらOSをリブート。

2)環境設定

ミラーリングに使用する領域を作成する。

2-1.DRBD用パーティションの準備

事前に仮想ディスクを用意する。
ここではSCSIを/dev/sdbとして用意。

2-2.共有ディスクのフォーマット(主系・副系共通)

DRBDを構成するデータ領域は1ノードあたり最低2つ必要となる。それぞれ128MB以上を割り当てる。

  • 通常のデータ領域
    ファイルシステムをマウントする、通常の領域。
  • メタデータ領域
    ディスク同期処理の際の差分の書き込みに使用する。

パーティションはひとつにまとめることも可能だが、出来れば領域ごとに
分けておくのが無難(だと思う)。
ここではメタデータ用は/dev/sdb1、通常のデータはdev/sdb2とする。
※結局1GBの領域を半分づつ分けてしまったw

  • フォーマット手順
    # fdisk /dev/sdb
    
    コマンド (m でヘルプ): n			←パーティション作成
    コマンドアクション
       e   拡張
       p   基本領域 (1-4)
    p					←基本領域作成のためpを選択(1つめ)
    領域番号 (1-4): 1				←領域番号1を入力(sdb1に割り当て)
    最初 シリンダ (1-130, default 1):	 	←開始シリンダ番号を入力(デフォルト値のままなのでEnter)
    Using default value 1
    終点 シリンダ または +サイズ または +サイズM
    または +サイズK (1-130, default 130): 65		←終点シリンダ番号を入力
    
    コマンド (m でヘルプ): n			←パーティション作成
    コマンドアクション
       e   拡張
       p   基本領域 (1-4)
    p					←基本領域作成のためpを選択(2つめ)
    領域番号 (1-4): 2				←領域番号2を入力(sdb2に割り当て)
    最初 シリンダ (66-130, default 66): 
    Using default value 66			←開始シリンダ番号を入力(デフォルト値のままなのでEnter)
    終点 シリンダ または +サイズ または +サイズM
    または +サイズK (66-130, default 130): 		←終点シリンダ番号を入力(終点まで使うのでEnter)
    Using default value 130
    
    コマンド (m でヘルプ): p			←領域を確認
    
    Disk /dev/sdb: 1073 MB, 1073741824 bytes
    255 heads, 63 sectors/track, 130 cylinders
    Units = シリンダ数 of 16065 * 512 = 8225280 bytes
    
    デバイス Boot       Start         End      Blocks   Id  System
    /dev/sdb1               1          65      522081   83  Linux
    /dev/sdb2              66         130      522112+  83  Linux
    
    コマンド (m でヘルプ): w			←設定を反映し、領域を作成する
    領域テーブルは交換されました!
    
    ioctl() を呼び出して領域テーブルを再読込みします。
    ディスクを同期させます。
    # 

    ※この時点ではまだファイルシステムは作成しない

2-3.設定ファイルの編集

DRBDの設定ファイルは/etc/drbd.confだが、空白の状態のため
サンプルとして用意されている/usr/share/doc/drbd-0.7.21/drbd.confをベースに
設定を進める。

※主系・副系で同じ設定にすること。

# cp /usr/share/doc/drbd-0.7.21/drbd.conf /etc/
cp: `/etc/drbd.conf' を上書きしてもよろしいですか(yes/no)? yes
# vi drbd.conf
  • [設定内容]
    resource r0 {
      protocol C;
      incon-degr-cmd "echo '!DRBD! pri on incon-degr' | wall ; sleep 60 ; \			┐
      halt -f";  startup {    wfc-timeout  0;    degr-wfc-timeout 120;    # 2 minutes.  } \	│実際は1行
      disk {    on-io-error   panic;  }  net {  }					┘
      syncer {
       rate 10M;
       group 1;
        al-extents 257;
      }
    
      on test01 {
        device     /dev/drbd0;
        disk       /dev/sdb2;
        address    192.168.0.12:7788;
        meta-disk  /dev/sdb1[0];
      }
    
      on test02 {
        device     /dev/drbd0;
        disk       /dev/sdb2;
        address    192.168.0.13:7788;
        meta-disk  /dev/sdb1[0];
      }
    }

    ※設定が完了したら副系へファイルをコピー。

3)動作検証

3-1.DRBDモジュールのロード

RPMでインストールした場合は、OS再起動時にモジュールが読み込まれるので
確認のみでOK。

# lsmod | grep drbd
drbd                  138464  1 

3-2.DRBDの起動と状態確認

DRBDの起動はプライマリとするノードから実行する。

▼主系(test01)

  1. DRBD起動
    # drbdadm up all
  2. 状態確認
    セカンダリ側が起動していないので、接続できていない状態になる。

    # cat /proc/drbd 
    version: 0.7.21 (api:79/proto:74)
    SVN Revision: 2326 build by , 20yy-mm-dd 15:47:30
     0: cs:WFConnection st:Secondary/Unknown ld:Inconsistent
        ns:0 nr:0 dw:0 dr:0 al:0 bm:64 lo:0 pe:0 ua:0 ap:0
    # 

▼副系(test02)

  1. DRBD起動
    # drbdadm up all
  2. 状態確認
    プライマリ側との接続が確立され、ステータスが変化する。

    # cat /proc/drbd 
    ersion: 0.7.21 (api:79/proto:74)
    SVN Revision: 2326 build by root@host.example.com, 20yy-mm-dd 17:11:52
     0: cs:Connected st:Secondary/Secondary ld:Inconsistent	←接続状態が"Connected"となる
        ns:0 nr:0 dw:0 dr:0 al:0 bm:64 lo:0 pe:0 ua:0 ap:0

3-3.Primary状態への移行

初回は各ローカルディスクの状態は接続後も"Inconsistent"になっているため
プライマリ側のステータスをPrimaryに強制変更する。

  • ステータスを変更
    # drbdadm -- --do-what-I-say primary all

3-4.状態確認

プライマリ側のステータスが以下のように変更される。
同時にプライマリ・セカンダリのデータ同期が開始される。

# cat /proc/drbd 
version: 0.7.21 (api:79/proto:74)
SVN Revision: 2326 build by root@host.example.com, 20yy-mm-dd 15:47:30
 0: cs:SyncSource st:Primary/Secondary ld:Consistent			←SecondaryからPrimaryに変更
    ns:49492 nr:0 dw:0 dr:49888 al:0 bm:66 lo:0 pe:89 ua:99 ap:0
        [==>.................] sync'ed: 10.2% (472972/522112)K		←データ同期状況
        finish: 0:01:07 speed: 7,020 (7,020) K/sec
#

3-5.データの同期

上記4の状態確認のうち、ステータスを確認すると
cs(接続状態)が "SyncSource"となっていることが確認できる。
またデータ同期率のゲージが表示されるので、完了までの目安とすることができる。

  • [上記4の状態確認の抜粋]
     0: cs:SyncSource st:Primary/Secondary ld:Consistent
        ns:49492 nr:0 dw:0 dr:49888 al:0 bm:66 lo:0 pe:89 ua:99 ap:0
            [==>.................] sync'ed: 10.2% (472972/522112)K
             finish: 0:01:07 speed: 7,020 (7,020) K/sec

3-6.同期完了の確認

データ同期が完了すると、ns、drに同期が行われたバイト数が表示される。

# cat /proc/drbd 
version: 0.7.21 (api:79/proto:74)
SVN Revision: 2326 build by root@host.example.com, 20yy-mm-dd 15:47:30
 0: cs:Connected st:Primary/Secondary ld:Consistent
    ns:522112 nr:0 dw:0 dr:522112 al:0 bm:96 lo:0 pe:0 ua:0 ap:0

4)ファイルシステムの作成

DRBDの動作確認が出来たらファイルシステムを作成。
作成の際はかならずプライマリノードになっている必要がある。
指定するデバイスは/dev/drbd0。

▼主系
もともとプライマリなので、ノード状態を確認して問題なければ
ファイルシステムを作成する。

  1. ノード状態の確認
    # drbdadm state all
    Primary/Secondary
  2. ファイルシステムを作成
    # mke2fs -j /dev/drbd0 

    作成後、任意のディレクトリにマウントして運用。

▼副系
副系は通常セカンダリとなるので、確認したら一時的にプライマリに
変更する。

  1. 副系のノード状態の確認
    # drbdadm state all
    Secondary/Primary
  2. 主系のDRBDデバイスを切断する(主系で実施)
    # drbdadm down all
  3. 副系をプライマリノードに指定
    # drbdadm -- --do-what-I-say primary all
  4. ファイルシステムを作成
    # mke2fs -j /dev/drbd0 

5)サービスの自動起動

インストール後に/etc/init.d/にサービススクリプトが置かれるので
通常はこちらから起動してもオッケー。

最後にchkconfigで自動起動の登録をおこなう。
/etc/init.d/drbdではサービス起動/停止/再起動、ステータス確認が可能。
ステータスの出力内容は/proc/drbdの内容と同じ。

※但し備考欄にもあるが、あくまでサービスが起動するだけでステータス変更や
ファイルシステムへのマウントは行われない。

備考

DRBDには起動時にプライマリの指定やディスクマウントの処理を行うための
サービス用スクリプトが用意されておらず、initスクリプトで起動しても
起動直後は/dev/drbd*デバイスが存在するのみで、両ノードともにセカンダリ状態で、かつマウントされない。
そのため以下の作業ないし設定が必要となる。

  • 手動でマウント
  • rc.localなどに書き込む
  • ブート時にプライマリ指定、マウントを実行するスクリプトを作成する

heartbeat?DRBD用のリソース用スクリプトが含まれており、
 
DRBD+heartbeat?の組み合わせでステータス変更、マウントまで自動実行が可能になる。

 - cluster, GNU/Linux, infra