Recent Changes

2011-05-06
2011-02-22
2011-02-18
2011-02-16
2011-02-15

Latest File Release

[1-01] Pacemakerリポジトリパッケージ (RHEL7) (1.1.19-1.1)2018-12-07 13:00
[1-02] Pacemakerリポジトリパッケージ (RHEL6) (1.1.19-1.1)2018-12-07 13:00
[1-03] Pacemakerリポジトリパッケージ (RHEL5) (1.0.13-2.1)2014-08-13 09:28
[1-10] pm_ctl : 運用管理連携機能 (1.0-1)2012-11-05 11:20
[1-11] pm_logconv-cs : ログメッセージ制御機能(Corosync対応) (1.0-1)2012-11-12 09:53
[2-01] Heartbeat (RedHat/CentOS用rpmパッケージ) (2.1.4-1)2008-08-28 09:53
[2-02] hb-monitor:クラスタ状態表示機能 (1.03-1)2011-02-16 07:21
[2-03] hb-extras:拡張リソースエージェント・プラグイン (1.02-1)2011-02-16 07:21
[2-04] hb-logconv:ログメッセージ制御機能 (1.02-1)2011-02-16 07:21
[2-05] hb-cibgen:cib.xml編集ツール (1.03-1_1)2009-11-16 13:31
[2-06] hb-diskd:ディスク監視デーモン (1.10-1)2010-01-22 10:20
[2-07] VIPcheck:VIPcheckリソースエージェント (1.1)2009-11-30 07:21
[2-08] hb-sfex:共有ディスク排他制御 (1.30-1)2010-01-22 10:00
[2-09] hb-logmoni:ロギングデーモン監視 (2.00-1)2010-01-22 10:10
[2-10] hb-ipv6:IPv6対応追加パッケージ (1.00-1)2010-01-29 07:21
[2-11] hb-vmmonitor:デバイス一括監視機能 (1.00-1)2010-06-11 07:21
[2-12] vm-logd-monitor:ログデーモン監視機能(Domain-0用) (1.00-1)2010-06-11 07:21
[2-13] stonith-wrapper2:STONITHラッパープラグイン2 (2.00)2010-06-18 07:21
[2-14] hb-actmonitor:フェイルオーバ抑止機能 (1.00-1)2010-11-26 07:21

Wiki Guide

Side Bar

共有ディスク排他制御 (hb-sfex)

SFEX(Shared Disk File EXclusiveness Control Program)は、Active-Standbyのクラスタ構成で運用中、Heartbeat通信が切れた場合に両ノードがActiveとなる(スプリットブレイン状態)ことを防ぐために使用します。

このリリースのファイルを表示

インストール方法

本ツールのパッケージ hb-sfex-1.30-1.x86_64.rpm をダウンロードします。その後、以下のようにrpmコマンドを使ってインストールします。

# rpm -ivh hb-sfex-1.30-1.x86_64.rpm
Preparing...                ########################################### [100%]
   1:hb-sfex               ########################################### [100%]

基本的な考え方

  • SFEXは共有ディスクの所有権を制御するリソースです。
  • SFEXは共有ディスク上の特別なパーティションを使い、以下のデータを扱います。
  • "status" 誰かにディスクが所有されているかを示します。
  • "node" ディスクを所有しているノード名を示します。
  • "count" ディスクを所有しているノードが生きているか判断するために使われます。
  • 一般的に、共有ディスク上のデータパーティションを使うリソース(例えば、PostgreSQL)と一緒にリソースグループを作ります。
  • 所有権を持ったノードのリソースのみがデータパーティションにアクセスできます。

sfex0.png

  • いつ、ノードは所有権を獲得できるか?
  • ケース1:誰も所有権を持っていないとき。
  • ケース2:他のノードがダウンしていると判断できるとき。

シーケンス図

起動処理

SFEXはcib.xmlの中で高いスコアが付けられたノードで開始されます。そのため、複数のノードで、同時に共有ディスクにアクセスすることはありません。

Node A

  1. SFEXは共有ディスクからデータを読み、"status"を取得します。通常、共有ディスクはだれにも所有されていないので"status"は"NO_OWNED"となります。
  2. node=Node Aとstatus=OWNEDを含むデータを書き込みます。
  3. 再びデータを読み込み、node="Node A"のデータを取得します。
  4. 自身のノード名と比較します。ノード名が変更されていなければ、Node Aが所有権を獲得します。
  5. SFEXはその後、Heartbeatのモニタ処理によって共有ディスク上の"count"の値をインクリメントします。

この処理は所有権の更新を意味します。

seq1_start.png

Heartbeat通信断

Node A

  1. SFEXはHB更新処理によって所有権を更新します。

Node B

  1. heartbeat通信が失敗したとき、スタンバイノード(Node B)はリソースを起動します。
  2. SFEXは共有ディスク上のデータを読み込みます。
  3. しばらく処理を待ちます。(待ち時間はsfexのモニタ間隔より長くするべきです。この待ち時間により、Node Aによる定期的な更新を待ち、Node Aが所有権を持っていることを確認します。)
  4. 再びデータを読み込みます。
  5. 新しい"count"の値を確認します。二つの"count"の値が異なった場合、Node Aが動作中であると判断できます。
  6. Node Aが動作中であるため、SFEX起動処理は停止します。

seq2_HBdown.png

アクティブノードのダウン

Node A

  1. 故障によってNode Aがダウン

Node B

このNode B起動処理はHB通信断と同じように行われます。

  1. しばらく待ちます。(Node Aの定期的な更新を待つが、Node Aが更新するこを確認できない)
  2. SFEXはデータを再び読みます。
  3. 新旧、二つの"count"の値を比較すると"count"の値が同じになります。これはNode Aがダウンしていると判断できます。
  4. node=Node B と stauts=OWNEDを含むデータをディスクに書き出します。
  5. データを再び読み込みます。
  6. 自身のノード名と比較します。ノード名が変更されていなければ、Node Bが所有権を獲得します。
  7. その後、他のリソースも起動します。

seq3_NodeDown.png

複数ノードからの同時のディスクアクセス

この事象はほとんど発生しません。しかしながら、heartbeat通信が切れた状態で同時に複数のノードが起動された場合などに発生します。

Node A / Node B 共有ディスクへの書き込みは最終的にシリアライズされます。書き込みできるエリアは"一つ"であるためです。その結果、最後に書き込まれたノード名が残ります。 この例では、Node Bが残ります。

  1. データを再び読み込みます。
  2. Node A:"owner"の値が変更になります。このノードは所有権を獲得できません。Node B:Node Bの名前が"owner"の値になります。Node Bが所有権を取得します。

seq4_ST_access.png

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>