CentOS7.x+Pacemaker/Corosync+DRBD8によるHA構成
CentOS7.xでPacemakerを使ってHAを構成する場合、下記2通りの方法があった。
- RHEL/CentOS7.x で提供されている High Availability オプションを利用(RHELのはオプションで有償)
- Linux-HA Japan 提供のPacemakerパッケージを利用
- あとCLUSTEPROとかの商用製品
以下では情報量の多い&便利なプラグインが用意されている "Linux-HA Japan" のパッケージを利用した手順を示す。
参考URL
Linux-HA Japan コミュニティの方々がオープンソースカンファレンス等で提供・公開して下さっている資料を参考にする。
- Linux-HA Japan
- Linux-HA Japan ダウンロード
- 動かして理解するPacemaker ~CRM設定編~ その1
- DRBD Download
- Pacemakerでフェイルオーバー時にメール送信する
備忘メモ
- crm と pcs の両コマンドが用意されているが、Linux-HA Japan パッケージでは crm が推奨らしい(pcsはcorosyncがいぢれないとか)
- STONITH(ストニス)プラグインとして fence-agents と、cluster-glue のパッケージがあるが、cluster-glue に含まれるプラグインの利用が推奨らしい
- DRBD9 + drbd-utils で試したらうまくいかなかった(´・ω・`)
検証環境
- AWS/EC2, t2.micro インスタンス
- CentOS7.x (2016/04/18時点)
- /dev/sda 8GB, /dev/sdb 8GB
- SELinux を無効化
- その他、インスタンス作成時の状態を維持
- セキュリティグループでノード間の通信は全て通すように設定
- server1 : 10.0.0.10
- server2 : 10.0.0.11
2016/12追記
今はAWS/EC2上で作ってもうまく動かないかも。
Linux-HA Japan製 Pacemaker のインストール
Linux-HA Japan で公開されていリポジトリ設定用のRPMをインストールし、yumを用いてPacemaker関連パッケージのインストールを行う。"mailx" はメール通知で使うので一緒に入れる。
# mkdir /usr/local/src/pacemaker ; cd $_# curl -L "https://osdn.jp/frs/redir.php?m=iij&f=%2Flinux-ha%2F63918%2Fpacemaker-repo-1.1.13-1.1.el7.x86_64.rpm" -o pacemaker-repo-1.1.13-1.1.el7.x86_64.rpm# yum -y install ./pacemaker-repo-1.1.13-1.1.el7.x86_64.rpm# yum -y install pacemaker-all mailx
yum アップデートの除外設定
そのままだと CentOS7.x デフォルトで提供されている Pacemaker/Corosync でアップデートが適用されてしまう恐れがあるので、念のため更新から除外しておく。
# vi /etc/yum.conf
exclude=pacemaker* corosync*
Corosync の設定
Corosync共通暗号鍵の作成
Corosyncが用いる暗号鍵を作成する。
# corosync-keygen -k /etc/corosync/authkey -l
Corosync共通暗号鍵の展開
HAを構成する各ノードに、作成した暗号鍵を適当に転送する。
# scp -p /etc/corosync/authkey root@10.0.0.11:/etc/corosync/authkey
Pacemaker/Corosyncの設定
Corosyncの設定
続いて Corosync の動作に必要な設定を行う。テンプレートとしてUDPマルチキャストのものと、UDPユニキャストの設定が用意されている。下記ではUDPユニキャストのテンプレートをベースに設定を行う。
# cd /etc/corosync# cp corosync.conf.example.udpu corosync.conf
コメントアウトしている xxx.xxx.xxx.xxx は2つ目のNICを用いたい場合に設定する。
# Please read the corosync.conf.5 manual pagetotem { version: 2 rrp_mode: active crypto_cipher: none crypto_hash: none interface { ringnumber: 0 bindnetaddr: 10.0.0.0 mcastport: 5405 ttl: 1 } #interface { # ringnumber: 1 # bindnetaddr: xxx.xxx.xxx.xxx # mcastport: 5405 # ttl: 1 #} transport: udpu}logging { fileline: off to_logfile: yes to_syslog: yes logfile: /var/log/cluster/corosync.log debug: off timestamp: on logger_subsys { subsys: QUORUM debug: off }}nodelist { node { ring0_addr: 10.0.0.10 #ring1_addr: xxx.xxx.xxx.xxx nodeid: 1 } node { ring0_addr: 10.0.0.11 #ring1_addr: xxx.xxx.xxx.xxx nodeid: 2 } # 3台目以降の設定 #node { # ring0_addr: xxx.xxx.xxx.xxx # ring1_addr: xxx.xxx.xxx.xxx #}}quorum { # Enable and configure quorum subsystem (default: off) # see also corosync.conf.5 and votequorum.5 provider: corosync_votequorum expected_votes: 2}
プロセスの挙動について設定
Pacemakerのプロセスが故障した際、halt状態になるよう設定する。
# cp /etc/sysconfig/pacemaker{,.orig}# vi /etc/sysconfig/pacemaker
...68 # PCMK_fail_fast=no 69 PCMK_fail_fast=yes
Corosyncのプロセスが故障した際、CorosyncのWatchdogが動作するように設定(Restartを有効にする)
# systemctl edit --full corosync
...Restart=on-failure ...RestartSec=70 ...ExecStartPre=/sbin/modprobe softdog soft_margin=60 ...
Pacemaker停止時にCorosyncも停止する設定を有効にする。
# systemctl edit --full pacemaker
...46 # ExecStopPost=/bin/sh -c 'pidof crmd || killall -TERM corosync' 47 ExecStopPost=/bin/sh -c 'pidof crmd || killall -TERM corosync'
HA構成の起動確認
Pacemakerを起動し、HAを構成する各ノードの通信が正常に行われている事を確認
# systemctl start pacemaker# crm_mon -rfA -1...2 Nodes configured ...※両ノードが認識されており、Online で認識されている事を確認# systemctl stop pacemaker
DRBDのインストール
DRBDによる共有ディスクを作成する。ここではコマンドだけ列挙し細かい説明は省く。とりあえずDRBDインスコ
# yum -y install @development wget bash-completion# mkdir /usr/local/src/drbd ; cd $_# wget http://www.drbd.org/download/drbd/8.4/drbd-8.4.7-1.tar.gz# tar zxvf drbd-8.4.7-1.tar.gz# cd drbd-8.4.7-1# make && make install ; echo $?# cd ..# modinfo drbd | egrep -i version
drbd-utils のインスコ
# mkdir /usr/local/src/drbd-utils ; cd $_# wget https://www.drbd.org/download/drbd/utils/drbd-utils-8.9.6.tar.gz# tar zxvf drbd-utils-8.9.6.tar.gz# cd drbd-utils-8.9.6# ./configure --sysconfdir=/etc --localstatedir=/var --without-manual --with-pacemaker --with-udev --with-bashcompletion# make && make install ; echo $?
各設定ファイルの作成
# cd /etc/drbd.d/# mv global_common.conf global_common.conf.orig# vi global_common.conf
global { usage-count no;}common { startup { wfc-timeout 60; # 1 minutes. degr-wfc-timeout 60; # 1 minutes. } disk { on-io-error pass_on; } net { protocol C; max-buffers 8000; max-epoch-size 8000; sndbuf-size 0; } syncer { c-plan-ahead 0; c-max-rate 120M; c-min-rate 50M; rate 120M; al-extents 3389; }}
# vi drbd0.res
resource drbd0 { device /dev/drbd0; disk /dev/xvdb1; meta-disk internal; on ip-10-0-0-10.ap-northeast-1.compute.internal { address 10.0.0.10:7789; } on ip-10-0-0-11.ap-northeast-1.compute.internal { address 10.0.0.11:7789; }}
# vi /etc/hosts...10.0.0.10 server1 ip-10-0-0-10 ip-10-0-0-10.ap-northeast-1.compute.internal 10.0.0.11 server2 ip-10-0-0-11 ip-10-0-0-11.ap-northeast-1.compute.internal # parted /dev/xvdb> mklabel> mkpart> quit# drbdadm create-md drbd0# mkdir /data
DRBDのここまでの手順を両系で実行後、DRBDのサービスを両方で起動し、初期同期を開始する。
# systemctl start drbd# cat /proc/drbd# drbdadm primary drbd0 --force# cat /proc/drbd# mkfs.xfs /dev/drbd0# mount /dev/drbd0 /data
その他パッケージのインストール
ついでに PostgreSQL もリソースに含めるため、インストールしておく。
# yum -y install postgresql-server# systemctl edit --full postgresql...# Location of database directory#Environment=PGDATA=/var/lib/pgsql/dataEnvironment=PGDATA=/data/pgsql/data
下記はDRBDをマウントしている側(Primary)で実行
# drbdadm status =>Primaryである事を確認# mount =>/dev/drbd0 を /data にマウントしている事を確認# mkdir /data/pgsql# chown postgres:postgres /data/pgsql# su - postgres$ initdb --no-locale -E UTF8 /data/pgsql/data$ exit# systemctl start postgresql# ps -efww | grep postgres =>/data/pgsql/data でサービスが起動している事を確認# systemctl stop postgresql# umount /data# drbdadm secondary drbd0
CRMリソースの設定
CRMリソースの設定は、基本的にリソースの定義 -> グループ/クローンの作成 -> 起動・依存関係の設定みたいな感じ。crm ファイルを作成後、読み込ませるだけ。
# cd ~# vi /tmp/hoge =>下記の"設定ファイル"の内容を編集してコピペ
設定ファイル
### Cluster Option ------------------------------------------------------- ##### クラスター全体の設定、STONITH(ストニス)は false にしている。## no-quorum-policy ... 2台構成なので "ignore" を選択(クォーラムを無視する)# stonith-enabled ... 強制的なノード停止を無効(false)にする# startup-fencing ... 起動時のフェンシングを無効(false)にする# resource-stickiness ... 切り戻しが起こらないようにする(INFINITY)# migration-threshold ... リソース管理エラー -> 切り替えまでの閾値(1回)#property \ no-quorum-policy="ignore" \ stonith-enabled="false" \ startup-fencing="false"### Resource Defaults ###rsc_defaults \ resource-stickiness="INFINITY" \ migration-threshold="1"### Fencing Topology ----------------------------------------------------- ##### フェンシング動作時の挙動設定## stonith ... ipmi/libvirt を利用した、相方にトドメを刺す仕組み# stonith-helper ... stonith による相打ちを防ぐ仕組み##fencing_topology \# server01: prmHelper1-1 prmLibvirt1-2 \# server02: prmHelper2-1 prmLibvirt2-2###### Group Configuration ####group grpStonith1 \# prmHelper1-1 \# prmLibvirt1-2##group grpStonith2 \# prmHelper2-1 \# prmLibvirt2-2##primitive prmHelper1-1 stonith:external/stonith-helper \# params \# pcmk_reboot_retries=1 \# hostlist="server01" \# dead_check_target="192.168.1.10 192.168.11.10 192.168.12.10 192.168.122.40" \# standby_check_command="/usr/sbin/crm_resource -r prmDB -W | grep -qi `hostname`" \# run_online_check="yes" \# op start interval="0s" timeout="20s" on-fail="restart" \# op monitor interval="3600s" timeout="20s" on-fail="restart" \# op stop interval="0s" timeout="15" on-fail="ignore"##primitive prmLibvirt1-2 stonith:external/libvirt \# params \# hostlist="server01" \# hypervisor_uri="qemu+ssh://192.168.122.1/system" \# op start interval="0s" timeout="60s" on-fail="restart" \# op monitor interval="3600s" timeout="60s" on-fail="restart" \# op stop interval="0s" timeout="60s" on-fail="ignore"##primitive prmHelper2-1 stonith:external/stonith-helper \# params \# pcmk_reboot_retries=1 \# hostlist="server02" \# standby_check_command="/usr/sbin/crm_resource -r prmDB -W | grep -qi `hostname`" \# run_online_check="yes" \# op start interval="0s" timeout="20s" on-fail="restart" \# op monitor interval="3600s" timeout="20s" on-fail="restart" \# op stop interval="0s" timeout="15" on-fail="ignore"##primitive prmLibvirt2-2 stonith:external/libvirt \# params \# hostlist="server02" \# hypervisor_uri="qemu+ssh://192.168.122.1/system" \# op start interval="0s" timeout="60s" on-fail="restart" \# op monitor interval="3600s" timeout="60s" on-fail="restart" \# op stop interval="0s" timeout="60s" on-fail="ignore"##### Reousce Settings ----------------------------------------------------- ##### primitive ... リソースエージェントに準じたリソースの設定# group ... リソースのグループ化 (=orderも含めて考慮)# clone ... クラスタノードで共通するリソースの設定# ms ... master/slave系リソースの設定(DB,DRBDなど)#### Group Configuration ##### Master/Slaveリソース(ms)は location で紐付けるのでグループには含めないgroup grpTrac \ prmVIP \ prmFS \ prmDB \ prmMail### Clone Configuration ###clone clnPing \ prmPingclone clnDiskd1 \ prmDiskd1clone clnDiskd2 \ prmDiskd2ms msDrbd \ drbd \ meta \ resource-stickiness="1" \ master-max="1" \ master-node-max="1" \ clone-max="2" \ clone-node-max="1" \ notify="true"## VIPprimitive prmVIP ocf:heartbeat:IPaddr2 \ params \ ip="10.0.0.9" \ nic="eth0" \ cidr_netmask="24" \ op start interval="0s" timeout="20s" on-fail="restart" \ op monitor interval="10s" timeout="20s" on-fail="restart" \ op stop interval="0s" timeout="20s" on-fail="ignore"## DRBD/drbd0 primitive drbd ocf:linbit:drbd \ params \ drbdconf="/etc/drbd.conf" \ drbd_resource="drbd0" \ op start interval="0s" timeout="240s" on-fail="restart" \ op monitor role="Master" interval="10s" timeout="20s" on-fail="restart" \ op monitor role="Slave" interval="20s" timeout="20s" on-fail="restart" \ op promote interval="0s" timeout="90s" on-fail="stop" \ op demote interval="0s" timeout="90s" on-fail="ignore" \ op stop interval="0s" timeout="100s" on-fail="ignore"### Primitive Configuration ##### DRBD/mountprimitive prmFS ocf:heartbeat:Filesystem \ params \ fstype="xfs" \ run_fsck="force" \ device="/dev/drbd0" \ directory="/data" \ op start interval="0s" timeout="60s" on-fail="restart" \ op monitor interval="20s" timeout="40s" on-fail="restart" \ op stop interval="0s" timeout="60s" on-fail="ignore"## PostgreSQLprimitive prmDB ocf:heartbeat:pgsql \ params \ pgctl="/bin/pg_ctl" \ psql="/bin/psql" \ pgdata="/data/pgsql/data" \ start_opt="-p 5432" \ pgdba="postgres" \ pgport="5432" \ pgdb="template1" \ op start interval="0s" timeout="120s" on-fail="restart" \ op monitor interval="10s" timeout="10s" on-fail="restart" \ op stop interval="0s" timeout="20s" on-fail="ignore"## Mailprimitive prmMail ocf:heartbeat:MailTo \ params \ email="underboob@example.com,oppaoppai@example.com" \ subject="Pacemaker Alert - futomomo.example.com (xxx.xxx.xx.xxx)" \ op monitor depth="0" timeout="10s" interval="10s"## GATEWAY PINGprimitive prmPing ocf:pacemaker:ping \ params \ name="default_ping_set" \ host_list="10.0.0.1" \ multiplier="100" \ attempts="2" \ timeout="2" \ debug="true" \ op start interval="0s" timeout="60s" on-fail="restart" \ op monitor interval="10s" timeout="60s" on-fail="restart" \ op stop interval="0s" timeout="60s" on-fail="ignore"## Local Disk Check - /dev/xvdbprimitive prmDiskd1 ocf:pacemaker:diskd \ params \ name="diskcheck_status" \ device="/dev/xvdb" \ options="-e -t 70" \ interval="10" \ dampen="2" \ op start interval="0s" timeout="60s" on-fail="restart" \ op monitor interval="10s" timeout="60s" on-fail="restart" \ op stop interval="0s" timeout="60s" on-fail="ignore"## Local Disk Check - /dev/xvdaprimitive prmDiskd2 ocf:pacemaker:diskd \ params \ name="diskcheck_status_internal" \ device="/dev/xvda" \ options="-e" \ interval="10" \ dampen="2" \op start interval="0s" timeout="60s" on-fail="restart" \ op monitor interval="10s" timeout="60s" on-fail="restart" \ op stop interval="0s" timeout="60s" on-fail="ignore"### Persistence Settings ------------------------------------------------- ##### ノードの重み付けと、リソースの場所・同居・順序の明示# location ... 場所、どのノードで起動するか?# colocation ... 同居、どのリソースと一緒に起動するか?# order ... 順序、どのリソースの前/後に起動するか?#### Resource Location ##### DRBD/grpTracリソースの起動は、ping/disk check が正常なノードで行う。# 重み付けで1台目のノードを優先するように設定#location rsc_location-msDrbd-1 msDrbd \ rule 200: #uname eq ip-10-0-0-10.ap-northeast-1.compute.internal \ rule 100: #uname eq ip-10-0-0-11.ap-northeast-1.compute.internal \ rule -INFINITY: not_defined default_ping_set or default_ping_set lt 100 \ rule -INFINITY: not_defined diskcheck_status or diskcheck_status eq ERROR \ rule -INFINITY: not_defined diskcheck_status_internal or diskcheck_status_internal eq ERRORlocation rsc_location-grpTrac-2 grpTrac \ rule 200: #uname eq ip-10-0-0-10.ap-northeast-1.compute.internal \ rule 100: #uname eq ip-10-0-0-11.ap-northeast-1.compute.internal \ rule -INFINITY: not_defined default_ping_set or default_ping_set lt 100 \ rule -INFINITY: not_defined diskcheck_status or diskcheck_status eq ERROR \ rule -INFINITY: not_defined diskcheck_status_internal or diskcheck_status_internal eq ERROR#location rsc_location-grpStonith1-3 grpStonith1 \# rule -INFINITY: #uname eq pm01#location rsc_location-grpStonith2-4 grpStonith2 \# rule -INFINITY: #uname eq pm02### Resource Colocation ##### ping/dick check が有効なノードで DRBD を起動する# DRBD/Masterノードでのみ grpTrac のリソースを起動する。#colocation rsc_colocation-msDrbd-clnPing-1 INFINITY: msDrbd clnPing colocation rsc_colocation-msDrbd-clnDiskd1-2 INFINITY: msDrbd clnDiskd1 colocation rsc_colocation-msDrbd-clnDiskd2-3 INFINITY: msDrbd clnDiskd2 colocation rsc_colocation-grpTrac-msDrbd-4 INFINITY: grpTrac msDrbd:Master### Resource Order ##### ping/disk check が有効になってから DRBD を開始する。# DRBDが開始された後、grpTrac のリソースが開始するように設定# 末尾の設定で grpTrac のリソースが停止してから、DRBDが secondary になるように指定している(symmetrical=true)、他は順不同#order rsc_order-clnPing-msDrbd-1 0: clnPing msDrbd symmetrical=false order rsc_order-clnDiskd1-msDrbd-2 0: clnDiskd1 msDrbd symmetrical=false order rsc_order-clnDiskd2-msDrbd-3 0: clnDiskd2 msDrbd symmetrical=false order rsc_order-msDrbd-grpTrac-4 INFINITY: msDrbd:promote grpTrac:start
コメント行で怒られるので、コメント行を除外した crm ファイルを作成し反映する。
# egrep -v "^#" /tmp/hoge > ~/resource.crm# crm configure load update resource.crm
ちゃんと動く事を祈る。 ダメな場合は /etc/sysconfig/pacemaker や corosync.conf でデバッグを有効にして調査してなんとかする。
# crm_mon -rfA -1
とりあえず動いたのは動いた。実際にはもっと設定詰めて色々試験しないとダメだけども。
以上、なにごとも適当に。