fence_sshを試してみた

概要

fence_sshは、リモートノードをクラスタから安全に隔離するためのフェンシングエージェントです。SSHを利用してノードへのアクセスを行い、再起動や電源オフなどの操作を実行します。このエージェントはSSHを用いるため、対象ノードがハングアップして接続が確立できない場合にはフェンシングが機能しません。そのため、このエージェントは完全なフェンシングエージェントではなく、本番環境よりもテスト用途に適したツールです。
クラスタ環境での信頼性が重要な場合は、他のハードウェアベースのフェンシングエージェントの利用をおすすめします。

公式GitHubリポジトリでさらに詳しい情報を確認できます: リンク

今回はこのfence_sshを使ったPacemakerでのフェンシング設定について解説します。

今回の環境

2ノードのLinuxサーバで、OSはRockyLinux 8.10をインストールしています。
ホスト名はnode1とnode2になります。
PacemakerはLINBIT社のデモライセンスで入手したものを利用しています。デモライセンスは デモライセンス申請ページ から申請できます。

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

まずfence_sshの開発サイト(リンク)からfence_sshをダウンロードしてください。
ダウンロードしたファイルを/usr/sbinにコピーして、chmod コマンドで実行権を付与します。

# wget https://raw.githubusercontent.com/nannafudge/fence_ssh/refs/heads/master/fence_ssh
# mv fence_ssh /usr/sbin
# chmod 755 /usr/sbin/fence_ssh

また、fence_sshの実行にfence-agents-commonコマンドも必要になるため、これをdnf(yum)でインストールします。

# dnf install fence-agents-common

パッケージのインストールが終わったら、次はアカウントの設定を行います。

アカウントの設定

rootアカウントでfence_sshを動かすと設定が簡単です。fence_sshを利用するために、各ノードでSSHの公開鍵を作成して、公開鍵を交換しておきます。

公開鍵の作成と鍵交換

各ノードでssh-keygenコマンドを実行し、SSHの公開鍵を作成します。

  # ssh-keygen
 # ssh-copy-id root@node2

同じようにnode2でも実行します。

 # ssh-keygen
# ssh-copy-id root@node1

SSHによる疎通確認

rootアカウントで相互にSSHログインしてエラーなくログインできることを確認してください。

  # ssh root@node2   

同じようにnode2でも実行します。

 # ssh root@node1   

パスワードなしでsshログインに成功したら、次はパッケージfence_sshの試験を行います。

パッケージの単体試験

コマンドとしてfence_sshを実行して相手ノードが再起動できるかテストします。
次のように入力します。

  # fence_ssh -h node2 -u root -s true -o reboot

node1から実行して、node2が再起動すれば正常に動作しています。
もし動作しない場合は、次のようにbashのデバッグオプションをつけて実行してエラー箇所を調べて下さい。

  # bash -x /usr/sbin/fence_ssh -h ・・・・

Pacemakerの設定

過去に投稿したフェンシングの記事 (リンク) と同じく、Dummyリソースエージェントを使って
fence_sshの動作を確認します。Pacemakerの設定は以下のようになります。

node 1: node1
node 2: node2
primitive stonith1 stonith:fence_ssh \
        params hostname=node1 user=root pcmk_host_list=node1 \
        op monitor interval=60s 
primitive stonith2 stonith:fence_ssh \
        params hostname=node2 user=root pcmk_host_list=node2 \
        op monitor interval=60s 
primitive test Dummy \
        op start interval=0s timeout=30s \
        op monitor interval=10s timeout=60s \
        op stop interval=0s timeout=30s on-fail=fence
location l_stonith1 stonith1 -inf: node1
location l_stonith2 stonith2 -inf: node2
property cib-bootstrap-options: \
        stonith-enabled=true \
        no-quorum-policy=ignore \
        have-watchdog=false \
        cluster-infrastructure=corosync \
        cluster-name=cluster2 \
        dc-version=2.0.5.linbit-2.0.el8-ba59be712

testリソースのstopの引数にon-fail=fenceがあるので、停止に失敗するとフェンシングが発動して障害が発生したノードを相手ノードが再起動します。

動作確認

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

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の定義ににより停止に失敗します。この結果フェンシングが発動して、node1はnode2から停止されます。