こんにちは SCSK 野口です。
前回の記事 『LifeKeeperの「Quorum/Witness」とは』 では、
Quorum/Witnessの種類とパラメータについてご紹介いたしました。
まだ、お読みでない方は上記リンクからご覧ください。
本記事では、Quorum/Witness(Storage)を仮想マシン上のLinux環境に導入してみます。
今回、共有ストレージには「blockタイプ」を採用します。
おさらい
前回の記事でもお伝えしましたが、共有ストレージは各ノードからアクセス可能なストレージのことです。
Quorum/Witness機能専用で使用する共有ストレージは、LifeKeeperリソースとして保護することはできません。
あくまでもスプリットブレインを回避する機能のために使用します。
Storageモードでは、下記3つの共有ストレージの種類(タイプ)が選択できます。
・block………共有ストレージに物理ストレージやRDM(物理互換)、iSCSI(VM 内イニシエーター)を使用する場合
・file…………共有ストレージにNFS (または Amazon EFS) を使用する場合
・aws_s3……共有ストレージに AmazonのS3 、または Amazon S3互換のオブジェクトストレージを使用する場合
※ Windowsの場合は、blockタイプはありません。

ちなみにStorageモードは、2ノード以上4ノード以下から利用可能よ!

導入
今回の構成について
今回の構成では Virtual Box(仮想VM)を使用し、2台のサーバ(ノード)構成にします。
また、共有ストレージについては VDI(Virtual Disck Image)を使用していきます。
そして、1QWKオブジェクトあたり必要な容量は 4096バイト (4KB) となります。
「QWK_STORAGE_TYPE」を blockタイプにした場合、QWK オブジェクトの配置場所は以下となります。

今回は2台のサーバ(ノード)だから、
QWKオブジェクトに必要な容量は 8192バイト(8KB)だよ!

2つのパーティションを用意する必要があるんだね!
動作環境
今回の Qurum/Witness(Storage構成) を導入した構成は以下となります。

一般的な Active/Standby 構成ね

稼働系ノードの障害時に待機系ノードにサービスを引き継ぐんだよね!
導入手順
1.サーバをセットアップし、他のサーバとネットワーク通信ができることを確認します。
※ サーバセットアップの詳細は省かせていただきます。
サーバ間で通信できているか、お互いに pingコマンドで疎通確認してみます。
PING rhel75n02 (~.~.~.~) 56(84) bytes of data.
64 bytes from rhel75n02 (~.~.~.~): icmp_seq=1 ttl=64 time=1.68 ms
64 bytes from rhel75n02 (~.~.~.~): icmp_seq=2 ttl=64 time=0.943 ms
64 bytes from rhel75n02 (~.~.~.~): icmp_seq=3 ttl=64 time=0.960 ms
— rhel75n02 ping statistics — 3 packets transmitted, 3 received, 0% packet loss, time 2003ms
rtt min/avg/max/mdev = 0.943/1.194/1.681/0.346 ms
PING rhel75n01 (~.~.~.~) 56(84) bytes of data.
64 bytes from rhel75n01 (~.~.~.~): icmp_seq=1 ttl=64 time=1.49 ms
64 bytes from rhel75n01 (~.~.~.~): icmp_seq=2 ttl=64 time=0.913 ms
64 bytes from rhel75n01 (~.~.~.~): icmp_seq=3 ttl=64 time=0.909 ms
— rhel75n01 ping statistics — 3 packets transmitted, 3 received, 0% packet loss, time 2004ms
rtt min/avg/max/mdev = 0.909/1.106/1.496/0.275 ms
2.サーバに LifeKeeper をインストールします。
その際、「Use Quorum/Witness functions」を有効にし、Quorum/Wintness パッケージをインストールします。
3.全てのノード間でコミュニケーションパスを作成し、ALIVEであることを確認します。
今回は LKWMCなので、左タスクバーの「コミュニケーションパス」を選択します。
※ コミュニケーションパス(ハートビート)が1つの場合、「リソースツリー」画面では警告が表示されます。
コミュニケーションパスのステータスが「ALIVE」であることを確認します。
4.すべてのノードで Quorum/Witness の設定を行います。(/etc/default/LifeKeeper)
※ パラメータについては、冒頭でお話しした記事を参照してください。
QUORUM_MODE=storage # デフォルト値は majority です
# What style of quorum verification do we do in comm_up/down
# and lcm_avail (maybe other) event handlers.
# NOTE: This only matters of the quorum support is installed
# (the steeleye-lkQWK package).
# The possible values are:
# – none/off: Do nothing, skip the check, assume all is well.
# – majority: Verify that this node and the nodes it can reach
# have more tha half the cluster nodes.
# – tcp_remote: Verify that this node can reach more than half
# of the QUORUM_HOSTS via tcp/ip.
# – storage: Verify by the QWK storage protocol (requires
# additional configuration).
WITNESS_MODE=storage #デフォルト値は remote_verify です
# This can be either off/none, remote_verify or storage.
# In remote_verify mode, core event handlers (comm_down) will
# double check the death of a system by seeing if other visible
# nodes also think it’s dead.
# In storage mode, core event handlers (comm_down) will check
# the death of a system by the QWK storage protocol.
なお、Storageモードを利用しているため、必要なパラメータは設定ファイルの末尾に追加します。
LK_DISTRIBUTION=redhat
LK_DISTRIBUTION_VERSION=7.5-8.el7ON_VERSION=7.5-8.el
QWK_STORAGE_TYPE=block #(必須)追記
QWK_STORAGE_HBEATTIME=6 #(任意)追記しない場合はデフォルト値 (6)となる
QWK_STORAGE_NUMHBEATS=4 #(任意)追記しない場合はデフォルト値 (4)となる
QWK_STORAGE_OBJECT_rhel75n01=/dev/sdc1 #(必須)追記
QWK_STORAGE_OBJECT_rhel75n02=/dev/sdc2 #(必須)追記

「QWK_STORAGE_OBJECT_ <ホスト名>」のパラメーターは、
ホスト名に” – ” と ” . ” を含む場合、” _ ” (アンダースコア)に置き換えてください!

「 node-1 」と「 node-2 」や「 node.1 」と「 node.2 」の場合は、
「 node_1 」と「 node_2 」に置き換えて追記すればいいんだね!
1号機(rhel75n01)からqwk_storage_init コマンドを実行します。
※ 「QWKオブジェクトとして既に存在しますが上書きしますか?」 と問われるので ”y” を入力し、[Enter] を押します。
ok: LifeKeeper is running.
ok: The LifeKeeper license key is successfully installed.
ok: QWK parameter is valid.
QWK object of /dev/sdc1 is not yet avail.
/dev/sdc1 already exsits as not QWK_STORAGE_OBJECT: overwrite? (y/N): y
すると、全ノードで QWK オブジェクトの初期化が終わるまで待ち状態になります。
ok: LifeKeeper is running.
ok: The LifeKeeper license key is successfully installed.
ok: QWK parameter is valid.
QWK object of /dev/sdc1 is not yet avail.
/dev/sdc1 already exsits as not QWK_STORAGE_OBJECT: overwrite? (y/N): y
ok: The path of QWK object is valid.
ok: down: /opt/LifeKeeper/etc/service/qwk-storage: 2764s
ok: Initialization of QWK object of own node is completed.
QWK object of /dev/sdc2 is not yet avail.
QWK object of /dev/sdc2 is not yet avail.
QWK object of /dev/sdc2 is not yet avail.
2号機(rhel75n02)からも qwk_storage_init コマンドを実行すると、
2号機(rhel75n02)1号機(rhel75n01)ともに 「 Successful. 」 と出力されます。
※ 1号機(rhel75n01)と同様のことを問われるので ”y” を入力し、[Enter] を押します。
ok: LifeKeeper is running.
ok: The LifeKeeper license key is successfully installed.
ok: QWK parameter is valid.
QWK object of /dev/sdc2 is not yet avail.
/dev/sdc2 already exsits as not QWK_STORAGE_OBJECT: overwrite? (y/N): y
ok: The path of QWK object is valid.
ok: down: /opt/LifeKeeper/etc/service/qwk-storage: 2788s
ok: Initialization of QWK object of own node is completed.
ok: quorum system is ready.
ok: run: /opt/LifeKeeper/etc/service/qwk-storage: (pid 5152) 1s, normally down
Successful.
ちなみに初期化後のログを確認したところ、以下のようなメッセージが出力されます。
Jul 15 17:39:43 rhel75n01 runsv[4974]: INFO:runit:::013008:qwk-storage server is starting up Jul 15 17:39:43 rhel75n01 qwk_storage_server[4973]: INFO:qwk:::135805:starting qwk_storage_server Jul 15 17:39:43 rhel75n01 qwk_storage_server[4973]: INFO:qwk:::135848:[rhel75n01:/dev/sdc1] invalid qwk object was found. initializing to sequence 0. Jul 15 17:39:43 rhel75n01 qwk_storage_server[4973]: INFO:qwk:::135848:[rhel75n02:/dev/sdc2] invalid qwk object was found. initializing to sequence 0. Jul 15 17:39:43 rhel75n01 qwk_storage_server[4973]: INFO:qwk:::135923:[rhel75n01:/dev/sdc1] qwk object was restored. Jul 15 17:39:43 rhel75n01 qwk_storage_server[4973]: INFO:qwk:::135924:quorum state changed to AVAIL. Jul 15 17:39:55 rhel75n01 qwk_storage_server[4973]: INFO:qwk:::135923:[rhel75n02:/dev/sdc2] qwk object was restored.

この手順が完了すると、クラスターにおいて Quorum および Witnessの機能が有効化されるわ!
フェイルオーバーが実行される前に Quorumチェック と Witnessチェックが実施されるよ!!

ちなみに、共有ストレージにアクセスできなくなるとリソースの起動に影響するよ。
だから、すべてのノードから常時アクセス可能な共有ストレージが必要だよ!
動作確認
QWKオブジェクトが指定された間隔で更新されているか、実際に確認してみます。
更新間隔は/etc/default/LifeKeeper に記載される QWK_STORAGE_HBEATTIME(デフォルト6)で定義されます。
1号機(rhel75n01)から ddコマンドを 2回実行し、QWK オブジェクト1が更新されているか確認してみます。
※ 2回目の ddコマンドを実行する際は、指定された時間と同じくらい間隔をあけてください。
1+0 レコード入力
1+0 レコード出力
4096 バイト (4.1 kB) コピーされました、 0.0016561 秒、 2.5 MB/秒
signature=lifekeeper_qwk_object
local_node=rhel75n01
time=Fri Jul 16 01:31:15 2025
sequence=8651
node=rhel75n02
commstat=UP
checksum=9659698734818933381
[root@rhel75n01 ~]# dd if=/dev/sdc1 bs=4096 count=1 | strings
1+0 レコード入力
1+0 レコード出力
4096 バイト (4.1 kB) コピーされました、 0.00232737 秒、 1.8 MB/秒
signature=lifekeeper_qwk_object
local_node=rhel75n01
time=Fri Jul 16 01:31:21 2025
sequence=8652
node=rhel75n02
commstat=UP
checksum=9659699284571077253
1号機(rhel75n01)からQWK オブジェクト2(/dev/sdc2)も確認してみます。
※ 2号機からの確認は省かせていただきます。
1+0 レコード入力
1+0 レコード出力
4096 バイト (4.1 kB) コピーされました、 0.0110848 秒、 370 kB/秒
signature=lifekeeper_qwk_object
local_node=rhel75n02
time=Fri Jul 16 01:50:10 2025
sequence=8833
node=rhel75n01
commstat=UP
checksum=9643936960751614597
[root@rhel75n01 ~]# dd if=/dev/sdc2 bs=4096 count=1 | strings
1+0 レコード入力
1+0 レコード出力
4096 バイト (4.1 kB) コピーされました、 0.000993328 秒、 4.1 MB/秒
signature=lifekeeper_qwk_object
local_node=rhel75n02
time=Fri Jul 16 01:50:16 2025
sequence=8834
node=rhel75n01
commstat=UP
checksum=9643937510513719941

両ノード( rhel75n01 と rhel75n02 )のタイムスタンプは同じになるとは限らないわよ
なお、 Quorum/Witness(Storage)を導入しているサーバでは、
OS起動後にログを確認すると以下のようなメッセージが出力されます。
Jul 16 10:13:05 rhel75n01 qwk_storage_server[2960]: INFO:qwk:::135857:[rhel75n02:/dev/sdc2] lcd sys state: UP (It looks the same from its own node and from the target node.) Jul 16 10:13:05 rhel75n01 qwk_storage_server[2960]: INFO:qwk:::135863:[rhel75n02:/dev/sdc2] remote node up (status=CR1) Jul 16 10:13:05 rhel75n01 qwk_storage_server[2960]: INFO:qwk:::135866:quorum_verify(LCM_AVAIL, ): AVAIL Jul 16 10:13:14 rhel75n01 qwk_storage_server[2960]: INFO:qwk:::135857:[rhel75n02:/dev/sdc2] lcd sys state: UP (It looks the same from its own node and from the target node.) Jul 16 10:13:14 rhel75n01 qwk_storage_server[2960]: INFO:qwk:::135863:[rhel75n02:/dev/sdc2] remote node up (status=CR1) Jul 16 10:13:14 rhel75n01 qwk_storage_server[2960]: INFO:qwk:::135866:quorum_verify(COMM_UP, rhel75n02): AVAIL Jul 16 10:13:14 rhel75n01 qwk_storage_server[2960]: INFO:qwk:::135868:witness_verify(COMM_UP, rhel75n01): UP Jul 16 10:13:14 rhel75n01 qwk_storage_server[2960]: INFO:qwk:::135868:witness_verify(COMM_UP, rhel75n02): UP
まとめ
今回は Quorum/Witness を実際に導入してみましたがいかがでしたか。
導入する際は、以下の点に注意してください。
・導入する前に、ホスト名やノード数に細心の注意を払う。
・導入する際は、コミュニケーションパスが Aliveであることを確認する。
・動作確認では、指定された間隔で更新されているかタイムスタンプを確認する。