2台でHA構築 (CentOS6.9) 2018年追記

## version

```
CentOS6.9 x86_64

pacemaker-1.1.17
corosync-2.4.2
crmsh-2.1.9

drbd84-utils-8.9.8
kmod-drbd84-8.4.9
```

* [DRBD構築支援サービス｜サービス紹介｜株式会社コンバージョン](http://www.conversion.co.jp/service/drbd)

![スクリーンショット_2017-08-14_18-21-07.png](https://qiita-image-store.s3.amazonaws.com/0/25728/3662f12e-d283-4228-f722-ffb944eb465c.png)



## 参考

* @takehironetさんの[CentOS 6でPacemaker 1.1をつかう - Qiita](http://qiita.com/takehironet/items/ee6a50f7f9b349abd085)
* Linux-HA Japanの[すぐに始められる！最新のPacemakerで始める高可用クラスタ入門](http://linux-ha.sourceforge.jp/wp/wp-content/uploads/OSC-Tokyo2014Fall.pdf)

## corosyncについて

* corosyncはheartbeatの代わりとして使用されている。
    * [CorosyncはHeartbeatよりも設計が新しいため、通信効率が優れています。](http://www.atmarkit.co.jp/ait/articles/1510/23/news010_2.html)
* memberで書いているのは古い。(corosync.conf)
    * nodelistを使う。
* `service corosync start`は古い。
    * `/sbin/initctl start pacemaker.combined`を使う。
    * CentOS7では`systemctl start pacemaker`


##今回の構成

* IP
  * 192.168.0.102 (db1)
  * 192.168.0.103 (db2)

### selinuxとiptablesを無効

```sh:rootで実施
# selinux次回起動時から無効
sed -i -e 's/^SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config

# iptable無効
/sbin/service iptables stop; /sbin/chkconfig iptables off
```

### Linux-HAのパッケージをインストール

* [Package [1-02] Pacemakerリポジトリパッケージ (RHEL6) - Linux-HA Japan - OSDN](http://sourceforge.jp/projects/linux-ha/releases/p12469)
    * http://sourceforge.jp/projects/linux-ha/releases/p12469

```sh
rpm -ivh pacemaker-repo-1.1.17-1.1.el6.x86_64.rpm
```

#### パッケージが競合するので除外

```diff:/etc/yum.repos.d/CentOS-Base.repo
  [base]
+ exclude=pacemaker pacemaker-libs corosync cluster-glue heartbeat resource-agents
  
  [updates]
+ exclude=pacemaker pacemaker-libs corosync cluster-glue heartbeat resource-agents

...
```

### パッケージ インストール

```bash:
yum install -y {corosync,pacemaker}.x86_64 crmsh
```

### corosync.conf

```rb:/etc/corosync/corosync.conf
totem {
        version: 2
        crypto_cipher: none
        crypto_hash: none
        interface {
                ringnumber: 0
                bindnetaddr: 192.168.0.0
                mcastport: 5405
                ttl: 1
        }
        transport: udpu
}
logging {
        fileline: off
        to_logfile: yes
        to_syslog: no
        logfile: /var/log/cluster/corosync.log
        debug: off
        timestamp: on
        logger_subsys {
                subsys: QUORUM
                debug: off
        }
}
nodelist {
        node {
                ring0_addr: 192.168.0.102
                nodeid: 1
        }
        node {
                ring0_addr: 192.168.0.103
                nodeid: 2
        }
}
quorum {
        provider: corosync_votequorum
        expected_votes: 2
        two_node: 1
}
```

* reboot

### pacemaker.combined起動

```bash:corosyncも起動してくれる
initctl start pacemaker.combined
# CentOS7では systemctl start pacemaker
```

```bash:クラスタ状態確認
/usr/sbin/crm_mon -A
```

1分くらい待つと表示される。

```sh:rootのcronに登録
@reboot (/sbin/initctl start pacemaker.combined)
# CentOS7では @reboot (systemctl start pacemaker)
```

### master/standby切り替える時は以下

```bash:
crm node standby

(master/standby切り替わったことを確認してから以下)

crm node online
```


----

* 以下[pacemaker - 2台でHA構築 (CentOS5.11) - Qiita](http://qiita.com/tukiyo3/items/00c73c45d015e55ab4fc)をベースに記述

### 2台中1台ダウン時の設定

```bash:設定ファイルの検証
# /usr/sbin/crm_verify -L -V
   error: unpack_resources: 	Resource start-up disabled since no STONITH resources have been defined
   error: unpack_resources: 	Either configure some or disable STONITH with the stonith-enabled option
   error: unpack_resources: 	NOTE: Clusters with shared data need STONITH to ensure data integrity
Errors found during check: config not valid
```

```sh:2台中1台ダウン時の設定
# STONITH無効化
crm configure property \
  stonith-enabled=false

# quorum無効化 (ノードの数が半分以下になったときはクラスタとしてサービス提供不可と見なすが2台構成で1台落ちたらその状態になるので無効化)
crm configure property \
  no-quorum-policy=ignore

# ノード復帰時に自動でリソースを元のノード上に移そうとするのを止める
crm configure rsc_defaults \
  resource-stickiness=100
```

```
# crm configure show
node 1: db1
node 2: db2
property cib-bootstrap-options: \
	have-watchdog=false \
	dc-version=1.1.17-1.el6-b36b869 \
	cluster-infrastructure=corosync \
	stonith-enabled=false \
	no-quorum-policy=ignore
rsc_defaults rsc-options: \
	resource-stickiness=100
```

## DRBD

### インストール

```bash:
rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org
rpm -Uvh http://www.elrepo.org/elrepo-release-6-8.el6.elrepo.noarch.rpm
# CentOS7の場合、http://ftp.colocall.net/pub/elrepo/elrepo/el7/x86_64/RPMS/elrepo-release-7.0-3.el7.elrepo.noarch.rpm

yum history sync

yum install -y drbd84-utils kmod-drbd84

# pacemakerからdrbdを起動するためここではoff
/sbin/chkconfig drbd off
```

### 設定(/dev/sda2)

```rb:/etc/drbd.d/r0.res
resource r0
{
    protocol C;
    net{
        # 書き込みパフォーマンス向上
        max-buffers 8000;
        max-epoch-size 8000;
        # TCP送信バッファの自動調整をする
        sndbuf-size 0;
    }
    syncer {
        # drbdadm verify用
        verify-alg sha1;
        rate 80M;
    }
    meta-disk internal;
    device /dev/drbd1;
    disk /dev/sda2;

    on db1.local {
        address 10.0.1.102:7788;
    }
    on db2.local {
        address 10.0.1.103:7788;
    }
}
```

#### ループバックデバイスを使う方法

* ミッションクリティカルではない場合にのみ使用

```rb:/etc/drbd.d/r0.res
resource r0
{
    protocol C;
    net{
        # 書き込みパフォーマンス向上
        max-buffers 8000;
        max-epoch-size 8000;
        # TCP送信バッファの自動調整をする
        sndbuf-size 0;
    }
    meta-disk internal;
    device /dev/drbd1;
    disk /dev/loop1;

    startup {
            wfc-timeout 120;
    }
    disk {
            on-io-error pass_on;
    }

    on db1.local {
        address 192.168.0.102:7788;
    }
    on db2.local {
        address 192.168.0.103:7788;
    }
}
```

```sh:ループバックの場合
sudo dd if=/dev/zero of=/srv/loop bs=1M count=1000
sudo losetup /dev/loop1 /srv/loop
```

* [How to set up a loop device at boot time? - Ask Ubuntu](https://askubuntu.com/questions/54970/how-to-set-up-a-loop-device-at-boot-time)

```sh:rootのcronに追加
# crontab -e
@reboot /sbin/losetup /dev/loop1 /srv/loop
```

### hostsにて名前解決

```diff:/etc/sysconfig/network
- HOSTNAME=localhost.localdomain
+ HOSTNAME=db1.local
```

```bash:/etc/hosts
192.168.0.102   db1
192.168.0.103   db2
```

* reboot


### create-md

```rb:初期化
dd if=/dev/zero of=/dev/sda2 bs=1M count=100
ループバックで進めようとしている場合は以下
dd if=/dev/zero of=/dev/loop1 bs=1M count=100
```

```sh:両方のサーバーで実施
drbdadm -c /etc/drbd.conf create-md r0
modprobe drbd
drbdadm up r0

mkdir /var/lib/mysql/
```

### DRBDデバイスの状態確認

```sh:最初は両方Secondary表示
$ cat /proc/drbd

version: 8.4.9-1 (api:1/proto:86-101)
GIT-hash: 9976da086367a2476503ef7f6b13d4567327a280 build by mockbuild@Build64R6, 2016-12-13 18:38:15
 0: cs:Connected ro:Secondary/Secondary ds:Inconsistent/Inconsistent C r-----
    ns:0 nr:0 dw:0 dr:0 al:8 bm:0 lo:0 pe:0 ua:0 ap:0 ep:1 wo:f oos:1015740
```

* [同期速度の設定](https://blog.3ware.co.jp/drbd-users-guide-8.3/s-configure-syncer-rate.html)

### DRBDデバイスの初期化

```rb:Primary側でのみ実施
drbdadm -- --overwrite-data-of-peer primary r0
```

```sh
$ cat /proc/drbd
version: 8.4.9-1 (api:1/proto:86-101)
GIT-hash: 9976da086367a2476503ef7f6b13d4567327a280 build by mockbuild@Build64R6, 2016-12-13 18:38:15
 0: cs:SyncSource ro:Primary/Secondary ds:UpToDate/Inconsistent C r-----
    ns:38688 nr:0 dw:0 dr:39352 al:8 bm:0 lo:0 pe:2 ua:0 ap:0 ep:1 wo:f oos:977468
	[>....................] sync'ed:  4.1% (977468/1015740)K
	finish: 0:06:47 speed: 2,392 (2,392) K/sec
```

* cs:SyncSource 表示となる。

```sh:Primary側でのみ実施
mkfs.ext4 /dev/drbd1
```

```sh:Primary側でのみ実施
mount /dev/drbd1 /var/lib/mysql/
```

```sh:/etc/fstab
/dev/drbd1      /var/lib/mysql  ext4 defaults,noauto,nofail 1 1
```

#### drbd primary / secondary 切り替え

```sh
# db1
umount /var/lib/mysql/
drbdadm secondary r0

# db2
drbdadm primary r0
mount /dev/drbd1 /var/lib/mysql/
```

#### DRBDトラブル時の対応(Primary/Unknown)

* [drbdを復旧(再同期)させるメモ - うまいぼうぶろぐ](http://hogem.hatenablog.com/entry/20080706/1215341445)

```sh
(セカンダリ側) drbdadm secondary r0
(セカンダリ側) drbdadm -- --discard-my-data connect r0

# 以下をすることでPrimary/UnknownからPrimary/Secondary表記になる。
(プライマリ側) drbdadm connect r0
```

#### verify

```
drbdadm verify r0
```

```sh:/proc/drbd
 1: cs:VerifyT ro:Secondary/Primary ds:UpToDate/UpToDate C r-----
    ns:0 nr:128 dw:128 dr:33545076 al:0 bm:0 lo:0 pe:0 ua:0 ap:0 ep:1 wo:f oos:0
	[=======>............] verified: 44.6% (40748/73508)M
	finish: 0:18:07 speed: 38,356 (18,940) K/sec
```

* verify中は cs:VerifyT 表示になる。
* 不整合がある場合は Insconsistent 表示になるらしい。
* `C` はprotocol Cのこと。

----

### crm (pacemaker)

```sh:pacemakerが起動していること。
$ ps -ef | grep pacemaker
root      7611     1  0 11:45 ?        00:00:00 pacemakerd
189       7615  7611  0 11:45 ?        00:00:00 /usr/libexec/pacemaker/cib
root      7616  7611  0 11:45 ?        00:00:00 /usr/libexec/pacemaker/stonithd
root      7617  7611  0 11:45 ?        00:00:00 /usr/libexec/pacemaker/lrmd
189       7618  7611  0 11:45 ?        00:00:00 /usr/libexec/pacemaker/attrd
189       7619  7611  0 11:45 ?        00:00:00 /usr/libexec/pacemaker/pengine
189       7620  7611  0 11:45 ?        00:00:00 /usr/libexec/pacemaker/crmd
```

```sh:(参考まで)指定できるOCFリソースエージェント一覧
$ crm ra list ocf
```

```rb:一覧
$ ls /usr/lib/ocf/resource.d/*
/usr/lib/ocf/resource.d/heartbeat:
anything      dnsupdate   iface-bridge      lxc          pgsql             SAPInstance         varnish
AoEtarget     docker      iface-vlan        MailTo       pingd             scsi2reservation    VIPArip
apache        Dummy       IPaddr            ManageRAID   portblock         SendArp             VirtualDomain
asterisk      eDir88      IPaddr2           ManageVE     postfix           ServeRAID           vmware
AudibleAlarm  ethmonitor  IPsrcaddr         mysql        pound             sfex                vsftpd
awseip        Evmsd       IPv6addr          mysql-proxy  proftpd           sg_persist          WAS
awsvip        EvmsSCC     iscsi             nagios       Pure-FTPd         slapd               WAS6
ClusterMon    exportfs    iSCSILogicalUnit  named        rabbitmq-cluster  SphinxSearchDaemon  WinPopup
clvm          Filesystem  iSCSITarget       nfsnotify    Raid1             Squid               Xen
conntrackd    fio         jboss             nfsserver    redis             Stateful            Xinetd
CTDB          galera      kamailio          nginx        Route             symlink             zabbixserver
db2           garbd       ldirectord        oracle       rsyncd            SysInfo
Delay         ICP         LinuxSCSI         oralsnr      rsyslog           syslog-ng
dhcpd         ids         LVM               pgagent      SAPDatabase       tomcat

/usr/lib/ocf/resource.d/linbit:
drbd

/usr/lib/ocf/resource.d/pacemaker:
attribute   controld  HealthCPU    o2cb  pingd   Stateful  SystemHealth
ClusterMon  Dummy     HealthSMART  ping  remote  SysInfo
```


```
# 一応こちらでも確認できるっぽい
# https://github.com/ClusterLabs/resource-agents/tree/master/heartbeat
```

/usr/lib/ocf/resource.d/heartbeat/drbd から
/usr/lib/ocf/resource.d/linbit/drbd に移った様子

* [クラスタ構成にDRBDのサービスを追加する](https://blog.3ware.co.jp/drbd-users-guide-8.3/s-pacemaker-crm-drbd-backed-service.html)
* [CRM CLI (command line interface) tool](https://linux-ha.osdn.jp/wp/wp-content/uploads/crm_cli.html)
* /var/lib/pacemaker/cib/cib.xml が実態。

* [primitiveでリソースを定義](http://linux-ha.osdn.jp/wp/archives/3855#primitive)

```rb:r0
crm configure primitive \
  drbd_mysql ocf:linbit:drbd \
  params drbd_resource="r0" \
  op monitor interval="15s"
```

```rb:Master-Slave構成
crm configure ms \
  ms_drbd_mysql drbd_mysql \
  meta master-max="1" master-node-max="1" \
  clone-max="2" clone-node-max="1" \
  notify="true"
```

```rb:mount(/varlib/mysql)
crm configure primitive \
  fs_mysql ocf:heartbeat:Filesystem \
  params device="/dev/drbd1" \
  directory="/var/lib/mysql" \
  fstype="ext4"
```

* ocf: /usr/lib/ocf/resource.d/ にあるリソースエージェント

```rb:IPaddr2(10.138.0.100を割り当て)
crm configure primitive \
  ip_mysql ocf:heartbeat:IPaddr2 \
  params ip="10.138.0.100" cidr_netmask="24" nic="eth0" iflabel="0"
```

* [リソースの定義](http://linux-ha.osdn.jp/wp/archives/3855)

```rb:primitive(リソースの定義)
crm configure primitive \
  mysqld lsb:mysqld
```

```rb:group(グループ定義)
crm configure group \
  mysql fs_mysql ip_mysql mysqld
```

* [colocation](http://linux-ha.osdn.jp/wp/archives/3868#colocation)

```rb:colocation(同一ノードで起動する)
crm configure colocation \
  mysql_on_drbd INFINITY: mysql ms_drbd_mysql:Master
```

* [orderで順序を制約](http://linux-ha.osdn.jp/wp/archives/3868#order)

> INFINITY:絶対に、左→右の順にアクションしなければならない

```rb:order(drbdの後にmysqlが起動)
crm configure order \
  mysql_after_drbd INFINITY: ms_drbd_mysql:promote mysql:start
```

location で `-inf:`指定すると絶対に切り替わらない。


### うまくいった設定例

```ruby:/etc/mysql/db2/my.cnf
[mysqld]
socket=/var/run/mysqld/mysqld.sock2
datadir=/opt/mysql/var/

default-character-set=sjis

log=/tmp/query.log
log-long-format

skip-locking
key_buffer = 2048M
max_allowed_packet = 1M
table_cache = 512
sort_buffer_size = 2M
net_buffer_length = 2M
myisam_sort_buffer_size = 128M
myisam_sort_buffer_size = 2M
wait-timeout = 180
max_connections = 4096

#thread_cache = 8
thread_cache = 512
query_cache_size= 32M
thread_concurrency = 8

user            = mysql
bind-address    = 192.168.0.101
port            = 3307

[client]
socket=/var/run/mysqld/mysqld.sock2
default-character-set=sjis
```

```sh:configure
# crm configure show
node 1: db1.local \
	attributes standby=off
node 2: db2.local \
	attributes standby=off
primitive MySQL2 mysql \
	params binary="/opt/mysql/bin/mysqld_safe" client_binary="/opt/mysql/bin/mysql" config="/etc/mysql/db2/my.cnf" datadir="/var/lib/mysql/db2" log="/var/lib/mysql/logs/db2/mysql.err" pid="/var/run/mysqld/db2.pid" socket="/var/run/mysqld/mysqld.sock2" \
	op monitor interval=60s \
	meta target-role=Started
primitive MySQLData ocf:linbit:drbd \
	params drbd_resource=r0 \
	op monitor interval=15s
primitive MySQLFS Filesystem \
	params device="/dev/drbd1" directory="/var/lib/mysql" fstype=ext4
primitive ip_mysql IPaddr2 \
	params ip=192.168.0.101 cidr_netmask=24 nic=bond0 iflabel=0
group MySQLGroup MySQLFS ip_mysql MySQL2
ms MySQLDataClone MySQLData \
	meta master-max=1 master-node-max=1 clone-max=2 clone-node-max=1 notify=true
colocation mysql_on_drbd inf: MySQLGroup MySQLDataClone:Master
order MySQL2-after-MySQLFS inf: MySQLFS MySQL2
order MySQLFS-after-MySQLData inf: MySQLDataClone:promote MySQLGroup:start

property cib-bootstrap-options: \
	have-watchdog=false \
	dc-version=1.1.17-1.el6-b36b869 \
	cluster-infrastructure=corosync \
	stonith-enabled=false \
	no-quorum-policy=ignore
rsc_defaults rsc-options: \
	resource-stickiness=100
```

---

## crm_mon -Aの値について

```sh:drbdの正常時
Node Attributes:
* Node db1.local:
    + master-MySQLData                  : 10000
* Node db2.local:
    + master-MySQLData                  : 10000
```

```sh:drbdの初回同期中(db1->db2)
Node Attributes:
* Node db1.local:
    + master-MySQLData                  : 10000
* Node db2.local:
    + master-MySQLData                  : 10
```

```sh:drbdの同期中(db1->db2)
Node Attributes:
* Node db1.local:
    + master-MySQLData                  : 10000
* Node db2.local:
    + master-MySQLData                  : 100
```

```sh:Secondary/Unknown時、もしくは同期中。
Node Attributes:
* Node db1.local:
    + master-MySQLData                  : 10000
* Node db2.local:
    + master-MySQLData                  : 1000
```

### DRBDのprotocol (C->Aなど)変更方法

* /etc/drbd.d/r0.res を変更してStandby側をOS再起動などで冗長化解除し、再度冗長化されることで変更される。

### その他参考URL

* [DRBD [がらくたネット]](http://e-garakuta.net/techinfo/doku.php/linux/drbd)
* [IBM Knowledge Center - DRBD ステータスの監視](https://www.ibm.com/support/knowledgecenter/ja/SSULQD_7.1.0/com.ibm.nz.adm.doc/c_sysadm_monitoring_drbd_status.html)
* [drbdを復旧(再同期)させるメモ - うまいぼうぶろぐ](http://hogem.hatenablog.com/entry/20080706/1215341445)