Amazon LinuxでDRBD 8.3.11を構築する

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

DRBDとは

DRBD(Distributed Replicated Block Device)は、ネットワークを通じてストレージ(ブロックデバイス)をリアルタイムに複製するソフトウェアです。この複製をレプリケーションといいまして、DRBDには3つのモードがあります。デフォルト設定では、同期レプリケーションを行います。同期は、ファイル単位ではなくブロックデバイス単位で必要最小限のデータのみ同期しますから効率が良いです。DRBDインストール後に、/etc/drbd.d/global_common.confを確認すると同期方法を確認できます。

  • プロトコルA:非同期レプリケーション
  • プロトコルB:メモリ同期(準同期)レプリケーション
  • プロトコルC:同期レプリケーション

今回は、Amazon Linux上にDRBDを構築して動作確認をしてみたいと思います。

セットアップ前の準備

まず、プライマリとセカンダリを設定するために2つのインスタンスを用意します。また、それぞれのインスタンスにEBSボリュームを1つ追加しておきます。Management Console等でEBSボリュームを作成してマウントしてください。これが同期用のデバイスとなります。Linux内ではxdvfという名前で登録されると思います。

$ ls /dev/xvdf

また、yumで各種ソフトウェアやカーネルを最新版にしておきましょう。

$ sudo yum update -y

DRBDのインストール

実は、Amazon Linuxには、初めからカーネルレベルでDRBDモジュールが入っています。確認をしてみます。

$ modprobe -l | grep drbd
kernel/drivers/block/drbd/drbd.ko

$ modinfo drbd | grep version
version:        8.3.11
srcversion:     2D876214BAAD53B31ADC1D6

で、このカーネルにインストールされているバージョンと同じものを、ユーザーランドにインストールします。ここからがハマったところだったのですが、yumでインストールするとカーネルよりも新しいバージョンをインストールしてしまいます。私が試したところ、カーネルが8.3.11で、ユーザーランドが8.3.13でした。バージョンが異なるとDRBDを起動できません。そこで、rpmを取得して手動でインストールします。

$ sudo rpm -Uvh http://elrepo.org/linux/elrepo/el5/x86_64/RPMS/drbd83-utils-8.3.11-1.el5.elrepo.x86_64.rpm

$ sudo modprobe -v drbd
insmod /lib/modules/3.2.21-1.32.6.amzn1.x86_64/kernel/drivers/connector/cn.ko 
insmod /lib/modules/3.2.21-1.32.6.amzn1.x86_64/kernel/lib/lru_cache.ko 
insmod /lib/modules/3.2.21-1.32.6.amzn1.x86_64/kernel/drivers/block/drbd/drbd.ko

さらにこれだけでも足りません。rpmで8.3.11をインストールした後にyum updateを行ってしまうと更新してしまいます。そこで、yum update時の除外ルールを設定します。

# vi /etc/yum.conf
[main]
exclude= *drbd*

インストールされているか、自動起動するか、確認してみましょう。

$ chkconfig --list drbd
drbd           	0:off	1:off	2:on	3:on	4:on	5:on	6:off

DRBDの初期設定

インストールが完了しましたので続いて同期するデバイスの設定を行います。以下のコマンドは、ループバックデバイスの作成を行っています。ループバックデバイスとは、普通のファイルをあたかもデバイスのように扱う機能です。ddで空ファイルを作成し、losetupで関連づけを行っています。

$ sudo dd if=/dev/zero of=/var/drbd-meta bs=1M count=128
128+0 records in
128+0 records out
134217728 bytes (134 MB) copied, 0.296614 s, 452 MB/s

$ sudo losetup /dev/loop0 /var/drbd-meta

続きまして、DRBDの設定ファイルを記述します。設定ファイルの場所は、/etc/drbd.d/内に記述します。global_common.confは全体設定で、.resファイルが個別設定です。今回は、drbd_res0.resというファイルを作成しました。deviceは、後でマウントして使うデバイス名を書きます。diskは、EBSでアタッチしたボリュームのデバイス名を書きます。meta-diskはループバックデバイスで作成したデバイス名です。onブロックは、プライマリとセカンダリのインスタンス情報を書きます。internalなホスト名を書いてください。ホスト名で.ap-northeast-1.compute.internalまでドメインで書くと反応しませんでした。publicドメインやIPを指定すると通信料金が多く掛かってしまいますので避けましょう。以下は記述例です。drbdが同期を行う際に使うポート番号として7788番を指定していますので、EC2のセキュリティグループで7788番での通信を許可してください。同一セキュリティグループからの7788番アクセスを許可すれば良いかと思います。

$ sudo vi /etc/drbd.d/drbd_res0.res

resource drbd_res0 {
  syncer {rate 50M;}
  device     /dev/drbd0;
  disk       /dev/xvdf;
  meta-disk  /dev/loop0[0];
  on ip-10-150-179-XXX {
    address    10.150.179.XXX:7788;
  }
  on ip-10-146-101-YYY {
    address    10.146.101.YYY:7788;
  }
}

ここまで設定がうまく行っていればDRBDの管理ツールを使ってメタデータを作成できるはずです。

$ sudo drbdadm create-md drbd_res0
  --==  Thank you for participating in the global usage survey  ==--
The server's response is:

you are the 1681th user to install this version
Writing meta data...
initializing activity log
NOT initialized bitmap
New drbd meta data block successfully created.
success

DRBDの起動

全て整いました!それでは、DRBDを起動しましょう。片方のインスタンスで起動すると、もう片方のインスタンスでのDRBD起動待ちとなります。全て同じようにもうひとつのインスタンスで設定を行って起動してください。すると、待ち状態から動作確認ができたということでコンソールに復帰します。

$ sudo service drbd start
  --==  Thank you for participating in the global usage survey  ==--
The server's response is:

node already registered
Starting DRBD resources: [ ].........

両方のインスタンスがちゃんと動いているか確認してみましょう。いくつかコマンドが提供されています。

$ sudo service drbd status
drbd driver loaded OK; device status:
version: 8.3.11 (api:88/proto:86-96)
srcversion: 2D876214BAAD53B31ADC1D6 
m:res        cs         ro                   ds                     p  mounted  fstype
0:drbd_res0  Connected  Secondary/Secondary  Inconsistent/Diskless  C

$ sudo drbd-overview
  0:drbd_res0  Connected Secondary/Secondary Inconsistent/Diskless C r----- 
  
$ sudo cat /proc/drbd
version: 8.3.11 (api:88/proto:86-96)
srcversion: 2D876214BAAD53B31ADC1D6 
 0: cs:Connected ro:Secondary/Secondary ds:Inconsistent/Diskless C r-----
    ns:0 nr:0 dw:0 dr:0 al:0 bm:0 lo:0 pe:0 ua:0 ap:0 ep:1 wo:f oos:5242624

ポイントは、Secondary/Secondaryという部分です。これもハマりポイントでした。DRBDの場合、プライマリに昇格させてからデバイスをマウントします。そして、ファイルの書き込み操作を行うと裏で同期レプリケーションしてくれるのです。ということで、片方のインスタンスで以下のコマンドを打ちます。両方でやってはダメです。両方プライマリにはなれません。

プライマリとセカンダリ

$ sudo drbdadm -- --overwrite-data-of-peer primary drbd_res0
  --==  Thank you for participating in the global usage survey  ==--
The server's response is:

または

$ sudo drbdadm -- primary drbd_res0

初期動作に置いて、--overwrite-data-of-peerオプションを指定すると、ただちに両デバイス間でフル同期作業が始まります。初めてでなければオプションを外しても大丈夫です。プライマリに昇格したか確認してみましょう。

$ sudo cat /proc/drbd
version: 8.3.11 (api:88/proto:86-96)
srcversion: 2D876214BAAD53B31ADC1D6 
 0: cs:Connected ro:Primary/Secondary ds:UpToDate/UpToDate C r-----
    ns:0 nr:0 dw:0 dr:664 al:0 bm:0 lo:0 pe:0 ua:0 ap:0 ep:1 wo:f oos:0

同期レプリケーションの確認

先ほど、drbd_res0.resのdeviceにてデバイス指定をしました。ここに書き込まれた内容が同期されます。そこで、まずはデバイスを初期化してマウントします。xfsファイルフォーマットを使ってみたいと思います。

$ sudo yum install xfs*

$ sudo mkfs.xfs /dev/drbd0
meta-data=/dev/drbd0             isize=256    agcount=4, agsize=327680 blks
         =                       sectsz=512   attr=2
data     =                       bsize=4096   blocks=1310720, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0
log      =internal log           bsize=4096   blocks=2560, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0

マウントするディレクトリーを作成します。そして、マウントします。

$ sudo mkdir /data

$ sudo mount /dev/drbd0 /data

ファイルを書き込んでみましょう。

$ sudo touch /data/hello.txt
$ ls /data
hello.txt

これで、裏側ではプライマリとセカンダリの間で同期レプリケーションが行われています。DRBDの同期レプリケーションは、プライマリとセカンダリへの同期が全て終わってから書き込み完了となります。ブロックデバイス単位での同期ですので、ユーザやプロセスが考慮する必要がなく、いつもと同じようにマウントしたデバイスを使えるのがDRBDの良いところですね。

セカンダリを昇格させる

セカンダリをプライマリへ昇格させて、もう片方のインスタンスにデータが同期されているか確認します。まずは、プライマリのデバイスをアンマウントしてセカンダリへ降格させます。

$ sudo umount /data
$ sudo drbdadm secondary drbd_res0
$ sudo cat /proc/drbd
version: 8.3.11 (api:88/proto:86-96)
srcversion: 2D876214BAAD53B31ADC1D6 
 0: cs:Connected ro:Secondary/Secondary ds:UpToDate/UpToDate C r-----
    ns:2077 nr:0 dw:2077 dr:1149 al:2 bm:0 lo:0 pe:0 ua:0 ap:0 ep:1 wo:f oos:0

プライマリ/セカンダリだったものが、セカンダリ/セカンダリになりました。次にもう片方のインスタンスから以下のコマンドでプライマリへ昇格させます。

$ sudo cat /proc/drbd
version: 8.3.11 (api:88/proto:86-96)
srcversion: 2D876214BAAD53B31ADC1D6 
 0: cs:Connected ro:Secondary/Secondary ds:UpToDate/UpToDate C r-----
    ns:0 nr:2077 dw:2077 dr:0 al:0 bm:0 lo:0 pe:0 ua:0 ap:0 ep:1 wo:f oos:0

$ sudo drbdadm primary drbd_res0

$ sudo cat /proc/drbd                              
version: 8.3.11 (api:88/proto:86-96)
srcversion: 2D876214BAAD53B31ADC1D6 
 0: cs:Connected ro:Primary/Secondary ds:UpToDate/UpToDate C r-----
    ns:0 nr:2077 dw:2077 dr:664 al:0 bm:0 lo:0 pe:0 ua:0 ap:0 ep:1 wo:f oos:0
    
$ sudo mount /dev/drbd0 /data

そして、最後のデータ確認です!!!!

$ ls /data
hello.txt

やったーーー、できたーーー!

まとめ

いやぁ、時間掛かったよw。DRBDよりもLinuxの操作理解に時間掛かった。例えば、アンマウントできなくって困っていたら、自分がそのディレクトリに居たとか、カーネルバージョンとユーザーランドバージョンが異なっていたとか、yum updateで勝手に更新されないようにするとか。さらに、AWS部分では、ルートデバイスではなくアタッチしたEBSを使っていたり、internalのIPを使う部分であったり、2つのインスタンスを違うデータセンターに置いたり(Availability Zone)とか。他にも伝えたいことはたくさんあるのですが、続きは次回ということでお楽しみに。今日から君も同期レプリケーションマスターだぁ!

参考資料

DRBDってなに?

[RHEL][DRBD] Linux+DRBDで作るサーバ冗長構成

DRBD on Amazon’s Linux