21
22

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

DRBD 8.4 インストールから必要な操作まで

Posted at

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をいれれば有効にできます。

ELRepoのrpmを入れる。
# yum -y install http://elrepo.org/linux/elrepo/el7/x86_64/RPMS/elrepo-release-7.0-2.el7.elrepo.noarch.rpm

最新版はのrpmはこの辺から確認しましょう。

DRBDをインストール

DRBDを入れる
# yum -y install drbd84-utils kmod-drbd84

DRBDの設定

コンフィグファイルとしては/etc/drbd.d/global_common.conf/etc/drbd.d/*.resとなります。*.resは各リソースの設定(要するにsyncさせたいディスクの設定)となります。今回は*.resr1.resとしています。

/etc/drbd.d/global_common.confについては基本的には変更不要です。
global_common.confglobalセクションにあるusage-countはDRBDプロジェクトがDRBDの利用状況についての統計を取るための設定であり、DRBDがインストールされるたびにHTTP接続が発生します。情報取得とHTTP接続を気にされるようであれば、設定でnoに変更してください。

/etc/drbd.d/global_common.conf
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へ記載します。色々と確認したのですが、現状では下記のコンフィグがベストとしています。

/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.
DRBDの起動
# drbdadm up r1

r1はr1.resで定義した物です。
メタデータはディスクの末尾の領域に確保されます。

drbdの状態は/proc/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/0r1.resで定義したリソース名とボリューム番号です。
ds:UpToDate/UpToDateになれば同期完了の意味です。
これで、同期が完了している状態となるので、利用する側を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: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
Primary
# 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を使って簡単に認識させる事ができます。

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側で下記を実行します。なお、このやり方は追加した領域の同期をスキップさせるやり方です。初期同期と同様に空の部分を同期しても仕方ない為です。

drbd側で拡張&同期スキップ
# 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 CloudCloudコンソール(もしくはAPI)から対象のボリュームを選択しデタッチします。この時仮想マシンはオンラインのままデタッチします。
OSから見ると、いきなりSCSI Diskが無くなった様に見えます。

detachVolumeする前
# 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
detachVolumeの後
# 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/drbdds:Diskless/UpToDateとDisklessと言うステータスに代わっていることぐらいです。

OS上のログ
# # 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 CloudCloudコンソール(もしくはAPI)からボリュームを作成(Secondary側と同サイズ)してPrimary Nodeの仮想マシンへアタッチします。(ボリューム => ボリューム作成 => できたボリューム選択 => アタッチ)
仮想マシンはオンラインのままボリュームのアタッチを行います。

OSに追加したディスクを認識させる

SCSIはecho "- - -" > /sys/class/scsi_host/host?/scanとすることで、SCSI Busのrescanができます。rescanすることで、オンラインのままディスクを認識させる事ができます。

Diskを認識させる
# 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に切り替えることはできません。
primaryがいたらprimaryにはなれない
# 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
mountしてなければOK
# 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

ということで、以下が正しい順番になります。

  1. サービス停止 (ex:systemctl stop mysqld)
  2. unmount (ex: unmount /dev/drbd0)
  3. primary側で drbdadm secondary r1
  4. secondary側で、drbdadm primary r1

Primary側がOSごと死んだ時

この場合、まずはサービス復旧しないといけないので、SecondaryをPrimaryに昇格し、マウントしてサービスを起動します。
これは既に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の状態

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: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側を見ると、次のようになっています。

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に昇格できます。

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の方のデータを残す形でスプリットブレインを解消してみます。

両ノードにデータを書き込む

動きを確認したいので、両ノードからデータを書き込んでおきます。

元から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
元はSecondaryに書き込み
# 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状態である必要があります。

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しておく必要があります。

Secondaryに変更する
# 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状態なので、これを回復します。

元々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と同じ状態になっているか確認してみます。

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
PrimaryをSecondaryに降格
# 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
元々Secondaryを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: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との組み合わせが記載されています。
今のところ自分はこの部分に興味がないので、ドキュメント見て頑張ってください!

21
22
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
21
22

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?