CentOS 7 のリポジトリからサクッとインストールできる下記で試しています。
- corosync-2.3.4-7.el7_2.1
- pacemaker-1.1.13-10.el7_2.2
- resource-agents-3.9.5-54.el7_2.9
Pacemaker/Corosync の構成
確認用に次のような構成で Pacemaker/Corosync の環境を構築しています。
corosync
- pm01
- 192.168.33.11/24 (enp0s8 / ring0)
- 192.168.99.11/24 (enp0s9 / ring1)
- pm02
- 192.168.33.12/24 (enp0s8 / ring0)
- 192.168.99.12/24 (enp0s9 / ring1)
pacemaker
sudo pcs property set stonith-enabled="false"
sudo pcs property set no-quorum-policy="ignore"
sudo pcs resource defaults migration-threshold="1"
sudo pcs resource create dummy1 ocf:pacemaker:Dummy state=/tmp/pm-dummy1
sudo pcs resource create dummy2 ocf:pacemaker:Dummy state=/tmp/pm-dummy2
sudo pcs resource group add dummys dummy1 dummy2
/etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
192.168.33.11 pm01
192.168.33.12 pm02
192.168.99.11 pm01-back
192.168.99.12 pm02-back
snmptrapd
snmptrap の確認のために ローカルに snmptrapd をセットアップします。
必要なもろもろをインストールします。
sudo yum -y install net-snmp net-snmp-utils net-snmp-perl mailx
snmptrapd ですべてのトラップをメールで root に転送するように設定します。
sudo tee /etc/snmp/snmptrapd.conf <<'EOS'
disableAuthorization yes
traphandle default /usr/bin/traptoemail root
EOS
root へのメールは自分のメールアドレスに転送させます。
echo ore@example.com | sudo tee /root/.forward
pacemaker や corosync の mib を読み込むために /etc/snmp/snmp.conf
を作成します。
sudo tee /etc/snmp/snmp.conf <<'EOS'
mibs ALL
EOS
snmptrapd を開始します。
sudo systemctl start snmptrapd
sudo systemctl enable snmptrapd
試しに適当なトラップを送信します。トラップがメールで送信されれば正しくセットアップされています。
sudo snmptrap -v 1 -c hoge localhost corosync localhost 6 1 ''
sudo snmptrap -v 1 -c hoge localhost pacemaker localhost 6 1 ''
corosync-notifyd
corosync-notifyd
は corosync の重要なイベントを dbus や snmptrap で通知するサービスです。ノードの故障や復帰を通知することができますが・・・リソース障害は corosync の管轄じゃないので通知できません。
/etc/sysconfig/corosync-notifyd
でコマンドラインオプションを指定できるので 127.0.0.1
にトラップを送信するように設定します。
sudo tee /etc/sysconfig/corosync-notifyd <<'EOS'
OPTIONS="-s -l -m 127.0.0.1"
EOS
corosync-notifyd
を開始します。
sudo systemctl start corosync-notifyd
開始した時点で次のようなトラップが送信されました。
SNMPv2-MIB::snmpTrapOID.0 COROSYNC-MIB::corosyncNoticesQuorumStatus
COROSYNC-MIB::corosyncObjectsNodeName "pm01"
COROSYNC-MIB::corosyncObjectsNodeID 1
COROSYNC-MIB::corosyncObjectsQuorumStatus "quorate"
pacemaker や corosync を停止・開始したときの通知
片方の pacemaker を停止してみる。
sudo systemctl stop pacemaker
このときはトラップは送信されません。
corosync を停止してみる。
sudo systemctl stop corosync
次のようなトラップが片割れ(pm01 で corosync を停止したので pm02 から)から送信されました。
# from pm02
SNMPv2-MIB::snmpTrapOID.0 COROSYNC-MIB::corosyncNoticesNodeStatus
COROSYNC-MIB::corosyncObjectsNodeName "pm01-back"
COROSYNC-MIB::corosyncObjectsNodeID 1
COROSYNC-MIB::corosyncObjectsNodeAddress "192.168.99.11"
COROSYNC-MIB::corosyncObjectsNodeStatus "left"
pacemaker を開始してみる(corosync も一緒に開始されます)。
sudo systemctl start pacemaker
次のようなトラップが送信されました。
# from pm02
SNMPv2-MIB::snmpTrapOID.0 COROSYNC-MIB::corosyncNoticesNodeStatus
COROSYNC-MIB::corosyncObjectsNodeName "pm01-back"
COROSYNC-MIB::corosyncObjectsNodeID 1
COROSYNC-MIB::corosyncObjectsNodeAddress "192.168.99.11"
COROSYNC-MIB::corosyncObjectsNodeStatus "joined"
リソース障害
リソース障害を発生させてみる。
sudo rm /tmp/pm-dummy1
が、リソース障害ではなにも通知されませんでした。
通信障害
NIC の 1 つを iptables で塞いでみます。
sudo yum -y install iptables-services
sudo systemctl start iptables
sudo iptables -F
sudo iptables -A INPUT -i enp0s9 -j DROP
次のようなトラップが送信されました。両方のノードから通知が来ると思っていたのですが、、、片方からしか来ませんでした(corosync-cfgtool
で見た感じ、両方のノードで faulty
になってます)。
# from pm02
SNMPv2-MIB::snmpTrapOID.0 COROSYNC-MIB::corosyncNoticesRRPStatus
COROSYNC-MIB::corosyncObjectsNodeName "pm02"
COROSYNC-MIB::corosyncObjectsNodeID 2
COROSYNC-MIB::corosyncObjectsIfaceNo 1
COROSYNC-MIB::corosyncObjectsRRPStatus "faulty"
塞いでた穴を開きます。
sudo iptables -F
次のようなトラップが送信されました。これも片方のノードからしか送信されませんでした。
# from pm02
SNMPv2-MIB::snmpTrapOID.0 COROSYNC-MIB::corosyncNoticesRRPStatus
COROSYNC-MIB::corosyncObjectsNodeName "pm02"
COROSYNC-MIB::corosyncObjectsNodeID 2
COROSYNC-MIB::corosyncObjectsIfaceNo 1
COROSYNC-MIB::corosyncObjectsRRPStatus "operational"
ノード障害
サーバを強制終了してみます。Vagrant 環境なので次のように強制終了します。
vagrant halt --force pm01
次のようなトラップが送信されました。
# from pm02
SNMPv2-MIB::snmpTrapOID.0 COROSYNC-MIB::corosyncNoticesNodeStatus
COROSYNC-MIB::corosyncObjectsNodeName "pm01-back"
COROSYNC-MIB::corosyncObjectsNodeID 1
COROSYNC-MIB::corosyncObjectsNodeAddress "192.168.99.11"
COROSYNC-MIB::corosyncObjectsNodeStatus "left"
サーバを起動します。
vagrant up pm01
vagrant ssh pm01
sudo systemctl start corosync-notifyd
sudo systemctl start pacemaker
次のようなトラップが送信されました。
# from pm02
SNMPv2-MIB::snmpTrapOID.0 COROSYNC-MIB::corosyncNoticesNodeStatus
COROSYNC-MIB::corosyncObjectsNodeName "pm01-back"
COROSYNC-MIB::corosyncObjectsNodeID 1
COROSYNC-MIB::corosyncObjectsNodeAddress "192.168.99.11"
COROSYNC-MIB::corosyncObjectsNodeStatus "joined"
# from pm01
SNMPv2-MIB::snmpTrapOID.0 COROSYNC-MIB::corosyncNoticesQuorumStatus
COROSYNC-MIB::corosyncObjectsNodeName "pm01"
COROSYNC-MIB::corosyncObjectsNodeID 1
COROSYNC-MIB::corosyncObjectsQuorumStatus "quorate"
# from pm01
SNMPv2-MIB::snmpTrapOID.0 COROSYNC-MIB::corosyncNoticesRRPStatus
COROSYNC-MIB::corosyncObjectsNodeName "pm01"
COROSYNC-MIB::corosyncObjectsNodeID 1
COROSYNC-MIB::corosyncObjectsIfaceNo 0
COROSYNC-MIB::corosyncObjectsRRPStatus "operational"
# from pm01
SNMPv2-MIB::snmpTrapOID.0 COROSYNC-MIB::corosyncNoticesRRPStatus
COROSYNC-MIB::corosyncObjectsNodeName "pm01"
COROSYNC-MIB::corosyncObjectsNodeID 1
COROSYNC-MIB::corosyncObjectsIfaceNo 1
COROSYNC-MIB::corosyncObjectsRRPStatus "operational"
corosync-notifyd を起動すると corosync も起動する
ちなみに corosync-notifyd
の systemd のユニットファイルに Wants=corosync.service
が書かれているので、corosync-notifyd
を開始すると corosync
も一緒に開始します。
cat /usr/lib/systemd/system/corosync-notifyd.service
# [Unit]
# Description=Corosync Dbus and snmp notifier
# Wants=corosync.service
# After=corosync.service
# :
サーバのブート時に corosync
を起動させたくないのであれば注意が必要です。
crm_mon で snmp-traps とかメール通知
たしか crm_mon
に --snmp-traps
とか --mail-to
とかのオプションがあって、リソース障害を snmptrap やメールで通知できるはず、、、なのだけど man crm_mon
にも crm_mon --help
にもその情報がない。。。
だいぶ前に LinuxHA Japan のリポジトリからインストールした pacemaker-1.0.13-2.el6.x86_64
の crm_mon 1.0.13 for OpenAIS and Heartbeat (Build: a83fae5)
だと --snmp-traps
とか --mail-to
とかもあるんだけど。。。
とりあえずダメ元で試してみる。
pacemaker のインストール時に crm_mon
のための systemd のユニットファイルがインストールされています。
cat /usr/lib/systemd/system/crm_mon.service
内容は次の通り。
:
[Service]
Type=forking
EnvironmentFile=-/etc/sysconfig/crm_mon
ExecStart=/usr/sbin/crm_mon $OPTIONS
Restart=always
:
Type=forking
とあるので crm_mon
はデーモン化するのが良さそう。EnvironmentFile
でファイル名の頭に -
がついているのは man systemd.exec
によるとファイルが存在しないときには無視するという意味とのこと。
次のように /etc/sysconfig/crm_mon
でコマンドライン引数を指定します。
sudo tee /etc/sysconfig/crm_mon <<'EOS'
OPTIONS="--daemonize --snmp-traps=127.0.0.1"
EOS
crm_mon.service
を開始します。
sudo systemctl start crm_mon.service
sudo systemctl status crm_mon.service
意図的にリソース障害を発生させてみる・・・が、トラップが送信される気配がない。
ためしに下記でも試してみるも・・・が、メールが送信される気配はない。
sudo tee /etc/sysconfig/crm_mon <<'EOS'
OPTIONS="--daemonize --mail-to=root"
EOS
どうもこれらの機能は CentOS 7 のリポジトリの pacemaker では無効になっているっぽい。
- http://clusterlabs.org/doc/en-US/Pacemaker/1.1/html/Pacemaker_Explained/ch07.html#idm140617236272336
Depending on your system settings and compilation settings, SNMP or email alerts might be unavailable. Check the output of crm_mon --help to see whether these options are available to you. In any case, executing an external agent will always be available, and you can use this agent to send emails, SNMP traps or whatever action you develop.
crm_mon の external-agent でコマンド呼び出し
man crm_mon
に --external-agent
はあったので、こっちを試してみる。
sudo tee /etc/sysconfig/crm_mon <<'EOS'
OPTIONS="--daemonize --external-agent=/vagrant/agent.sh --external-recipient=ore-recipient"
EOS
/vagrant/agent.sh
は次のような内容です。
# !/bin/bash
env | sort | /bin/logger -t ore-agent -i
crm_mon.service
を再起動します。
sudo systemctl restart crm_mon.service
sudo systemctl status crm_mon.service
意図的にリソース障害を発生させると /var/log/messages
に次のようなログが記録されました。
Apr 26 07:25:30 pm01 ore-agent[4553]: CRM_notify_desc=OK
Apr 26 07:25:30 pm01 ore-agent[4553]: CRM_notify_node=pm02
Apr 26 07:25:30 pm01 ore-agent[4553]: CRM_notify_rc=0
Apr 26 07:25:30 pm01 ore-agent[4553]: CRM_notify_recipient=ore-recipient
Apr 26 07:25:30 pm01 ore-agent[4553]: CRM_notify_rsc=dummy2
Apr 26 07:25:30 pm01 ore-agent[4553]: CRM_notify_status=0
Apr 26 07:25:30 pm01 ore-agent[4553]: CRM_notify_target_rc=0
Apr 26 07:25:30 pm01 ore-agent[4553]: CRM_notify_task=monitor
:
つまり、指定したコマンドがこれらの環境変数を付けて実行されるということなので、次のようにメール通知を設定してみます。
# !/bin/bash
env | grep ^CRM_notify | sort |
mail -s "[$CRM_notify_node] $CRM_notify_rsc $CRM_notify_task $CRM_notify_desc" root
意図的にリソース障害を発生させると、メールがだだだっと送信されました。
crm_mon を pacemaker のリソースにする
下記の例のように crm_mon
を systemd ではなく pacemaker のリソースとして管理しても良いかもしれません。
- http://clusterlabs.org/doc/en-US/Pacemaker/1.1/html/Pacemaker_Explained/s-notification-external.html
systemd の crm_mon.service
を停止します。
sudo systemctl stop crm_mon.service
sudo systemctl disable crm_mon.service
sudo systemctl status crm_mon.service
リソースエージェント ocf:pacemaker:ClusterMon
の説明を見てみます。
sudo pcs resource describe ocf:pacemaker:ClusterMon
下記のとおりです。
ocf:pacemaker:ClusterMon - Runs crm_mon in the background, recording the cluster status to an HTML file
This is a ClusterMon Resource Agent.
It outputs current cluster status to the html.
Resource options:
user: The user we want to run crm_mon as
update: How frequently should we update the cluster status
extra_options: Additional options to pass to crm_mon. Eg. -n -r
pidfile: PID file location to ensure only one instance is running
htmlfile: Location to write HTML output to.
次のように Clone リソースとして設定します。
sudo pcs resource create crm_mon ocf:pacemaker:ClusterMon \
user="root" extra_options="--external-agent=/vagrant/agent.sh" \
meta migration-threshold="INFINITY" --clone
crm_mon の external-agent で通知を間引く
すべてを通知すると結構な量のメールが飛んで来るので、下記のように間引きました。
# !/bin/bash
if [ "$CRM_notify_node" != "$(uname -n)" ]; then
# 自ノード以外は除外
exit 0
fi
if [ "$CRM_notify_task" == "monitor" ]; then
case "$CRM_notify_desc" in
OK|ok)
# monitor の OK は除外
exit 0
;;
esac
fi
env | grep ^CRM_notify | sort |
mail -s "[$CRM_notify_node] $CRM_notify_rsc $CRM_notify_task $CRM_notify_desc" root
このスクリプトを --external-agent
に設定すれば概ね以下のようなときだけ通知されます。
- リソースの開始/停止(失敗でも成功でも)
- リソースの監視で異常を検出
自ノードのリソース障害しか通知しないため、ノード障害が発生したときにはそのノードで稼働していたリソースの障害は通知されません(通知する crm_mon
が死んでいるので)。
Active/Standby のアクティブ側のノード障害なら、スタンバイ側のリソースが開始するので、その通知を持ってノード障害を推測することができますが、Clone リソースしか無い、とか、Active/Standby のスタンバイ側の障害、とかだと、この方法だけではノード障害を検出することができません。
ので、corosync-notifyd
と併用するのが良いかもしれません。
あるいは crm_mon
を Clone リソースとして設定しているなら crm_mon
リソースだけはノードに依らず通知してみるとか。
# !/bin/bash
if [ "$CRM_notify_node" != "$(uname -n)" ]; then
if [ "$CRM_notify_rsc" != "crm_mon" ]; then
exit 0
fi
fi
if [ "$CRM_notify_task" == "monitor" ]; then
case "$CRM_notify_desc" in
OK|ok)
exit 0
;;
esac
fi
env | grep ^CRM_notify | sort |
mail -s "[$CRM_notify_node] $CRM_notify_rsc $CRM_notify_task $CRM_notify_desc" root
これなら、例えば pm01 のノード障害時に、pm02 から、pm01 の crm_mon
が停止した旨の通知が送られてきます。ただし、pm01 が開始したときには pm01 と pm02 の両方から pm01 の crm_mon
が開始した旨の通知が送られてきますが。