Pacemakerでかんたんクラスタリング体験してみよう!

第3回Pacemakerでいろいろ設定してみよう![構築応用編]

さて、第2回では単純な1+1構成と簡単なリソースの起動を試してみましたが、今回はスプリットブレイン対策を考えてみたいと思います。

スプリットブレインって?

Pacemakerを設定する上で欠かせないのがスプリットブレイン対策です。スプリットブレインとはインターコネクト(ハートビート)通信が全て切断された状態のことです。

通常はあるサーバ(DCと呼ぶ)のPacemakerがクラスタ全体の指揮をとっていますが、スプリットブレインになると、各サーバのPacemakerが勝手に指揮をとり始めます。そうなると最悪の場合、各サーバでリソースが起動し、リソースの種類によってはデータの破壊やIPアドレスの競合といった状態を引き起こしてしまいます。

図1 スプリットブレイン
図1 スプリットブレイン

こういった状態を避けるためにインターコネクト用LANは冗長化することが望ましいのですが、それでもスプリットブレインになった時の対策として、Pacemakerの機能であるSTONITHや、リソースエージェント(RA)のsfex, VIPcheckを紹介します。

STONITH

STONITHはスプリットブレイン対策として最も有効な機能のひとつで、スプリットブレインになった場合に、強制的に相手のサーバをフェンシング (再起動) することで、最悪の事態を回避します。

この機能を使うには、相手から電源を落としてもらうためのハードウェア制御ボードが必要になります。現在、標準規格のIPMIをはじめ、HP社製サーバ搭載のiLO, IBM社製サーバ搭載のIMM等、複数の制御ボードに対応しており、それぞれのハードウェアに対応したプラグインが提供されています。どのようなプラグインが用意されているかは、以下のコマンドで確認できます。

# crm ra list stonith

なお上記コマンドで表示されるプラグインは、実際に電源を制御する実プラグイン以外に、STONITHの動作を補助するためのプラグインもあり、実際にはこれら補助プラグインと実プラグインを連携させて制御します。

では実際に設定してみましょう。クラスタ制御機能(Heartbeat)の設定は、第2回の設定を使用してください。今回は標準規格のIPMIを例に説明していきます。また説明をわかりやすくするために、他のリソースや補助プラグインは動かさず、実プラグインのみを動作させます。

ネットワーク構成はSTONITH専用にインターコネクト用LANとは別のインターフェースを用意し、相手のサーバのIPMIボードと接続してください。またIPMIボードには固定IPを割り振り、電源制御できるアカウントを用意しておいてください。今回は次のような設定を前提とします。

図2 STONITHの構成
図2 STONITHの構成
表1 ネットワーク設定
 IPMIボード
IPアドレス
IPMIボード
ユーザID
IPMIボード
パスワード
pm01192.168.100.1ipmiuser1ipmipass1
pm02192.168.100.2ipmiuser2ipmipass2

まず、環境によってはIPMI操作用のコマンドがインストールされていない可能性がありますので、OpenIPMI-toolsをインストールします。

(各サーバで実行)
# yum -y install OpenIPMI-tools

第2回のリソース制御機能(Pacemaker)の設定が残っている場合は一旦Pacemakerを停止し、設定をクリアします。第2回ではcrmコマンドでクリアしましたが、今回はファイルを削除する方法でやってみます。

(各サーバで実行)
# /etc/init.d/heartbeat stop
(各サーバで実行)
# rm -f /var/lib/heartbeat/crm/*
# /etc/init.d/heartbeat start

空っぽの状態でPacemakerが起動し、両サーバがOnlineになったことを確認します。

# crm_mon -A
============
省略
============

Online: [ pm01 pm02 ]

Node Attributes:
* Node pm02:
    + pm01-eth1                         : up
    + pm01-eth2                         : up
* Node pm01:
    + pm02-eth1                         : up
    + pm02-eth2                         : up

では設定していきます。設定には通常のリソース設定と同様にcrmコマンドを使用します。crmコマンドって何?という人は第2回を参照してください。今回は対話モードを使って設定してみたいと思います。

# crm configure
crm(live)configure# 

まずはクラスタ全体の設定です。上記プロンプトで以下の設定を入力します。

見やすいように"\"を使って改行しています。
property $id="cib-bootstrap-options" \
	no-quorum-policy="ignore" \
	stonith-enabled="true" \
	startup-fencing="false"

rsc_defaults resource-stickiness="INFINITY" \
                migration-threshold="1"

stonith-enabled="true" で、STONITH機能を有効にします。startup-fencingは、Pacemaker起動時に相手のサーバの状態が把握できない場合に念のために相手をフェンシングする機能で、起動時にすでにスプリットブレインになっていた場合などに有効に働きます。今回はfalse(無効)を使用します。no-quorum-policyは第2回の時と同様、2台構成の場合はおまじないと思って、ignoreを設定しておいてください。rsc_defaultsの設定も第2回と同様に設定します。

次にプラグインの設定です。今回はIPMIなので、external/ipmiというプラグイン(以下ipmiプラグイン)を使用します。なお、実際のプラグインの置き場所は64bit環境の場合/usr/lib64/stonith/plugins/ になります。では、ipmiプラグインにどのようなパラメータが必要なのか調べます。

# crm ra info stonith:external/ipmi
IPMI STONITH external device (stonith:external/ipmi)

ipmitool based power management. Apparently, the power off
method of ipmitool is intercepted by ACPI which then makes
a regular shutdown. If case of a split brain on a two-node
it may happen that no node survives. For two-node clusters
use only the reset method.

Parameters (* denotes required, [] the default):

hostname (string): Hostname
    The name of the host to be managed by this STONITH device.

ipaddr (string): IP Address
    The IP address of the STONITH device.

userid (string): Login
    The username used for logging in to the STONITH device.

passwd (string): Password
    The password used for logging in to the STONITH device.

interface (string, [lan]): IPMI interface
    IPMI interface to use, such as "lan" or "lanplus".

stonith-timeout (time, [60s]):
    How long to wait for the STONITH action to complete. Overrides the stonith-timeout cluster property

priority (integer, [0]):
    The priority of the stonith resource. The lower the number, the higher the priority.

Operations' defaults (advisory minimum):

    start         timeout=60
    stop          timeout=15
    status        timeout=60
    monitor_0     interval=3600 timeout=60

7つのパラメータがあるようです。

ではipmiプラグインを追加してみましょう。まずはpm01をフェンシングするためのリソース設定を追加します。

デフォルト値を使用するパラメータ(stonith-timeout, priority)については設定を省略しています。
primitive stonith1 stonith:external/ipmi \
	params \
		userid="ipmiuser1" \
		passwd="ipmipass1" \
		ipaddr="192.168.100.1" \
		hostname="pm01" \
		interface="lanplus" \
	op start interval="0s" timeout="60s" on-fail="restart" \
	op monitor interval="300s" timeout="60s" on-fail="restart" \
	op stop interval="0s" timeout="60s" on-fail="ignore"

"stonith1"は、このリソースを識別するIDで任意の文字列です。useridやpasswd, ipaddrには、IPMIボードに設定した情報を記述します。また、hostnameにはこの設定でフェンシングできるサーバ名 "pm01"を設定します。interfaceは、IPMIのバージョンに依存し、バージョン2.0の場合lanplus, バージョン1.5の場合lanを指定します。

同様にpm02をフェンシングするためのリソース設定を追加します。

primitive stonith2 stonith:external/ipmi \
	params \
		userid="ipmiuser2" \
		passwd="ipmipass2" \
		ipaddr="192.168.100.2" \
		hostname="pm02" \
		interface="lanplus" \
	op start interval="0s" timeout="60s" on-fail="restart" \
	op monitor interval="300s" timeout="60s" on-fail="restart" \
	op stop interval="0s" timeout="60s" on-fail="ignore"

以上の設定だけで一応STONITHリソースは起動しますが、これだけではSTONITHリソースがどのサーバで起動するかわかりません。Pacemakerは自分のサーバ上のSTONITHリソースで自分のサーバをフェンシングすることができないので、pm01をフェンシングするSTONITHリソースはpm02上で、pm02をフェンシングするSTONITHリソースはpm01上で起動するように制約設定を追加します。

location location-stonith1 stonith1 \
	rule 200: #uname eq pm02 \
	rule -INFINITY: #uname eq pm01

location location-stonith2 stonith2 \
	rule 200: #uname eq pm01 \
	rule -INFINITY: #uname eq pm02

200や-INFINITY(-1000000と同等)は優先度を表すスコア値と呼ばれるもので、上3行の意味を要約すると、先ほど設定したstonith1というリソースはホスト名pm02というサーバ上ではスコア値200になり、ホスト名pm01というサーバ上では-INFINITY、つまりリソース起動禁止となります。

以上で設定完了です。設定を反映させ、設定モードを終了します。

crm(live)configure# commit
crm(live)configure# exit

実際にSTONITHリソースが起動したかどうか確認してみましょう。

# crm_mon
============
省略
============

Online: [ pm01 pm02 ]

stonith1        (stonith:external/ipmi):        Started pm02
stonith2        (stonith:external/ipmi):        Started pm01

stonith1, stonith2が、pm02, pm01でStartedになり、無事意図したサーバで起動しました。

実際にインターコネクト通信のケーブルを全部抜いて、フェンシングが実行されれば成功です。通信断検知直後(スプリットブレイン状態時)は相手のサーバはUNCLEANという状態になり、フェンシングが成功するとOFFLINEになります。

# crm_mon
============
省略
============

Online: [ pm01 ]
OFFLINE: [ pm02 ]

stonith2        (stonith:external/ipmi):        Started pm01

なお、STONITHは通常のリソースの故障にも使うことができますので紹介しておきます。第2回の仮想IPの設定を例にすると、以下のような設定があったと思います。

primitive vip ocf:heartbeat:IPaddr2 \
        params ip="192.168.68.100" \
                nic="eth0" cidr_netmask="24" \
        op monitor interval="10s"

この"op" の設定には故障時の動作をon-failで定義することができます。たとえば以下のように op stop のon-failにfenceという設定をすると、リソースの停止失敗時に、STONITHでフェンシングすることできます。これによりフェイルオーバ中の中途半端な状態で止まってしまうことを防ぐことができます。第2回の設定と組み合わせてチャレンジしてみてください。

primitive vip ocf:heartbeat:IPaddr2 \
        params ip="192.168.68.100" \
                nic="eth0" cidr_netmask="24" \
        op start interval="0s" on-fail="restart" \
        op monitor interval="10s" on-fail="restart" \
        op stop interval="0s" on-fail="fence"

sfex

STONITHはPacemaker本体の機能とプラグインで実現していますが、排他制御を実現するためのリソースエージェント(RA)もいくつか存在します。その代表がsfexです。これは共有ディスクを使用している環境で使用できます。

sfexは起動されると共有ディスク上のsfex専用パーティションに所有権を定期的に書き込みます。この情報を元に、相手のサーバが生きているかどうかを判断します。つまり、相手のサーバのsfexが起動している時に自分のサーバのsfexを起動しようとするとリソース故障状態になります。もちろんsfexは単なるリソースエージェントに過ぎないので、有効に活用するにはsfexを二重起動させたくないリソースと同じグループに入れ、常にsfexを最初に起動するようにします。

なお、sfexや下記で紹介するVIPcheckだけでは、STONITHのようにリソース停止失敗時のサービス停止を防ぐことができないので、STONITHと併用することをお勧めします。なお、以下では説明を簡単にするためにSTONITHは無効にしています。

では、sfexを設定してみましょう。図4のように、ファイルシステムのマウント・アンマウントを実現するFilesystem RAとsfex RAを使い共有ディスクのダブルマウントを防いでみます。

図4 sfexの構成
図4 sfexの構成

まずはsfex専用パーティションの用意です。サイズは1024バイトもあれば十分です。fdiskやpartedコマンド等を使って共有ディスク上に用意しておいてください。今回は/dev/sdb1とします。ファイルシステムを作成する必要はなく、代わりに以下のコマンドで初期化します。-n は排他制御したいサーバ間で使う識別番号です。

# sfex_init -n 1 /dev/sdb1

次にリソースの設定を行います。今回、Filesystemリソースは、/dev/sdb2を/mnt/tmpにext3としてマウントするようにしたいと思います。

(どちらかのサーバ上で実行)
# mke2fs -j /dev/sdb2
(各サーバで実行)
# mkdir /mnt/tmp

各サーバでマウントができるか確認しておいてください。その際各サーバで同時にマウント(ダブルマウント)しないように注意してください。では、一旦Pacemakerの設定はクリアします。

(各サーバで実行)
# /etc/init.d/heartbeat stop
(各サーバで実行)
# rm -f /var/lib/heartbeat/crm/*
# /etc/init.d/heartbeat start

Pacemaker起動後、crmコマンドで設定していきます

# crm configure
crm(live)configure#

以下の設定を投入します。

property $id="cib-bootstrap-options" \
        no-quorum-policy="ignore" \
        stonith-enabled="false" \
        startup-fencing="false"

primitive sfex ocf:heartbeat:sfex \
        params \
                index="1" \
                device="/dev/sdb1" \
        op start interval="0s" timeout="120s" on-fail="restart" \
        op monitor interval="10s" timeout="60s" on-fail="restart" \
        op stop interval="0s" timeout="60s" on-fail="block"

primitive filesystem ocf:heartbeat:Filesystem \
        params \
                fstype="ext3" \
                device="/dev/sdb2" \
                directory="/mnt/tmp" \
        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="block"

group group1 sfex filesystem

sfexのindexパラメータにsfex_init実行時に設定した識別番号を、deviceパラメータに用意したsfex専用パーティションを設定します。またgroupの設定により、リソースの起動順番はsfex, filesystemとなり、sfexが起動成功しない限りファイルシステムがマウントされることはありません。

ではcommitで設定反映します。

crm(live)configure# commit

以下のようにリソースが起動すれば成功です。

# crm_mon
============
省略
============

Online: [ pm01 pm02 ]

 Resource Group: group1
     sfex       (ocf::heartbeat:sfex):  Started pm01
     filesystem (ocf::heartbeat:Filesystem):    Started pm01

ではここでインターコネクト通信を全て抜いて、スプリットブレインを発生させて見ましょう。今回はSTONITHが動いていないので、各サーバで以下のような表示になります。

pm01側の表示
============
省略
Current DC: pm01 (519bb7a2-3c31-414a-b6b2-eaef36a09fb7) - partition with quorum
省略
============

Online: [ pm01 ]
OFFLINE: [ pm02 ]

 Resource Group: group1
     sfex       (ocf::heartbeat:sfex):  Started pm01
     filesystem (ocf::heartbeat:Filesystem):    Started pm01
pm02側の表示
pm02# crm_mon
============
省略
Current DC: pm02 (8c93dc22-a27e-409b-8112-4073de622daf) - partition with quorum
省略
============

Online: [ pm02 ]
OFFLINE: [ pm01 ]


Failed actions:
    sfex_start_0 (node=pm02, call=4, rc=1, status=complete): unknown error

pm01側では今までリソースが起動していたので、そのまま起動し続けますが、pm02側ではsfexの起動故障が発生(Faild actionsのsfex_start_0の行)し、filesystemの起動を見事抑止してくれました。なお、あえてヘッダ部分の表示を残していますが、このようにpm01側では自分がクラスタ全体の指揮している(DC)と表示され、pm02側も自分がDCだと表示されます。これがスプリットブレインになっている証拠になります。

VIPcheck

最後に、排他制御を実現するもう一つのリソースエージェントVIPcheckを紹介します。これはLinux-HA Japan提供のpm_extrasパッケージに入っており、主に仮想IP(IPaddrやIPaddr2 RA)を使用している場合に使用可能です。

動作イメージはsfexと同じで、sfexの場合は共有ディスクを参照して相手の状態を確認しますが、VIPcheckは仮想IPを参照(ping)して相手の状態を確認します。具体的には仮想IPに対してpingを打ち、応答があれば相手のサーバでリソースが起動していると判断し、自分のサーバのVIPcheckは起動できずリソース故障状態になります。

図5 VIPcheckの構成
図5 VIPcheckの構成

なお、sfexの場合、共有ディスクのケーブルが抜けて、ディスクにアクセスできない場合に起動できないのに対し、VIPcheckはネットワークケーブルが抜けてpingに応答しない場合に起動成功するので、残念ながらsfexに比べて信頼性は低いと言えるでしょう。リソース設定イメージはsfexと同じなので、今回は紹介だけにとどめておきます。

まとめ

第3回では構築応用編としてスプリットブレイン対策の機能、設定例を紹介しました。

最初からいろいろと設定された複雑な構成を見ると、Pacemakerの設定は難しそうなイメージを抱く人が多いのですが、このように一つ一つの機能を分解して見ると結構簡単ではなかったでしょうか。いよいよ次回からは運用編として、いろいろな故障を起こしてみたり、その時の復旧方法を紹介したりする予定ですのでお楽しみに。

おすすめ記事

記事・ニュース一覧