SFEX (Shared Disk File EXclusiveness Control Program)
目的
SFEXはActive-Standbyのクラスタ構成で運用中、Heartbeat通信が切れた場合に両ノードがActiveとなる(スプリットブレイン状態)ことを防ぐために使用します。
ダウンロード
バイナリファイルはRHEL5用です。
バイナリファイル(32bit) --- sfex-1.3-i386.zip (52.9 KB) [md5sum: 0d6ee79540a6995468ad89f1dd6887ea]
バイナリファイル(64bit) --- sfex-1.3-x86_64.zip (59.7 KB) [md5sum: 3f4e6b30daca2a681b1029c8888b9112]
ソースファイル --- sfex-1.3.tar.gz (79.1 KB) [md5sum: 6bc563ad4a22d39b5f0fcf8726138ae8]
基本的な考え方
- SFEXは共有ディスクの所有権を制御するリソースです。
- SFEXは共有ディスク上の特別なパーティションを使い、以下のデータを扱います。
- "status" 誰かにディスクが所有されているかを示します。
- "node" ディスクを所有しているノード名を示します。
- "count" ディスクを所有しているノードが生きているか判断するために使われます。
- 一般的に、共有ディスク上のデータパーティションを使うリソース(例えば、PostgreSQL)と一緒にリソースグループを作ります。
- 所有権を持ったノードのリソースのみがデータパーティションにアクセスできます。
- いつ、ノードは所有権を獲得できるか?
- ケース1:誰も所有権を持っていないとき。
- ケース2:他のノードがダウンしていると判断できるとき。
シーケンス図
起動処理
SFEXはcib.xmlの中で高いスコアが付けられたノードで開始されます。そのため、複数のノードで、同時に共有ディスクにアクセスすることはありません。
Node A
- SFEXは共有ディスクからデータを読み、"status"を取得します。通常、共有ディスクはだれにも所有されていないので"status"は"NO_OWNED"となります。
- node=Node Aとstatus=OWNEDを含むデータを書き込みます。
- 再びデータを読み込み、node="Node A"のデータを取得します。
- 自身のノード名と比較します。ノード名が変更されていなければ、Node Aが所有権を獲得します。
- SFEXはその後、Heartbeatのモニタ処理によって共有ディスク上の"count"の値をインクリメントします。
この処理は所有権の更新を意味します。
Heartbeat通信断
Node A
- SFEXはHB更新処理によって所有権を更新します。
Node B
- heartbeat通信が失敗したとき、スタンバイノード(Node B)はリソースを起動します。
- SFEXは共有ディスク上のデータを読み込みます。
- しばらく処理を待ちます。(待ち時間はsfexのモニタ間隔より長くするべきです。この待ち時間により、Node Aによる定期的な更新を待ち、Node Aが所有権を持っていることを確認します。)
- 再びデータを読み込みます。
- 新しい"count"の値を確認します。二つの"count"の値が異なった場合、Node Aが動作中であると判断できます。
- Node Aが動作中であるため、SFEX起動処理は停止します。
アクティブノードのダウン
Node A
- 故障によってNode Aがダウン
Node B
このNode B起動処理はHB通信断と同じように行われます。
- しばらく待ちます。(Node Aの定期的な更新を待つが、Node Aが更新するこを確認できない)
- SFEXはデータを再び読みます。
- 新旧、二つの"count"の値を比較すると"count"の値が同じになります。これはNode Aがダウンしていると判断できます。
- node=Node B と stauts=OWNEDを含むデータをディスクに書き出します。
- データを再び読み込みます。
- 自身のノード名と比較します。ノード名が変更されていなければ、Node Bが所有権を獲得します。
- その後、他のリソースも起動します。
複数ノードからの同時のディスクアクセス
この事象はほとんど発生しません。しかしながら、heartbeat通信が切れた状態で同時に複数のノードが起動された場合などに発生します。
Node A / Node B 共有ディスクへの書き込みは最終的にシリアライズされます。書き込みできるエリアは"一つ"であるためです。その結果、最後に書き込まれたノード名が残ります。 この例では、Node Bが残ります。
- データを再び読み込みます。
- Node A:"owner"の値が変更になります。このノードは所有権を獲得できません。Node B:Node Bの名前が"owner"の値になります。Node Bが所有権を取得します。
SFEXを使う場合のcib.xml(サンプル)
<cib admin_epoch="0" epoch="1" have_quorum="false" cib_feature_revision="1.3">
<configuration>
<crm_config>
<cluster_property_set id="set01">
<attributes>
<nvpair id="symmetric-cluster"
name="symmetric-cluster" value="true"/>
<nvpair id="no-quorum-policy"
name="no-quorum-policy" value="ignore"/>
<nvpair id="stonith-enabled"
name="stonith-enabled" value="false"/>
<nvpair id="short-resource-names"
name="short-resource-names" value="true"/>
<nvpair id="is-managed-default"
name="is-managed-default" value="true"/>
<nvpair id="default-resource-stickiness"
name="default-resource-stickiness" value="INFINITY"/>
<nvpair id="stop-orphan-resources"
name="stop-orphan-resources" value="true"/>
<nvpair id="stop-orphan-actions"
name="stop-orphan-actions" value="true"/>
<nvpair id="remove-after-stop"
name="remove-after-stop" value="false"/>
<nvpair id="default-resource-failure-stickiness"
name="default-resource-failure-stickiness" value="-INFINITY"/>
<nvpair id="stonith-action"
name="stonith-action" value="reboot"/>
<nvpair id="default-action-timeout"
name="default-action-timeout" value="120s"/>
<nvpair id="dc-deadtime"
name="dc-deadtime" value="10s"/>
<nvpair id="cluster-recheck-interval"
name="cluster-recheck-interval" value="0"/>
<nvpair id="election-timeout"
name="election-timeout" value="2min"/>
<nvpair id="shutdown-escalation"
name="shutdown-escalation" value="20min"/>
<nvpair id="crmd-integration-timeout"
name="crmd-integration-timeout" value="3min"/>
<nvpair id="crmd-finalization-timeout"
name="crmd-finalization-timeout" value="10min"/>
<nvpair id="cluster-delay"
name="cluster-delay" value="180s"/>
<nvpair id="pe-error-series-max"
name="pe-error-series-max" value="-1"/>
<nvpair id="pe-warn-series-max"
name="pe-warn-series-max" value="-1"/>
<nvpair id="pe-input-series-max"
name="pe-input-series-max" value="-1"/>
<nvpair id="startup-fencing"
name="startup-fencing" value="true"/>
</attributes>
</cluster_property_set>
</crm_config>
<nodes/>
<resources>
<group id="grpPostgreSQLDB">
<primitive id="prmExPostgreSQLDB" class="ocf" type="sfex" provider="heartbeat">
<operations>
<op id="exPostgreSQLDB_start"
name="start" timeout="180s" on_fail="fence"/>
<op id="exPostgreSQLDB_monitor"
name="monitor" interval="10s" timeout="60s" on_fail="fence"/>
<op id="exPostgreSQLDB_stop"
name="stop" timeout="60s" on_fail="fence"/>
</operations>
<instance_attributes id="atrExPostgreSQLDB">
<attributes>
<nvpair id="dskPostgreSQLDB"
name="device" value="/dev/cciss/c1d0p1"/>
<nvpair id="idxPostgreSQLDB"
name="index" value="1"/>
<nvpair id="cltPostgreSQLDB"
name="collision_timeout" value="1"/>
<nvpair id="lctPostgreSQLDB"
name="lock_timeout" value="70"/>
<nvpair id="mntPostgreSQLDB"
name="monitor_interval" value="10"/>
<nvpair id="fckPostgreSQLDB"
name="fsck" value="/sbin/fsck -p /dev/cciss/c1d0p2"/>
<nvpair id="fcmPostgreSQLDB"
name="fsck_mode" value="check"/>
<nvpair id="hltPostgreSQLDB"
name="halt" value="/sbin/halt -f -n -p"/>
</attributes>
</instance_attributes>
</primitive>
<primitive id="prmFsPostgreSQLDB" class="ocf" type="Filesystem" provider="heartbeat">
<operations>
<op id="fsPostgreSQLDB_start"
name="start" timeout="60s" on_fail="fence"/>
<op id="fsPostgreSQLDB_monitor"
name="monitor" interval="10s" timeout="60s" on_fail="fence"/>
<op id="fsPostgreSQLDB_stop"
name="stop" timeout="60s" on_fail="fence"/>
</operations>
<instance_attributes id="atrFsPostgreSQLDB">
<attributes>
<nvpair id="devPostgreSQLDB"
name="device" value="/dev/cciss/c1d0p2"/>
<nvpair id="dirPostgreSQLDB"
name="directory" value="/mnt/shared-disk"/>
<nvpair id="fstPostgreSQLDB"
name="fstype" value="ext3"/>
</attributes>
</instance_attributes>
</primitive>
<primitive id="prmIpPostgreSQLDB" class="ocf" type="IPaddr" provider="heartbeat">
<operations>
<op id="ipPostgreSQLDB_start"
name="start" timeout="60s" on_fail="fence"/>
<op id="ipPostgreSQLDB_monitor"
name="monitor" interval="10s" timeout="60s" on_fail="fence"/>
<op id="ipPostgreSQLDB_stop"
name="stop" timeout="60s" on_fail="fence"/>
</operations>
<instance_attributes id="atrIpPostgreSQLDB">
<attributes>
<!-- chenge ip address attribute -->
<nvpair id="ipPostgreSQLDB" name="ip" value="aaa.bbb.ccc.ddd"/>
<nvpair id="maskPostgreSQLDB" name="netmask" value="nn"/>
<nvpair id="nicPostgreSQLDB" name="nic" value="bond0"/>
</attributes>
</instance_attributes>
</primitive>
<primitive id="prmApPostgreSQLDB" class="ocf" type="pgsql" provider="heartbeat">
<operations>
<op id="apPostgreSQLDB_start"
name="start" timeout="60s" on_fail="fence"/>
<op id="apPostgreSQLDB_monitor"
name="monitor" interval="30s" timeout="60s" on_fail="fence"/>
<op id="apPostgreSQLDB_stop"
name="stop" timeout="60s" on_fail="fence"/>
</operations>
<instance_attributes id="atrApPostgreSQLDB">
<attributes>
<nvpair id="pgctl01"
name="pgctl" value="/usr/local/pgsql/bin/pg_ctl"/>
<nvpair id="psql01"
name="psql" value="/usr/local/pgsql/bin/psql"/>
<nvpair id="pgdata01"
name="pgdata" value="/mnt/shared-disk/pgsql/data"/>
<nvpair id="pgdba01"
name="pgdba" value="postgres"/>
<nvpair id="pgdb01"
name="pgdb" value="template1"/>
<nvpair id="logfile01"
name="logfile" value="/var/log/pgsql.log"/>
</attributes>
</instance_attributes>
</primitive>
</group>
</resources>
<constraints>
<rsc_location id="rlcPostgreSQLDB" rsc="grpPostgreSQLDB">
<rule id="rulPostgreSQLDB_node01" score="200">
<expression id="expPostgreSQLDB_node01"
attribute="#uname" operation="eq" value="sfex01" />
</rule>
<rule id="rulPostgreSQLDB_node02" score="100">
<expression id="expPostgreSQLDB_node02"
attribute="#uname" operation="eq" value="sfex02"/>
</rule>
</rsc_location>
<rsc_location id="ping1:disconn" rsc="grpPostgreSQLDB">
<rule id="ping1:disconn:rule" score="-INFINITY" boolean_op="and">
<expression id="ping1:disconn:expr:defined"
attribute="default_ping_set" operation="defined"/>
<expression id="ping1:disconn:expr:positive"
attribute="default_ping_set" operation="lt" value="100"/>
</rule>
</rsc_location>
</constraints>
</configuration>
<status/>
</cib>
リリース情報
sfex -- バージョン1.3
- リリース日 2008年3月7日
