This site best when viewed with a modern standards-compliant browser. We recommend Firefox Get Firefox!.

Linux-HA project logo
Providing Open Source High-Availability Software for Linux and other OSes since 1999.

USA Flag UK Flag

Japanese Flag

ホームページ

サイトについて

コンタクト情報

使用条件

協力方法

セキュリティ

This web page is no longer maintained. Information presented here exists only to avoid breaking historical links.
The Project stays maintained, and lives on: see the Linux-HA Reference Documentation.
To get rid of this notice, you may want to browse the old wiki instead.

2010.1.28
追加パッケージ集リニューアル
追加パッケージ集は、こちらから

2008.8.28
RHEL用rpm更新
更新情報はこちらから

2008.8.18
Heartbeat 2.1.4
リリース!
Downloadはこちらから

2007.11.13
Linux-ha-japan日本語ML移植しました

2007.10.5
日本語サイトOPEN
日本語MLも開設しました

2007.10.5
OSC2007 Tokyo/Fall で Heartbeat紹介
発表資料を公開しました

Last site update:
2017-12-11 11:50:32

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

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

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

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起動処理は停止します。

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

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. その後、他のリソースも起動します。

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

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

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

  1. データを再び読み込みます。
  2. 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>

リリース情報

関連情報

Heartbeat用 追加パッケージ集 (contrib)