サイト内の現在位置を表示しています。

Oracle Cloud Infrastructureで両系活性を防止する方法(Windows/Linux)

CLUSTERPRO オフィシャルブログ ~クラブロ~

  • 2021/10/07 以下を追記。
  • Windows版の構築手順とサンプルスクリプトを追加しました。
  • Linux版のサンプルスクリプトを一部修正しました。

  • 2024/09/13 以下を追記。
  • OS起動時間の調整について記述を追加しました。

はじめに

Oracle Cloud Infrastructure(以降、OCI)において、HAクラスターの両系活性を防止するために、CLUSTERPROの機能の一つである強制停止スクリプトを利用したHAクラスターの構築を試してみました。
CLUSTERPROでは、両系活性を防止する方法として ネットワークパーティション解決(以降、NP解決)が設定可能です。OCI上における推奨構成では、NP解決にHTTP NP解決を設定します。

しかし、NP解決を設定した場合でもOSストール等が起きると両系活性が発生する可能性があります。
CLUSTERPROにはそのような場合に両系活性を防止するための機能として、強制停止スクリプトという機能があります。
今回は、この強制停止スクリプトをOCI上のHAクラスターに設定します。

  • なお、物理環境では、IPMIの機能や、VMware vCenter Serverの機能を利用する「強制停止機能」によって、サーバーを停⽌することができます。OCI環境では同様の機能は使用できないため、強制停止スクリプトによりサーバーの停止を実現します。
【参考】
  • Windows
    > リファレンスガイド
     > 第 6 章 ネットワークパーティション解決リソースの詳細

  • Linux
    > リファレンスガイド
     > 第 6 章 ネットワークパーティション解決リソースの詳細

この記事の内容

1. 強制停止スクリプトとは

強制停止スクリプトとは、サーバーのダウンを認識したときに残りのサーバー(正常なサーバー)でユーザーが作成した任意のスクリプトを実行する機能です。この機能を使用することで、ダウンしたサーバーを強制的に停止させることが可能になります。
これにより、ネットワークパーティション(スプリットブレイン)の状態が発生した場合でも、NP解決リソースによる回復動作に加えて、強制停止スクリプトを利用してサーバーを停止させることで、 両系活性の防止をより確実なものにすることができます。

強制停止スクリプトを実行する契機は、ハートビートタイムアウトによりサーバーのダウンを検出し、ダウンしたサーバーで起動していたフェールオーバーグループを他のサーバーで起動する場合となります。
Cluster WebUIなどからサーバーを正常に停止した場合や、ダウンしたサーバー上でフェールオーバーグループが起動しておらずフェールオーバーが発生しない場合などは、強制停止スクリプトを実行しません。
強制停止スクリプトの詳細については、リファレンスガイドをご参照ください。

【参考】
  • Windows
    > リファレンスガイド
     > 第 7 章 その他の設定情報
      > 7.2 強制停止スクリプト

  • Linux
    > リファレンスガイド
     > 第 7 章 その他の設定情報
      > 7.4 強制停止スクリプト

2. HAクラスター構成

今回は「VIP制御によるHAクラスター」を構築し、強制停止スクリプトを設定します。
強制停止スクリプトでは、OCI CLIを利用してダウンと判断したサーバーをシャットダウンします。
なお、フェールオーバーグループにはOracle Cloud仮想IPリソース、ミラーディスクリソースのみを設定します。

HAクラスターの構成

3. HAクラスターの構築手順

HAクラスターの構築手順をご紹介します。
構築手順は、WindowsとLinuxで異なりますのでご注意ください。

3.1 HAクラスター構築の事前準備

OCI環境におけるHAクラスター構築手順はソフトウェア構築ガイドをご参照ください。

【参考】
  • Windows > クラウド > Oracle Cloud Infrastructure > HAクラスタ構築ガイド
  • Linux > クラウド > Oracle Cloud Infrastructure > HAクラスタ構築ガイド

強制停止スクリプトを使用するためには、OCI CLIのセットアップが必要となります。OCI CLIのセットアップ方法についてはpopupこちらのサイトをご参照ください。

また、今回は強制停止スクリプトでコンピュート・インスタンスを停止するため、強制停止スクリプトから以下のコマンドを実行する必要があります。そのため、OCI CLIのセットアップ後、事前にOS上から以下のコマンドが実行できるか確認してください。

oci.exe compute instance action --action STOP --instance-id <相手サーバの OCID>
oci.exe compute instance get --instance-id <相手サーバの OCID>

なお、Windows版ではOCI CLIをセットアップしたユーザーで強制停止スクリプトを実行する必要があります。そのため、OCI CLIをセットアップしたユーザーを、強制停止スクリプト設定前にCluster WebUIのクラスタプロパティ > アカウントタブにて追加してください。アカウントタブの設定はCLUSTERPRO X 4.2以降で利用可能です。
Linux版ではrootユーザーでOCI CLIが実行できるようにセットアップを実施してください。

【参考】
  • Windows
    > リファレンスガイド
     > 第 2 章 パラメータの詳細
      > 2.2 クラスタプロパティ
       > 2.2.16 アカウントタブ

OCIおよびCLUSTERPROの構成は以下の通りです。

OCIの構成

  • 東京リージョン
  • VCN (CIDR: 10.0.0.0/16)
  • サブネット
  • Public Subnet  10.0.0.0/24
  • Private Subnet 10.0.1.0/24
  • Internet Gateway
  • NAT Gateway
  • コンピュート・インスタンス
  • サーバー1 (現用系サーバー):server1
  • IP構成
  • プライマリIP:10.0.1.101
  • サーバー2 (待機系サーバー):server2
  • IP構成
  • プライマリIP:10.0.1.102

CLUSTERPROの構成(Windows)

  • CLUSTERPRO X 4.2 for Windows (内部バージョン:12.22)
  • Windows Server 2019 (※)
  • フェールオーバーグループ (failover)
  • Oracle Cloud 仮想IPリソース
  • ミラーディスクリソース
  • クラスタパーティション : L:
  • データパーティション : M:

CLUSTERPROの構成(Linux)

  • CLUSTERPRO X 4.2 for Linux (内部バージョン:4.2.2-1)
  • Oracle Linux 7.7 (※)
  • フェールオーバーグループ (failover)
  • Oracle Cloud 仮想IPリソース
  • ミラーディスクリソース
  • クラスタパーティション : /dev/oracleoci/oraclevdb1
  • データパーティション : /dev/oracleoci/oraclevdb2

  • (※)CLUSTERPRO X 4.2にて動作確認が完了しているOSやディストリビューションを利用いただくことが可能です。
【参考】
  • CLUSTERPRO Server
    > CLUSTERPRO X 4.2

  • CLUSTERPRO Server
    > CLUSTERPRO X 4.2
  • 動作確認済みkernel一覧
    > CLUSTERPRO X 4.2

3.2 HAクラスターの構築

構築手順の詳細については、ソフトウェア構築ガイドをご参照ください。

【参考】
  • Windows > クラウド > Oracle Cloud Infrastructure > HAクラスタ構築ガイド
  • Linux > クラウド > Oracle Cloud Infrastructure > HAクラスタ構築ガイド

今回の構成では、OCIのソフトウェア構築ガイドの構成から変更し、Witnessハートビートリソース、HTTP NP解決リソースを削除し、強制停止スクリプトを設定します。
(今回のブログではNICのLink Downで両系活性をあえて発生させるために、Witnessハートビートリソース、 HTTP NP解決リソースを削除しています。実際の環境では削除しないことを推奨いたします。)

強制停止スクリプトは、以下のように設定します。
イメージ図は、Windows環境における例を記載しています。

  • 1.「クラスタのプロパティ」の「拡張」タブにて、「強制停止スクリプトを実行する」をチェックし、「スクリプト設定」をクリックします。

  • 2.「スクリプトの編集」で「編集」をクリックします。

  • 3.起動したテキストエディタで、以下のスクリプトを入力します。
  • 以下のスクリプトや設定ファイルはサンプルであり、動作を保証するものではありません。
  • ★部分の変数の値は環境に合わせて設定してください。
  • スクリプトが正常終了する際に戻り値として0を返却するように記述します。

強制停止スクリプト(Windows)

@echo off
rem ***************************************
rem *            forcestop.bat            *
rem ***************************************

rem OCI CLI PATH
set OCIPath="C:\Users\opc\bin\oci.exe" ★ OCIコマンドパス

rem node1 setting info
set HOST1=server1 ★ サーバー1のホスト名
set INSTANCE_OCID_HOST1=ocid1.instance.oc1.ap-tokyo-1.xxxx ★ サーバー1のINSTANCE OCID
rem node2 setting info
set HOST2=server2 ★ サーバー2のホスト名
set INSTANCE_OCID_HOST2=ocid1.instance.oc1.ap-tokyo-1.xxxx ★ サーバー2のINSTANCE OCID

rem instance exec stop count
set STOP_LOOP_MAX=2

echo "START"
echo "DOWN SERVER NAME : %CLP_SERVER_DOWN%"
echo "LOCAL SERVER NAME: %CLP_SERVER_LOCAL%"

if %CLP_SERVER_DOWN%==%HOST1% (
    set INSTANCE_OCID=%INSTANCE_OCID_HOST1%
) else if %CLP_SERVER_DOWN%==%HOST2% (
    set INSTANCE_OCID=%INSTANCE_OCID_HOST2%
) else (
    echo "SERVER is not found."
    exit 1
)

rem stop instance
set=STOP_LOOP_COUNT=0

:STOP_LOOP

%OCIPath% compute instance action --action STOP --instance-id %INSTANCE_OCID%
set ret=%ERRORLEVEL%

if %ERRORLEVEL%==0 (
    echo "succeeded to stop instance. (%INSTANCE_OCID%)"
    GOTO STOP_CHECK
)

echo "failed to stop instance. (%INSTANCE_OCID%, ret=%ret%)"

timeout /t 1
set /a STOP_LOOP_COUNT=STOP_LOOP_COUNT+1

if %STOP_LOOP_COUNT%==%STOP_LOOP_MAX% (
    echo "stop instance retry over."
    echo "EXIT %ret%"
    exit %ret%
)

GOTO STOP_LOOP


:STOP_CHECK
rem server down check

:CHECK_LOOP

%OCIPath% compute instance get --instance-id %INSTANCE_OCID% | findstr "lifecycle-state" | findstr "STOPPED"
set ret=%ERRORLEVEL%

if %ERRORLEVEL%==0 (
    echo "%INSTANCE_OCID% has been stopped."
    GOTO EXIT
)
timeout /t 1

GOTO CHECK_LOOP

:EXIT
echo "EXIT 0"
exit 0

強制停止スクリプト(Linux)

#! /bin/sh
#***********************************************
#*                forcestop.sh                 *
#***********************************************

OCIPath="/usr/bin/oci" ★OCIコマンドのパス

HOST1="server1" ★サーバー1のホスト名
INSTANCE_OCID_HOST1="ocid1.instance.oc1.ap-tokyo-1.xxxx" ★ サーバー1のINSTANCE OCID

HOST2="server2" ★サーバー2のホスト名
INSTANCE_OCID_HOST2="ocid1.instance.oc1.ap-tokyo-1.xxxx" ★ サーバー2のINSTANCE OCID

STOP_LOOP_MAX=2

if [ "${CLP_SERVER_DOWN}" = "${HOST1}" ]; then
    INSTANCE_OCID="${INSTANCE_OCID_HOST1}"
elif [ "${CLP_SERVER_DOWN}" = "${HOST2}" ]; then
    INSTANCE_OCID="${INSTANCE_OCID_HOST2}"
else
    echo "DOWN SERVER is not found."
    echo "EXIT 1"
    exit 1
fi

# インスタンスの停止要求
STOP_LOOP_COUNT=0

while [ "${STOP_LOOP_COUNT}" -lt "${STOP_LOOP_MAX}" ]
do
    sudo ${OCIPath} compute instance action --action STOP --instance-id ${INSTANCE_OCID}
    ret=$?
    if [ "${ret}" -eq 0 ]; then
        echo "succeeded to stop instance. (${CLP_SERVER_DOWN})"
        break
    fi
    echo "failed to stop instance. (${CLP_SERVER_DOWN}, ret=${ret})"
    sleep 1
    let STOP_LOOP_COUNT=${STOP_LOOP_COUNT}+1
done

if [ "${ret}" -ne 0 ]; then
    echo "stop instance retry over."
    echo "EXIT ${ret}"
    exit ${ret}
fi

# サーバーダウン確認
# サーバーの停止は強制停止スクリプトのタイムアウト時間確認される
# タイムアウト時間超過後は、強制停止スクリプトが失敗と判断される

while [ 0 ]
do
    STATUS=`sudo ${OCIPath} compute instance get --instance-id ${INSTANCE_OCID} | grep lifecycle-state | awk -F\" '{print $4}'`
    if [ $? -ne 0 ]; then
        echo "oci cli command error."
    else
        if [ "${STATUS}" = "STOPPED" ]; then
            echo "${CLP_SERVER_DOWN} has been stopped "
            break
        fi
        sleep 1
    fi
done

echo "EXIT 0"
exit 0

  • 4.「スクリプトの編集」に戻り、「フェイルオーバの抑制」、「タイムアウト」を設定します。

    [実行失敗時にグループのフェイルオーバを抑制する]にチェックを入れ、設定を有効化します。
    こちらの設定を有効化することで、強制停止スクリプトの戻り値を判定します。強制停止スクリプトが失敗した場合は、フェールオーバーが抑制されるため、より確実に両系活性を防止することが可能です。

    また、今回は強制停止スクリプトでダウンしたサーバーの停止完了の待ち合わせを実施するため、タイムアウトを300秒に設定します。

    なお、上記に加え、Windows環境では、「実行ユーザ」に、クラスタプロパティ > アカウントタブにて事前に設定した、OCI CLIを実行可能なユーザーを選択してください。

強制停止スクリプトの設定後に、OSの起動時間を調整します。
強制停止スクリプト実行中に対向サーバーでOS再起動などが実行された場合に、両系活性が発生することや、クラスター起動処理中に強制停止が実行されることを防止します。
別途、OSの起動時間が以下となるように設定します。

OSの起動時間 >= 強制停止スクリプトのタイムアウト + ハートビートタイムアウト + ハートビートインターバル

OS起動時間の調整手順の詳細については、インストール&設定ガイドをご参照ください。

【参考】
  • Windows
    > インストール&設定ガイド
    > 第 2 章 システム構成を決定する
     > 2.6 ハードウェア構成後の設定
      > 2.6.3 OS 起動時間を調整する (必須)

  • Linux
    > インストール&設定ガイド
    > 第 2 章 システム構成を決定する
     > 2.8 ハードウェア構成後の設定
      > 2.8.5 OS 起動時間を調整する (必須)

CLUSTERPRO X 4.3以前のバージョンでは、Windowsの場合のみ、OS起動時間を調整する代わりに互換コマンド(armdelay.exe)を使用してCLUSTERPROサービスの起動を遅延させることで対応が可能です。
CLUSTERPROサービス起動時の遅延時間を以下となるように設定します。

CLUSTERPROサービス起動時の遅延時間 >= 強制停止スクリプトのタイムアウト + ハートビートタイムアウト + ハートビートインターバル

CLUSTERPROサービス起動時の遅延時間の設定手順の詳細については、互換機能ガイドをご参照ください。

【参考】
● 共通 > 互換機能ガイド(Windows)
→第 4 章 互換コマンドリファレンス
→4.24 起動遅延時間を設定/表示する(armdelay コマンド)
また、DISK方式によるNP解決を行う場合や共有ディスクを利用する場合はOS起動時間の計算について、別の観点での考慮が必要です。
詳細については、popup【2024年版】サービス起動遅延時間設定機能の紹介も併せて参照ください。
  • リンク先の記事はCLUSTERPRO X 5.0から追加されたサービス起動遅延時間設定機能について解説していますが、サービス起動遅延時間の考え方とOS起動時間を調整する(遅延させる)考え方は同じものです。
    また、リンク先の記事では強制停止スクリプトではなく、CLUSTERPRO X 5.0から追加された強制停止リソースを利用しています。リンク先の記事の「強制停止リソースの強制停止タイムアウト時間 + 強制停止リソースの停止完了待ち時間」の部分は本記事の「強制停止スクリプトのタイムアウト」と読み替えてください。

4. 動作確認

強制停止スクリプトを実行する構成、また、実行しない構成で、ネットワークパーティション状態を起こして、HAクラスターの動作を確認します。
今回は、Linux環境における動作確認の例を記載します。

ネットワークパーティション状態を起こすため、現用系サーバーでCLUSTERPROの通信に使用しているNICを全てdownさせます。
なお、NICをdownさせることにより、インスタンスへ接続できなくなることが考えられます。
そのため、動作確認を実施する前に、OCIのインスタンス・コンソール接続を使用して、インスタンスに接続できることを確認してください。
インスタンス・コンソール接続についてはpopupこちらのサイトをご参照ください。

4.1 強制停止スクリプトを実行する場合

強制停止スクリプトを実行する場合、待機系サーバーはフェールオーバーグループを起動する前に強制停止スクリプトを実行して現用系サーバーを停止させます。そのため、両系活性を防ぐことができます。

待機系サーバーが現用系サーバーのダウンを検出した後のsyslogの出力は以下のようになります。フェールオーバーグループの起動前に強制停止スクリプトを実行していることが確認できます。

Jul 22 02:52:35 server2 clusterpro: [I] Server server1 has been stopped. ★ 現用系サーバーのダウンを検出
Jul 22 02:52:36 server2 clusterpro: [I] Script for forced stop has started. ★ 強制停止スクリプトを実行開始
Jul 22 02:52:59 server2 clusterpro: [I] Script for forced stop has completed. ★ 強制停止スクリプトの実行完了
Jul 22 02:52:59 server2 clusterpro: [I] Failover group failover has started. ★ フェールオーバーグループの起動を開始
Jul 22 02:52:59 server2 clusterpro: [I] Activating group failover has started.
Jul 22 02:52:59 server2 clusterpro: [I] Activating exec resource has started.

フェールオーバー完了後、現用系サーバーのステータスを確認するとstoppedとなっており、現用系サーバーが停止していることを確認できます。

[root@server2 ~]# oci compute instance get --instance-id ocid1.instance.oc1.ap-tokyo-1.xxxxx | grep lifecycle-state | awk -F\" '{print $4}'
STOPPED

4.2 (参考)強制停止スクリプトを実行しない場合

強制停止スクリプトを実行しない場合、待機系サーバーでフェールオーバーグループが起動されます。
その後、現用系サーバーにて、上述のNICをupした際に、現用系サーバーはフェールオーバーグループを起動している状態でクラスターに復帰するため、両系活性状態となります。
その後、syslogに以下のように出力され、両サーバーがシャットダウンします。

Jul 22 07:51:24 server1 clusterpro: [E] Group failover has started on more than one server.
Jul 22 07:51:24 server1 clusterpro: [I] Since server server2 is not specified as that which suppresses shutdown at both-system activation detection, it executed the shutdown request.
Jul 22 07:51:24 server1 clusterpro: [I] Since server server1 is not specified as that which suppresses shutdown at both-system activation detection, it executed the shutdown request.

さいごに

今回は強制停止スクリプトを利用したHAクラスターの構築手順をご紹介しました。

OCI上でネットワークパーティション発生時に両系活性をより確実に防止することができますので、強制停止スクリプトの利用をご検討ください。

お問い合わせ

本記事に関するお問い合わせは、popupお問い合わせ窓口までお問い合わせください。
  • 本記事で紹介しているスクリプトの内容についてのお問い合わせ、および、お客様環境に合わせたカスタマイズにつきましてはCLUSTERPRO導入支援サービスにて承っておりますので、上記窓口の"ご購入前のお問い合わせ"フォームまでお問い合わせください。