Pacemakerフェンシング入門

HAクラスターで故障したサーバの再起動が必要になることがあります。
たとえばカーネルパニックなどでサーバへのアクセスができなくなったような場合です。アクセスができなくなっても、OSのストレージへのアクセスが生き残っていると、ストレージへの二重アクセスが発生し、最悪データが破損する可能性が発生します。このような問題を防止するため、正常なサーバから故障したサーバを停止したり、再起動する機能をPacemakerは持っていてフェンシングと呼ばれます。

相手のサーバを停止するための機能は、IPMIやHP社製サーバのiLO、IBM社製サーバのIMM等のハードウェア制御ボードを利用します。制御ボードの仕様は各ボードで異なっているため、試すのは難しいですが、仮想環境ならばソフト的に制御できるのでフェンシングの動作確認が簡単にできます。

今回はVirtualboxの環境で使えるfence_vboxでフェンシングの設定と動作確認の方法を説明します。

1.テスト環境の準備

Virtualboxの環境にテスト用の仮想ゲスト(node1、node2)を2つ用意します。
各仮想ゲストのOSやIPアドレスは下図のように設定しました。

LINBIT HAのデモライセンスを使って、node1、node2にPacemakerとCorosyncをインストールしておきます。今回の動作確認に使ったPacemakerとCorosyncのバージョンは以下になります。

  • corosync-3.1.0
  • pacemaker-2.0.5

デモライセンスの申請は「作っておぼえるHAシステム」の中で申請リンクを紹介しています。

2.fence_vboxの動作確認

fence_vboxは内部でVirtualboxのVBoxManageコマンド使っています。まずはVBoxManageで動作を確認します。Virtualboxが動いているサーバ(仮想ホスト)で、Virtualboxを起動したユーザアカウントを使ってVBoxManageを実行します。

[hauser@es ~]$ VBoxManage list runningvms 
"CentOS83-1" {1d5b852d-34ea-4862-a370-ca42a845eb3c} 
"CentOS83-2" {63eadfc6-f29d-45a8-863c-3eed4785ba90}

ここで表示されているCentOS83-1とCentOS83-2は仮想ゲストOSを特定するIDになります。

VBoxManageコマンドの動作確認ができたら、次に仮想ゲストからsshで仮想ホストへログインできるか確認します。fence_vboxはsshでログインしてVBoxManageを実行するので、sshの設定は必須です。

[root@node1 ~]# ssh -l hauser 192.168.3.10
 hauser@192.168.3.10's password: 
 Last login: Tue Mar 30 10:06:42 2021 from node2
 [hauser@es ~]$ 

ユーザID hauserとパスワード *****でログインできることが確認できました。

最後にfence_vboxの動作を確認します。LINBITのリポジトリからfence_vboxをインストールします。node1、node2両方にインストールします。

root@node1 ~]# yum install fence-agents-vbox
依存関係が解決しました。
=======================================
 パッケージ                            
=======================================
インストール:
 fence-agents-vbox...
.....
.....
インストール済み:
  fence-agents-vbox-4.7.0.linbit-15.0.el8.noarch....
.....
.....

完了しました!

インストールが終わったらfence_vboxが単独で動作するか試してみましょう

[root@node1 ~]# fence_vbox -o list   -a "192.168.3.10" -l hauser -p *****
 CentOS83-1,1d5b852d-34ea-4862-a370-ca42a845eb3c
 CentOS83-2,63eadfc6-f29d-45a8-863c-3eed4785ba90
 …
 …

仮想ホストで動作中のホストの一覧が表示されました。
次にnode2の状態を確認してみます。

[root@node1 ~]# fence_vbox -o status -a "192.168.3.10" -l hauser -p ***** -n CentOS83-2
 Status: ON

node2のStatusがONで動作していることが確認できました。
最後にnode2が再起動ができるか確認します。

[root@node1 ~]# fence_vbox -o reboot -a "192.168.3.10" -l hauser -p ***** -n CentOS83-2
 Success: Rebooted

fence_vboxを使ってnode2(CentOS83-2)を再起動できました。

3.Pacemakerの設定

 Dummyリソースエージェントを使ったtestというリソースを定義します。Pacemakerの定義は次のようになります。

node 1: node1
node 2: node2
primitive test Dummy \
	op start interval=0s timeout=30s \
	op monitor interval=10s timeout=60s \
	op stop interval=0s timeout=30s
property cib-bootstrap-options: \
	stonith-enabled=false \
	have-watchdog=false \
	dc-version=2.0.5.linbit-1.0.el8-ba59be712 \
	cluster-infrastructure=corosync \
	cluster-name=cluster2 \
	last-lrm-refresh=1616579453

stonith-enabledをfalseにしてフェンシングを無効にしておきます。

crm_monコマンドで動作を確認します。

[root@node2 ~]# crm_mon -frAD
Cluster Summary:
  * Stack: corosync
  * Current DC: node1 (version 2.0.5.linbit-1.0.el8-ba59be712) - partition with quorum
  * Last updated: Tue Mar 30 14:26:25 2021
  * Last change:  Tue Mar 30 10:21:56 2021 by root via cibadmin on node1
  * 2 nodes configured
  * 1 resource instance configured

Node List:
  * Online: [ node1 node2 ]

Full List of Resources:
  * test	(ocf::heartbeat:Dummy):	 Started node1

Migration Summary:

リソースtestがnode1とnode2でアクティブ・スタンバイなリソースとして動きます。もしnode1が障害で停止すると、node2でリソースtestが動き始めます。

次にfence_vboxのリソースを定義します。
nodo1を停止するためのfence_node1とnode2を停止するためのfence_node2を定義します。

primitive fence_node1 stonith:fence_vbox \
	params ipaddr=192.168.3.10 login=hauser passwd="******" pcmk_host_map="node1:CentOS83-1" \
	op monitor interval=60s
primitive fence_node2 stonith:fence_vbox \
	params ipaddr=192.168.3.10 login=hauser passwd="******" pcmk_host_map="node2:CentOS83-2" \
	op monitor interval=60s

fence_node1はnode2でfence_node2はnode1で実行します。location設定でリソースが実行されるサーバを固定します。

location lo-fence_node1 fence_node1 -inf: node1
location lo-fence_node2 fence_node2 -inf: node2

locationのスコアを-infとしたので、fence_node1はnode1で動かない、fence_node2はnode2で動かないという意味になります。

次にtestリソースを修正して停止に失敗したら、フェンシングが実行されるようにします。

primitive test Dummy \
     op start interval=0s timeout=30s \
     op monitor interval=10s timeout=60s \
     op stop interval=0s timeout=30s on-fail=fence

timeoutが30sに定義されているので、Pacemakerがtestリソースに停止の命令を出したのち、30秒以上かかると停止の処理がエラーになっていると判断します。エラーの場合フェンシングが実行されます。

最後に、stonith-enabledをtrueにしてフェンシング機能を有効にします。

[root@node2 ~]# crm_mon -frAD1
Cluster Summary:
  * Stack: corosync
  * Current DC: node1 (version 2.0.5.linbit-1.0.el8-ba59be712) - partition with quorum
  * Last updated: Tue Mar 30 14:39:00 2021
  * Last change:  Tue Mar 30 14:38:38 2021 by root via cibadmin on node1
  * 2 nodes configured
  * 3 resource instances configured

Node List:
  * Online: [ node1 node2 ]

Full List of Resources:
  * test	(ocf::heartbeat:Dummy):	 Started node1
  * fence_node1	(stonith:fence_vbox):	 Started node2
  * fence_node2	(stonith:fence_vbox):	 Started node1

Migration Summary:

4.動作確認

フェンシングの動作を確認します。testリソースに停止のエラーを発生させて、fence_vboxが起動するか確認します。

testリソースを定義しているDummyリソースエージェントは
/usr/lib/ocf/resource.d/heartbeat/Dummyにあるシェルスクリプトです。
このファイルの119行目は次のようになっています。

dummy_stop() {
     dummy_monitor
     if [ $? =  $OCF_SUCCESS ]; then
         rm ${OCF_RESKEY_state}
     fi
     return $OCF_SUCCESS
 }

dummy_stop()はtestリソースが停止の時に呼ばれる定義なので、ここにsleep命令を入れて30秒以上処理時間が経過するように書き換えると、Pacemakerはtestリソースの停止が失敗したと判断します。

dummy_stop() {
     sleep 32  # <- 追加行
     dummy_monitor
     if [ $? =  $OCF_SUCCESS ]; then
         rm ${OCF_RESKEY_state}
     fi
     return $OCF_SUCCESS
 }

node1のDummyリソースエージェントにのみ修正してください。

node1でtestリソースが動いていることを確認して、node1のPacemakerを停止します。Pacemakerの停止でtestリソースも停止しようとしますが、sleep 32の定義ににより停止に失敗します。

停止失敗に対してfence_node1がnode2から起動されてnode1は再起動します。
node1の再起動によりリソースはnode2で実行されます。

[root@node2 ~]# crm_mon -frAD
Cluster Summary:
  * Stack: corosync
  * Current DC: node2 (version 2.0.5.linbit-1.0.el8-ba59be712) - partition with quorum
  * Last updated: Tue Mar 30 14:58:18 2021
  * Last change:  Tue Mar 30 14:38:38 2021 by root via cibadmin on node1
  * 2 nodes configured
  * 3 resource instances configured

Node List:
  * Online: [ node2 ]
  * OFFLINE: [ node1 ]

Full List of Resources:
  * test	(ocf::heartbeat:Dummy):	 Started node2
  * fence_node1	(stonith:fence_vbox):	 Started node2
  * fence_node2	(stonith:fence_vbox):	 Stopped

Migration Summary: