DRBDについて調べたのでまとめた
DRBDを使う上で必要そうな部分を調べたのでまとめです。
もしかすると、通知関連を調べて後日載せるかもしれません。
インストール
前提
- CentOS 7 + ELRepoのDRBDを想定しています。
- Primary NodeとSecondary NodeはIP Reachableである必要があります。
- /dev/sdbを同期する設定としています。(/dev/sdaはOSが利用。)
- DRBD 8.4のドキュメントはこちら。
ここでは、CentOS 7(+ yum update)がインストール済みでIP Reachableな環境がすでに存在する所から説明します。
具体的にはIDCF Cloudに標準で用意されているCentOS 7へデータディスクを1台接続し、追加ネットワークを利用してDRBDの同期セグメントとしました。また、余談ですがプライベートコネクトを利用し、ゾーン間やリージョン間でも問題なくDRBDの同期セグメントとして利用できることを確認しています。
ELRepoを有効に
ELRepoのトップページにGet startedがあるため、特に迷うことはないと思いますが、簡単に記載しておきます。基本的にはレポジトリのrpmをいれれば有効にできます。
# yum -y install http://elrepo.org/linux/elrepo/el7/x86_64/RPMS/elrepo-release-7.0-2.el7.elrepo.noarch.rpm
最新版はのrpmはこの辺から確認しましょう。
DRBDをインストール
# yum -y install drbd84-utils kmod-drbd84
DRBDの設定
コンフィグファイルとしては/etc/drbd.d/global_common.conf
と/etc/drbd.d/*.res
となります。*.res
は各リソースの設定(要するにsyncさせたいディスクの設定)となります。今回は*.res
はr1.res
としています。
/etc/drbd.d/global_common.conf
については基本的には変更不要です。
global_common.conf
のglobalセクションにあるusage-countはDRBDプロジェクトがDRBDの利用状況についての統計を取るための設定であり、DRBDがインストールされるたびにHTTP接続が発生します。情報取得とHTTP接続を気にされるようであれば、設定でno
に変更してください。
global {
usage-count no;
# minor-count dialog-refresh disable-ip-verification
# cmd-timeout-short 5; cmd-timeout-medium 121; cmd-timeout-long 600;
}
リソース設定は、今回/etc/drbd.d/r1.res
へ記載します。色々と確認したのですが、現状では下記のコンフィグがベストとしています。
resource r1 {
floating ipv4 192.168.15.xxx:7788 {
volume 0 {
device /dev/drbd0 minor 0;
disk /dev/sdb;
meta-disk internal;
}
}
floating ipv4 192.168.15.xxx:7788 {
volume 0 {
device /dev/drbd0 minor 0;
disk /dev/sdb;
meta-disk internal;
}
}
net {
protocol C;
max-buffers 8000;
max-epoch-size 8000;
}
disk {
al-extents 3389;
disk-barrier no;
disk-flushes no;
}
}
- チューニングガイドを参考に設定値を色々変えてみましたが、MySQLでsysbenchかける程度では差がほとんど無かったです。
- レプリケーションのモードのProtocol Cは完全同期モードで、BやAは準同期、非同期だが、B,Aでもパフォーマンスは上がらなかったです。(同様にMySQLでsysbench程度では。)
-
設定例などでは、
on hostname { address ... }
と記載されていますが、_hostname_など書きたくなかったのでfloating
を利用しています。 - 異論はありそうですが、とりあえずはこんな感じです。
メタデータを作成と起動
この手順は初めてDRBDを起動するときにだけ必要な操作です。
この操作はPrimary/Seconday両ノードに対して実行します。
# drbdadm create-md r1
New drbd meta data block successfully created.
# drbdadm up r1
r1
はr1.resで定義した物です。
メタデータはディスクの末尾の領域に確保されます。
drbdの状態は/proc/drbd
を見ることで確認できます。
# cat /proc/drbd
version: 8.4.6 (api:1/proto:86-101)
GIT-hash: 833d830e0152d1e457fa7856e71e11248ccf3f70 build by phil@Build64R7, 2015-04-10 05:13:52
0: cs:Connected ro:Secondary/Secondary ds:Inconsistent/Inconsistent 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:41941724
両ノードでdrbdadm up r1
まで実行すると、cs:Connected ro:Secondary/Secondary ds:Inconsistent/Inconsistent
になります。
データシンク
cs:Connected ro:Secondary/Secondary ds:Inconsistent/Inconsistent
ここまで来たら、どちらかのノードをPrimaryとしてデータを同期するのですが、空っぽのディスクを同期しても時間の無駄なので、初期同期をスキップします。
# drbdadm new-current-uuid --clear-bitmap r1/0
# cat /proc/drbd
version: 8.4.7-1 (api:1/proto:86-101)
GIT-hash: 3a6a769340ef93b1ba2792c6461250790795db49 build by phil@Build64R7, 2016-01-12 14:29:40
0: cs:Connected ro:Secondary/Secondary ds:UpToDate/UpToDate C r-----
ns:0 nr:21879057 dw:21879057 dr:0 al:8 bm:0 lo:0 pe:0 ua:0 ap:0 ep:1 wo:d oos:0
r1/0
はr1.res
で定義したリソース名とボリューム番号です。
ds:UpToDate/UpToDateになれば同期完了の意味です。
これで、同期が完了している状態となるので、利用する側をPrimaryとして設定します。
# drbdadm primary r1
# cat /proc/drbd
version: 8.4.7-1 (api:1/proto:86-101)
GIT-hash: 3a6a769340ef93b1ba2792c6461250790795db49 build by phil@Build64R7, 2016-01-12 14:29:40
0: cs:Connected ro:Primary/Secondary ds:UpToDate/UpToDate C r-----
ns:0 nr:0 dw:0 dr:912 al:0 bm:0 lo:0 pe:0 ua:0 ap:0 ep:1 wo:d oos:0
ro:Secondary/Secondary
からro:Primary/Secondary
に変わりました。なお、Secondary側で実行するとro:Secondary/Primary
となります。自ノードが先に表示されるので、自分がPrimaryなのかSecondaryなのかが分かります。
なお、フル同期する場合は、Primary側で下記のように実行します。
# drbdadm --force primary resource1
こちらは強制的にPrimaryになり、Secondary側はデータ同期が自動的に始まります。
同期進行中は次のようになります。
# cat /proc/drbd
version: 8.4.6 (api:1/proto:86-101)
GIT-hash: 833d830e0152d1e457fa7856e71e11248ccf3f70 build by phil@Build64R7, 2015-04-10 05:13:52
0: cs:SyncSource ro:Primary/Secondary ds:UpToDate/Inconsistent C r-----
ns:794524 nr:0 dw:0 dr:795436 al:0 bm:0 lo:0 pe:1 ua:0 ap:0 ep:1 wo:f oos:41147712
[>....................] sync'ed: 2.0% (40180/40956)M
finish: 0:37:18 speed: 18,372 (14,980) K/sec
フォーマットして使う
drbdを起動してどちらかをPrimaryとすると、Primary側で/dev/drbd0
が作成されます。/dev/drbd0
は通常のブロックデバイスとして利用できます。Secondary側は/dev/drbd0
が作成されないため利用することはできません。
普通のブロックデバイスと何も変わらないため、LVMしたり、そのままフォーマットしたりして利用できます。
今回は、前提に書いた通りIDCF Cloudを利用しています。IDCF Cloudでは、ボリュームのリサイズがオンラインで可能です。そして、DRBDもオンラインでディスク拡張をサポートしています。
といことで、LVMせずにオンライン拡張をやりたいので、そのままフォーマットして使います。(ディスクを束ねたり、パーティションを切るのであればLVMしましょう。)
書くまでもないですが、次のとおりです。
# mkfs.xfs -b size=1024 /dev/drbd0
ブロックサイズを指定していますが、単純にMySQLで利用する場合に1024の方が早かったからです。環境に依存する部分ですね。
これも書くまでもないですが、マウントです。
# mount -t xfs -o noatime,nodiratime,nobarrier /dev/drbd0 /var/lib/mysql/
オプションも適当です。なんでも使えます。
DRBDの起動と停止とPrimary
# drbdadm up r1
# drbdadm down r1
# drbdadm primary r1
起動しただけではro:Secondary/Secondary
になるので、どちらかをPrimaryとする必要があります。なお、Primaryで既に利用中の場合(マウントしている場合)はdownさせることはできません。
なので、Primaryにする側でdrbdadm primary r1
を実行してください。
ディスク拡張
一つ前にも書きましたが、IDCF Cloudでは、ボリュームのリサイズがオンラインで可能です。そして、DRBDもオンラインでディスク拡張をサポートしています。
やってみましょう。
IDCF Cloud側でボリュームのリサイズ
Cloudコンソール(もしくはAPI)のボリュームメニューから対象ボリュームを選択し、リサイズを実行したください。Primary/Secondary双方で実行しておきます。
仮想マシン選択 => ボリューム => ボリューム操作へ、の方がたどりやすいと思います。
OSに認識させる
ディスクが拡張されたことをOS側に認識させる必要があります。
CentOS 7ではblockdevを使って簡単に認識させる事ができます。
# fdisk -l /dev/sdb
Disk /dev/sdb: 53.7 GB, 53687091200 bytes, 104857600 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O サイズ (最小 / 推奨): 512 バイト / 512 バイト
# blockdev --rereadpt /dev/sdb
# fdisk -l /dev/sdb
Disk /dev/sdb: 64.4 GB, 64424509440 bytes, 125829120 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O サイズ (最小 / 推奨): 512 バイト / 512 バイト
53.7GBから64.4GBになっている事がわかります。
なお、以下でも同様にOSに拡張されたことを認識させる事ができます。
# echo 1 > /sys/class/scsi_device/<device>/device/rescan
注意: なお、この段階でdrbdadm down r1
などとdownさせてしまうとメタデータが発見できなくなり(メタデータがディスクの末尾に存在するため。拡張されて末尾が変わったから。)drbdadm up r1
できなくなってしまいますので、注意してください。(もちろん1回ハマった。)
drbd側を拡張
Primary側で下記を実行します。なお、このやり方は追加した領域の同期をスキップさせるやり方です。初期同期と同様に空の部分を同期しても仕方ない為です。
# drbdadm -- --assume-clean resize r1
メタデータの移動などもすべて自動で行ってくれます。
ファイルシステムを拡張
今回はXFSでフォーマットしていますので、xfs_growfsで拡張します。これもオンラインで可能です。ext4であれば、resize2fsでオンラインのまま拡張できます。
# xfs_growfs /var/lib/mysql/
meta-data=/dev/drbd0 isize=256 agcount=4, agsize=2621351 blks
= sectsz=512 attr=2, projid32bit=1
= crc=0 finobt=0
data = bsize=1024 blocks=10485404, imaxpct=25
= sunit=0 swidth=0 blks
naming =version 2 bsize=4096 ascii-ci=0 ftype=0
log =internal bsize=1024 blocks=10240, version=2
= sectsz=512 sunit=0 blks, lazy-count=1
realtime =none extsz=4096 blocks=0, rtextents=0
data blocks changed from 10485404 to 47184444
ディスクが壊れた時の対応と壊れたときの動作を確認
Cloudの場合、ディスクだけ壊れる事はほとんど無いと思いますが、ディスクの取り外しなども容易に試せるので、実験してみます。
また、DRBDはディスクが故障した時に故障したことを上位レイヤー(ファイルシステム)に通知しない、と行った設定が可能(デフォルト)で、そうするとどうなるかというと、Secondary側からデータを引っ張ってきてディスクは生きているかのように振舞ってくれます。つまり上で動いているサービスは継続されることになります。凄いですね!
ディスク(ボリューム)を取り外す
IDCF CloudのCloudコンソール(もしくはAPI)から対象のボリュームを選択しデタッチします。この時仮想マシンはオンラインのままデタッチします。
OSから見ると、いきなりSCSI Diskが無くなった様に見えます。
# lsscsi
[0:0:0:0] cd/dvd NECVMWar VMware IDE CDR00 1.00 /dev/sr0
[2:0:0:0] disk VMware Virtual disk 1.0 /dev/sda
[2:0:1:0] disk VMware Virtual disk 1.0 /dev/sdb
# cat /proc/drbd
version: 8.4.7-1 (api:1/proto:86-101)
GIT-hash: 3a6a769340ef93b1ba2792c6461250790795db49 build by phil@Build64R7, 2016-01-12 14:29:40
0: cs:Connected ro:Primary/Secondary ds:UpToDate/UpToDate C r-----
ns:0 nr:0 dw:0 dr:912 al:0 bm:0 lo:0 pe:0 ua:0 ap:0 ep:1 wo:d oos:0
# df -h /var/lib/mysql
ファイルシス サイズ 使用 残り 使用% マウント位置
/dev/drbd0 45G 3.7G 42G 9% /var/lib/mysql
# echo "ABC" > /var/lib/mysql/write_ok.txt
# sync
# ls -la /var/lib/mysql/write_ok.txt
-rw-r--r-- 1 root root 4 3月 10 11:58 /var/lib/mysql/write_ok.txt
# lsscsi
[0:0:0:0] cd/dvd NECVMWar VMware IDE CDR00 1.00 /dev/sr0
[2:0:0:0] disk VMware Virtual disk 1.0 /dev/sda
[2:0:1:0] disk VMware Virtual disk 1.0 /dev/sdb
# cat /proc/drbd
version: 8.4.7-1 (api:1/proto:86-101)
GIT-hash: 3a6a769340ef93b1ba2792c6461250790795db49 build by phil@Build64R7, 2016-01-12 14:29:40
0: cs:Connected ro:Primary/Secondary ds:Diskless/UpToDate C r-----
ns:2076 nr:24580 dw:26624 dr:3720 al:3 bm:0 lo:0 pe:0 ua:0 ap:0 ep:1 wo:d oos:0
# df -h /var/lib/mysql
ファイルシス サイズ 使用 残り 使用% マウント位置
/dev/drbd0 45G 3.7G 42G 9% /var/lib/mysql
# echo "ABC" > /var/lib/mysql/write_ok2.txt
# ls -la /var/lib/mysql/write_ok2.txt
-rw-r--r-- 1 root root 4 3月 10 13:46 /var/lib/mysql/write_ok2.txt
表面上は何事もなく利用できている事がわかります。
/proc/drbd
でds:Diskless/UpToDate
とDisklessと言うステータスに代わっていることぐらいです。
# # dmesg | tail -n 20
[172736.739903] sd 2:0:1:0: [sdb] FAILED Result: hostbyte=DID_NO_CONNECT driverbyte=DRIVER_OK
[172736.739916] sd 2:0:1:0: [sdb] CDB: Read(10) 28 00 00 00 00 02 00 00 01 00
[172736.739921] blk_update_request: I/O error, dev sdb, sector 2
[172736.739964] block drbd0: local READ IO error sector 2+1 on sdb
[172736.739971] block drbd0: disk( UpToDate -> Failed )
[172736.739987] block drbd0: Local IO failed in __req_mod. Detaching...
[172736.740103] sd 2:0:1:0: [sdb] FAILED Result: hostbyte=DID_NO_CONNECT driverbyte=DRIVER_OK
[172736.740106] sd 2:0:1:0: [sdb] CDB: Write(10) 2a 00 05 9f f4 78 00 00 08 00
[172736.740108] blk_update_request: I/O error, dev sdb, sector 94368888
[172736.740131] block drbd0: IO ERROR -5 on bitmap page idx 0
[172736.740162] block drbd0: bitmap WRITE of 1 pages took 0 jiffies
[172736.740163] block drbd0: we had at least one MD IO ERROR during bitmap IO
[172736.740186] block drbd0: 4 KB (1 bits) marked out-of-sync by on disk bit-map.
[172736.740211] sd 2:0:1:0: [sdb] FAILED Result: hostbyte=DID_NO_CONNECT driverbyte=DRIVER_OK
[172736.740213] sd 2:0:1:0: [sdb] CDB: Write(10) 2a 00 05 9f ff f8 00 00 08 00
[172736.740214] blk_update_request: I/O error, dev sdb, sector 94371832
[172736.740361] block drbd0: drbd_md_sync_page_io(,94371832s,WRITE) failed with error -5
[172736.740396] block drbd0: meta data update failed!
[172736.740414] block drbd0: disk( Failed -> Diskless )
[172736.742766] block drbd0: receiver updated UUIDs to effective data uuid: 757734BAC87B2EC0
# tail -n 22 /var/log/messages
Mar 10 13:43:36 localhost kernel: sd 2:0:1:0: [sdb] FAILED Result: hostbyte=DID_NO_CONNECT driverbyte=DRIVER_OK
Mar 10 13:43:36 localhost kernel: sd 2:0:1:0: [sdb] CDB: Read(10) 28 00 00 00 00 02 00 00 01 00
Mar 10 13:43:36 localhost kernel: blk_update_request: I/O error, dev sdb, sector 2
Mar 10 13:43:36 localhost kernel: block drbd0: local READ IO error sector 2+1 on sdb
Mar 10 13:43:36 localhost kernel: block drbd0: disk( UpToDate -> Failed )
Mar 10 13:43:36 localhost kernel: block drbd0: Local IO failed in __req_mod. Detaching...
Mar 10 13:43:36 localhost kernel: sd 2:0:1:0: [sdb] FAILED Result: hostbyte=DID_NO_CONNECT driverbyte=DRIVER_OK
Mar 10 13:43:36 localhost kernel: sd 2:0:1:0: [sdb] CDB: Write(10) 2a 00 05 9f f4 78 00 00 08 00
Mar 10 13:43:36 localhost kernel: blk_update_request: I/O error, dev sdb, sector 94368888
Mar 10 13:43:36 localhost kernel: block drbd0: IO ERROR -5 on bitmap page idx 0
Mar 10 13:43:36 localhost kernel: block drbd0: bitmap WRITE of 1 pages took 0 jiffies
Mar 10 13:43:36 localhost kernel: block drbd0: we had at least one MD IO ERROR during bitmap IO
Mar 10 13:43:36 localhost kernel: block drbd0: 4 KB (1 bits) marked out-of-sync by on disk bit-map.
Mar 10 13:43:36 localhost kernel: sd 2:0:1:0: [sdb] FAILED Result: hostbyte=DID_NO_CONNECT driverbyte=DRIVER_OK
Mar 10 13:43:36 localhost kernel: sd 2:0:1:0: [sdb] CDB: Write(10) 2a 00 05 9f ff f8 00 00 08 00
Mar 10 13:43:36 localhost kernel: blk_update_request: I/O error, dev sdb, sector 94371832
Mar 10 13:43:36 localhost kernel: block drbd0: drbd_md_sync_page_io(,94371832s,WRITE) failed with error -5
Mar 10 13:43:36 localhost kernel: block drbd0: meta data update failed!
Mar 10 13:43:36 localhost kernel: block drbd0: disk( Failed -> Diskless )
Mar 10 13:43:36 localhost kernel: block drbd0: receiver updated UUIDs to effective data uuid: 757734BAC87B2EC0
流石にOSのログにはそこそこ色々出ていますね。DRBDのStatusはUptoDate -> Failed -> Disklessと変わって行った事がわかります。
壊れたディスクを交換
一つ前でdetachVolumeしてしまったディスクは捨てて、新規にディスクを接続しPrimaryのディスクを復元してみます。
壊れたディスクをOSから切り離す
detachVolumeしてしまっているので、既に接続はされいないのですが、OSはまだあるものとして処理しています。まず、壊れたディスクをOSから切り離します。
SCSI Diskはecho 1 > /sys/block/sdb/device/delete
で切り離す事ができます。
# lsscsi
[0:0:0:0] cd/dvd NECVMWar VMware IDE CDR00 1.00 /dev/sr0
[2:0:0:0] disk VMware Virtual disk 1.0 /dev/sda
[2:0:1:0] disk VMware Virtual disk 1.0 /dev/sdb
# echo 1 > /sys/block/sdb/device/delete
# lsscsi
[0:0:0:0] cd/dvd NECVMWar VMware IDE CDR00 1.00 /dev/sr0
[2:0:0:0] disk VMware Virtual disk 1.0 /dev/sda
これで/dev/sdb
を切り離せました。
ディスク(ボリューム)の追加
IDCF CloudのCloudコンソール(もしくはAPI)からボリュームを作成(Secondary側と同サイズ)してPrimary Nodeの仮想マシンへアタッチします。(ボリューム => ボリューム作成 => できたボリューム選択 => アタッチ)
仮想マシンはオンラインのままボリュームのアタッチを行います。
OSに追加したディスクを認識させる
SCSIはecho "- - -" > /sys/class/scsi_host/host?/scan
とすることで、SCSI Busのrescanができます。rescanすることで、オンラインのままディスクを認識させる事ができます。
# echo "- - -" > /sys/class/scsi_host/host0/scan
# echo "- - -" > /sys/class/scsi_host/host1/scan
# echo "- - -" > /sys/class/scsi_host/host2/scan
# echo "- - -" > /sys/class/scsi_host/host3/scan
# echo "- - -" > /sys/class/scsi_host/host4/scan
# echo "- - -" > /sys/class/scsi_host/host5/scan
# echo "- - -" > /sys/class/scsi_host/host6/scan
# lsscsi
[0:0:0:0] cd/dvd NECVMWar VMware IDE CDR00 1.00 /dev/sr0
[2:0:0:0] disk VMware Virtual disk 1.0 /dev/sda
[2:0:1:0] disk VMware Virtual disk 1.0 /dev/sdb
IDCF Cloudの仮想マシンはなぜかSCSI Cardが4枚も接続されているらしく、ATAと合わせるとSCSI Cardが6枚もあることになっています。
大抵はhost2へディスクが接続されるようなのですが、良くわからないのでSCSI Card分rescanしてしまいましょう。(rescanしても特に問題ありません。)
DRBDのメタデータを再作成
基本的には新規インストールと同じです。
# drbdadm create-md r1
initializing activity log
NOT initializing bitmap
Writing meta data...
New drbd meta data block successfully created.
success
DRBDのリソースを再接続
リソースを再接続すれば完了です。
# cat /proc/drbd
version: 8.4.7-1 (api:1/proto:86-101)
GIT-hash: 3a6a769340ef93b1ba2792c6461250790795db49 build by phil@Build64R7, 2016-01-12 14:29:40
0: cs:Connected ro:Primary/Secondary ds:Diskless/UpToDate C r-----
ns:2095 nr:24580 dw:26624 dr:3720 al:3 bm:0 lo:0 pe:0 ua:0 ap:0 ep:1 wo:d oos:0
# drbdadm attach r1
# cat /proc/drbd
version: 8.4.7-1 (api:1/proto:86-101)
GIT-hash: 3a6a769340ef93b1ba2792c6461250790795db49 build by phil@Build64R7, 2016-01-12 14:29:40
0: cs:SyncTarget ro:Primary/Secondary ds:Inconsistent/UpToDate C r-----
ns:0 nr:3740 dw:3304 dr:20 al:3 bm:0 lo:0 pe:0 ua:0 ap:0 ep:1 wo:d oos:47181140
[>....................] sync'ed: 0.1% (46072/46076)M
finish: 7:16:51 speed: 1,652 (1,652) want: 2,160 K/sec
# echo "ABC" > /var/lib/mysql/write_ok3.txt
# ls -la /var/lib/mysql/write_ok3.txt
-rw-r--r-- 1 root root 4 3月 10 14:33 /var/lib/mysql/write_ok3.txt
同期が完了していなくても、問題なく利用できています。
同期が完了すると、ds:UpToDate/UpToDate
になります。
ディスクが壊れただけであれば、再構築まですべてオンラインで完結し、止まることもないのでサービスの継続性も失われません。(遅くはなりますが。とは言え、IDCF Cloudはネットワークもディスクも速いので、よっぽどディスクアクセスがない限りは結構使えると思います。)
Primary/Secondaryの切り替え
- どちらか一方が既にPrimaryの場合は、切り換えられません。
- 利用中の場合はdownしたSecondaryに切り替えることはできません。
# drbdadm primary r1
0: State change failed: (-1) Multiple primaries not allowed by config
Command 'drbdsetup-84 primary 0' terminated with exit code 11
# drbdadm secondary r1
0: State change failed: (-12) Device is held open by someone
Command 'drbdsetup-84 secondary 0' terminated with exit code 11
# unmount /var/lib/mysql
# drbdadm secondary r1
# cat /proc/drbd
version: 8.4.7-1 (api:1/proto:86-101)
GIT-hash: 3a6a769340ef93b1ba2792c6461250790795db49 build by phil@Build64R7, 2016-01-12 14:29:40
0: cs:Connected ro:Secondary/Secondary ds:UpToDate/UpToDate C r-----
ns:34 nr:47184880 dw:47184478 dr:20 al:6 bm:0 lo:0 pe:0 ua:0 ap:0 ep:1 wo:d oos:0
ということで、以下が正しい順番になります。
- サービス停止 (ex:systemctl stop mysqld)
- unmount (ex: unmount /dev/drbd0)
- primary側で
drbdadm secondary r1
- secondary側で、
drbdadm primary r1
Primary側がOSごと死んだ時
この場合、まずはサービス復旧しないといけないので、SecondaryをPrimaryに昇格し、マウントしてサービスを起動します。
これは既にPrimaryが死んでいるので普通にPrimaryに昇格してしまって問題ありません。
# cat /proc/drbd
version: 8.4.7-1 (api:1/proto:86-101)
GIT-hash: 3a6a769340ef93b1ba2792c6461250790795db49 build by phil@Build64R7, 2016-01-12 14:29:40
0: cs:WFConnection ro:Secondary/Unknown ds:UpToDate/DUnknown C r-----
ns:47212713 nr:8448 dw:8448 dr:47212713 al:6 bm:0 lo:0 pe:0 ua:0 ap:0 ep:1 wo:d oos:0
# drbdadm primary r1
# cat /proc/drbd
version: 8.4.7-1 (api:1/proto:86-101)
GIT-hash: 3a6a769340ef93b1ba2792c6461250790795db49 build by phil@Build64R7, 2016-01-12 14:29:40
0: cs:WFConnection ro:Primary/Unknown ds:UpToDate/DUnknown C r-----
ns:47212713 nr:8448 dw:8448 dr:47213625 al:6 bm:0 lo:0 pe:0 ua:0 ap:0 ep:1 wo:d oos:0
# mount -t xfs -o noatime,nodiratime,nobarrier /dev/drbd0 /var/lib/mysql/
この後は、壊れた元Primaryを復旧するわけですが、これは新規インストールと同様に進めて問題ありません。drbdadb up r1
した時点で同期が開始されます。
一つ問題があるとすると、IPアドレスだと思います。DRBDでは後からIPを変更する事ができません。(と思う。方法があるのかもしれないが。)IDCF Cloudの場合特に何も考えないとDHCPになってしまいます。IDCF CloudはIPをstaticで管理することも可能なので、同期セグメントのIPはstaticに管理した方がいいと思います。
スプリットブレインについて
スプリットブレインとは両方のノードがPrimayになってしまった状態のことを言います。これはどちらも書き込みができてしまう大変危険な状態です。
今までの説明でもわかるように、勝手にPrimary/Primaryの状態にはなりません。人為的ミスやクラスターソフトウェアのミスにより発生する可能性があります。
例えば、ネットワークの分断が発生して、両ノードがお互いを認識できない状態の時、Secondary側でdrbdadm primary r1
などすると発生します。
障害が発生してSecondary Nodeでdrbdadm primary r1
する時は、必ず元Primaryをシャットダウンしてから実行するようにしましょう。
もし、スプリットブレイン状態になってしまったら、どちらか片方のデータを諦めるしかありません。
スプリットブレインの実験
ここではネットワーク分断を再現して、実験してみましょう。
ネットワークを停止
単純にネットワークインターフェースをダウンして再現します。
今回はPrimary側でネットワークをダウンさせます。
# nmcli connection down f773ed44-f459-490e-acef-568376f1126b
Connection 'eno33557248' successfully deactivated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/0)
ネットワーク分断時のDRBDの状態
# cat /proc/drbd
version: 8.4.7-1 (api:1/proto:86-101)
GIT-hash: 3a6a769340ef93b1ba2792c6461250790795db49 build by phil@Build64R7, 2016-01-12 14:29:40
0: cs:StandAlone ro:Primary/Unknown ds:UpToDate/DUnknown r-----
ns:2056 nr:0 dw:0 dr:3880 al:0 bm:0 lo:0 pe:0 ua:0 ap:0 ep:1 wo:d oos:0
ネットワーク分断が発生するとcs:StandAlone ro:Primary/Unknown ds:UpToDate/DUnknown
となり、StandAloneとなるようです。StandAloneはリソースがdisconnect状態なので、ファイルシステムとしては使えているが、drbdからは切り離されているような状態になります。(正確ではないかも。)
この時、Secondary側を見ると、次のようになっています。
# cat /proc/drbd
version: 8.4.7-1 (api:1/proto:86-101)
GIT-hash: 3a6a769340ef93b1ba2792c6461250790795db49 build by phil@Build64R7, 2016-01-12 14:29:40
0: cs:WFConnection ro:Secondary/Unknown ds:UpToDate/DUnknown C r-----
ns:0 nr:2056 dw:4106 dr:13380 al:4 bm:0 lo:0 pe:0 ua:0 ap:0 ep:1 wo:d oos:0
Secondary側はStandAloneモードにはならないようです。
Secondary側をPrimaryに昇格
この状態の場合、SecondaryはPrimaryが居ないのでPrimaryに昇格できます。
# drbdadm primary r1
# cat /proc/drbd
version: 8.4.7-1 (api:1/proto:86-101)
GIT-hash: 3a6a769340ef93b1ba2792c6461250790795db49 build by phil@Build64R7, 2016-01-12 14:29:40
0: cs:WFConnection ro:Primary/Unknown ds:UpToDate/DUnknown C r-----
ns:0 nr:2056 dw:4106 dr:14292 al:4 bm:0 lo:0 pe:0 ua:0 ap:0 ep:1 wo:d oos:0
# mount -t xfs -o noatime,nodiratime,nobarrier /dev/drbd0 /var/lib/mysql/
これで両方が「自分はPrimaryだ」と言っている状態になりました。どっちらにも書き込めてしまう厄介な状態です。両方に書き込むとデータが分断してしまいますね。
スプリットブレインの解消
こうなってしまったら、どちらかのデータを捨てるしかありません。残す方を決めて、必要なデータを捨てる方から取り出し、スプリットブレインを解消します。
今回はネットワークを停止した、最初からPrimaryの方のデータを残す形でスプリットブレインを解消してみます。
両ノードにデータを書き込む
動きを確認したいので、両ノードからデータを書き込んでおきます。
# echo "ABC" > /var/lib/mysql/write_ok_primary.txt
# ls -la /var/lib/mysql/write_ok_primary.txt
-rw-r--r-- 1 root root 4 3月 10 17:55 /var/lib/mysql/write_ok_primary.txt
# echo "ABC" > /var/lib/mysql/write_ok_new_primary.txt
# ls -la /var/lib/mysql/write_ok_new_primary.txt
-rw-r--r-- 1 root root 4 3月 10 17:54 /var/lib/mysql/write_ok_new_primary.txt
ネットワークの復旧
先ずはネットワークをダウンした元々Primary側でネットワークを復旧しましょう。
# nmcli connection up f773ed44-f459-490e-acef-568376f1126b
接続が正常にアクティベートされました (D-Bus アクティブパス: /org/freedesktop/NetworkManager/ActiveConnection/3)
元SecondaryをStandAloneへ切り替え
次に元SecondaryをStandAloneの接続状態へ切り替えます。データを捨てるノードはStandAlone状態である必要があります。
# drbdadm disconnect r1
# cat /proc/drbd
version: 8.4.7-1 (api:1/proto:86-101)
GIT-hash: 3a6a769340ef93b1ba2792c6461250790795db49 build by phil@Build64R7, 2016-01-12 14:29:40
0: cs:StandAlone ro:Primary/Unknown ds:UpToDate/DUnknown r-----
ns:0 nr:2056 dw:8268 dr:19428 al:6 bm:0 lo:0 pe:0 ua:0 ap:0 ep:1 wo:d oos:2096
元SecondaryをSecondaryに戻す
次に元SecondaryをSecondaryに戻します。マウントしているとsecondaryにできないため、unmountしておく必要があります。
# umount /var/lib/mysql/
# drbdadm secondary r1
# cat /proc/drbd
version: 8.4.7-1 (api:1/proto:86-101)
GIT-hash: 3a6a769340ef93b1ba2792c6461250790795db49 build by phil@Build64R7, 2016-01-12 14:29:40
0: cs:StandAlone ro:Secondary/Unknown ds:UpToDate/DUnknown r-----
ns:0 nr:2056 dw:8271 dr:19428 al:6 bm:0 lo:0 pe:0 ua:0 ap:0 ep:1 wo:d oos:2096
元SecondaryのStandAloneの回復とデータ破棄
次にStandAloneからの回復と、スプリットブレインが起きてから書き込んだデータを破棄します。
# drbdadm connect --discard-my-data r1
# cat /proc/drbd
version: 8.4.7-1 (api:1/proto:86-101)
GIT-hash: 3a6a769340ef93b1ba2792c6461250790795db49 build by phil@Build64R7, 2016-01-12 14:29:40
0: cs:WFConnection ro:Secondary/Unknown ds:UpToDate/DUnknown C r-----
ns:0 nr:0 dw:8271 dr:19428 al:6 bm:0 lo:0 pe:0 ua:0 ap:0 ep:1 wo:d oos:2096
元々Primaryの方をStandAloneから回復
元々Primaryの方がまだStandAlone状態なので、これを回復します。
# drbdadm connect r1
# cat /proc/drbd
version: 8.4.7-1 (api:1/proto:86-101)
GIT-hash: 3a6a769340ef93b1ba2792c6461250790795db49 build by phil@Build64R7, 2016-01-12 14:29:40
0: cs:Connected ro:Primary/Secondary ds:UpToDate/UpToDate C r-----
ns:2096 nr:0 dw:0 dr:5976 al:0 bm:0 lo:0 pe:0 ua:0 ap:0 ep:1 wo:d oos:0
元々Primaryの方に書き込んだデータがSecondaryに同期され、ds:UpToDate/UpToDate
になれば、復旧完了です。
Secondaryのデータを確認
Secondaryのデータが破棄されて、元々Primaryと同じ状態になっているか確認してみます。
# ls -la /var/lib/mysql/write_ok_primary.txt
-rw-r--r-- 1 root root 4 3月 10 18:23 /var/lib/mysql/write_ok_primary.txt
# umount /var/lib/mysql/
# drbdadm secondary r1
# cat /proc/drbd
version: 8.4.7-1 (api:1/proto:86-101)
GIT-hash: 3a6a769340ef93b1ba2792c6461250790795db49 build by phil@Build64R7, 2016-01-12 14:29:40
0: cs:Connected ro:Secondary/Secondary ds:UpToDate/UpToDate C r-----
ns:2090 nr:0 dw:2082 dr:10876 al:5 bm:0 lo:0 pe:0 ua:0 ap:0 ep:1 wo:d oos:0
# drbdadm primary r1
# cat /proc/drbd
version: 8.4.7-1 (api:1/proto:86-101)
GIT-hash: 3a6a769340ef93b1ba2792c6461250790795db49 build by phil@Build64R7, 2016-01-12 14:29:40
0: cs:Connected ro:Primary/Secondary ds:UpToDate/UpToDate C r-----
ns:0 nr:2090 dw:16587 dr:23609 al:6 bm:0 lo:0 pe:0 ua:0 ap:0 ep:1 wo:d oos:0
# mount -t xfs -o noatime,nodiratime,nobarrier /dev/drbd0 /var/lib/mysql/
# ls -la /var/lib/mysql/write_ok_primary.txt
-rw-r--r-- 1 root root 4 3月 10 18:23 /var/lib/mysql/write_ok_primary.txt
# ls -la /var/lib/mysql/write_ok_new_primary.txt
ls: /var/lib/mysql/write_ok_new_primary.txt にアクセスできません: そのようなファイルやディレクトリはありません
スプリットブレイン時に書き込んだwrite_ok_new_primary.txt
が無く、write_ok_primary.txt
が同期できている事がわかります。
クラスタソフト
DRBDだけではPrimaryノードの障害時に障害を検知して、SecondaryノードをPrimaryへ昇格などといったことはできません。
これらは別のクラスターソフトウェアを利用する必要があります。
DRBDのドキュメントではPacemaker、Red Hat Cluster Suiteとの組み合わせが記載されています。
今のところ自分はこの部分に興味がないので、ドキュメント見て頑張ってください!