サンプルのアプリケーションは、DNS リソース (in.named) の信頼性を監視する、基本的な障害モニターを実装します。障害モニターは、次の要素から構成されます。
dns_probe - nslookup(1M) を使用し、サンプルのデータサービスの制御下にある DNS リソースが動作しているかどうかを確認するユーザー定義プログラム。DNS が動作していない場合、このメソッドは DNS をローカルで再起動しようとします。あるいは、再起動の再試行回数によっては、RGM がデータサービスを別のノードに再配置することを要求します。
dns_monitor_start - dns_probe を起動するコールバックメソッド。監視が有効である場合、RGM は、サンプルのデータサービスがオンラインになった後、自動的に dns_monitor_start を呼び出します。
dns_monitor_stop - dns_probe を停止するコールバックメソッド。RGM は、サンプルのデータサービスがオフラインになる前に、自動的に dns_monitor_stop を呼び出します。
dns_monitor_check - PROBE プログラムがデータサービスを新しいノードにフェイルオーバーするとき、VALIDATE メソッドを呼び出し、構成ディレクトリが利用可能であるかどうかを確認するコールバックメソッド。
dns_probe プログラムは、サンプルのデータサービスの管理下にある DNS リソースが動作しているかどうかを確認する、連続して動作するプロセスを実行します。dns_probe は、サンプルのデータサービスがオンラインになった後、RGM によって自動的に呼び出される dns_monitor_start メソッドによって起動されます。データサービスは、サンプルのデータサービスがオフラインになる前、RGM によって呼び出される dns_monitor_stop メソッドによって停止されます。
この節では、サンプルのアプリケーションの PROBE メソッドの重要な部分だけを説明します。parse_args 関数や syslog 機能番号を取得する方法など、すべてのコールバックメソッドに共通な機能については説明しません。このような機能については、「すべてのメソッドに共通な機能の提供」 を参照してください。
PROBE メソッドの完全なリストについては、「PROBE プログラムのコードリスト」 を参照してください。
検証プログラムは無限ループで動作します。検証プログラムは、nslookup(1M) を使用し、適切な DNS リソースが動作しているかどうかを確認します。DNS が動作している場合、検証プログラムは一定の期間 (Thorough_probe_interval システム定義プロパティに設定されている期間) だけ休眠し、その後、再び検証を行います。DNS が動作していない場合、検証プログラムは DNS をローカルで再起動しようとするか、再起動の再試行回数によっては、RGM がデータサービスを別のノードに再配置することを要求します。
Thorough_probe_interval - 検証プログラムが休眠する期間を設定します。
Probe_timeout - nslookup コマンドが検証を行う期間 (タイムアウト値) を設定します。
Network_resources_used - DNS が動作するサーバーを設定します。
Retry_count と Retry_interval - 再起動を行う回数と期間を設定します。
Rt_basedir - PROBE プログラムと gettime ユーティリティーが格納されているディレクトリを設定します。
scha_resource_get コマンドは、次に示すように、上記プロパティの値を取得し、シェル変数に格納します。
PROBE_INTERVAL=`scha_resource_get -O THOROUGH_PROBE_INTERVAL ¥ -R $RESOURCE_NAME -G $RESOURCEGROUP_NAM� probe_timeout_info=`scha_resource_get -O Extension -R $RESOURCE_NAME ¥ -G $RESOURCEGROUP_NAME Probe_timeout` PROBE_TIMEOUT=`echo $probe_timeout_info | awk '{print $2}'` DNS_HOST=`scha_resource_get -O NETWORK_RESOURCES_USED -R $RESOURCE_NAME ¥ -G $RESOURCEGROUP_NAM� RETRY_COUNT=`scha_resource_get -O RETRY_COUNT -R $RESOURCE_NAME -G¥ $RESOURCEGROUP_NAM� RETRY_INTERVAL=`scha_resource_get -O RETRY_INTERVAL -R $RESOURCE_NAME -G¥ $RESOURCEGROUP_NAM� RT_BASEDIR=`scha_resource_get -O RT_BASEDIR -R $RESOURCE_NAME -G¥ $RESOURCEGROUP_NAM�
システム定義プロパティ (Thorough_probe_intervalなど) の場合、scha_resource_get は値だけを戻します。拡張プロパティ (Probe_timeout など) の場合、scha_resource_get はタイプと値を戻します。値だけを取得するには awk(1) コマンドを使用します。
検証プログラム自身は、nslookup(1M) コマンドの while による無限ループです。while ループの前に、nslookup の応答を保管する一時ファイルを設定します。probefail 変数と retries 変数は 0 に初期化されます。
# nslookup 応答用の一時ファイルを設定する。 DNSPROBEFILE=/tmp/.$RESOURCE_NAME.probe probefail=0 retries=0 |
検証プログラム用の休眠期間を設定する。
hatimerun(1M) を使用し、nslookup に Probe_timeout の値とターゲットホストを渡して起動する。
nslookup の戻りコード (成功または失敗) に基づいて、probefail 変数を設定する。
probefail が 1 (失敗) に設定された場合、nslookup への応答がサンプルのデータサービスから来ており、他の DNS サーバーから来ているのではないことを確認する。
次に、while ループコードを示します。
while : do # 検証が動作すべき期間は THOROUGH_PROBE_INTERVAL プロパティに指 # 定されている。したがって、THOROUGH_PROBE_INTERVAL の間、検証 # プログラムが休眠するように設定する。 sleep $PROBE_INTERVAL # DNS がサービスを提供している IP アドレス上で nslookup コマンド # を実行する。 hatimerun -t $PROBE_TIMEOUT /usr/sbin/nslookup $DNS_HOST $DNS_HOST ¥ > $DNSPROBEFILE 2>&1 retcode=$? if [ $retcode -ne 0 ]; then probefail=1 fi # nslookup への応答が HA-DNS サーバーから来ており、 # /etc/resolv.conf ファイル内に指定されている他のネームサーバー # から来ていないことを確認する。 if [ $probefail -eq 0 ]; then # nslookup 照会に応答したサーバーの名前を取得する。 SERVER=` awk ' $1=="Server:" { print $2 }' ¥ $DNSPROBEFILE | awk -F. ' { print $1 } ' ` if [ -z "$SERVER" ]; then probefail=1 else if [ $SERVER != $DNS_HOST ]; then probefail=1 fi fi fi |
probefail 変数が 0 (成功) 以外である場合、nslookup コマンドがタイムアウトしたか、あるいは、サンプルのサービスの DNS 以外のサーバーから応答が来ていることを示します。どちらの場合でも、DNS サーバーは期待どおりに機能していないので、障害モニターは decide_restart_or_failover 関数を呼び出し、データサービスをローカルで起動するか、RGM がデータサービスを別のノードに再配置することを要求するかを決定します。probefail 変数が 0 の場合、検証が成功したことを示すメッセージが生成されます。
if [ $probefail -ne 0 ]; then decide_restart_or_failover else logger -p ${SYSLOG_FACILITY}.err¥ -t [$SYSLOG_TAG]¥ "${ARGV0} Probe for resource HA-DNS successful" fi |
decide_restart_or_failover 関数は、再試行最大期間 (Retry_interval) と再試行最大回数 (Retry_count) を使用し、DNS をローカルで再起動するか、RGM がデータサービスを別のノードに再配置することを要求するかを決定します。この関数は、次のような条件付きコードを実装します (コードリストについては、「PROBE プログラムのコードリスト」にある decide_restart_or_failover を参照してください)。
最初の障害である場合、データサービスをローカルで再起動します。エラーメッセージを記録し、retries 変数の再試行カウンタをインクリメントします。
最初の障害ではなく、再試行時間が再試行最大期間を過ぎている場合、データサービスをローカルで再起動します。エラーメッセージを記録し、再試行カウンタをリセットし、再試行時間をリセットします。
再試行時間が再試行最大期間を過ぎておらず、再試行カウンタが再試行最大回数を超えている場合、別のノードにフェイルオーバーします。フェイルオーバーが失敗すると、エラーメッセージを記録し、検証プログラムを状態 1 (失敗) で終了します。
再試行時間が再試行最大期間を過ぎておらず、再試行カウンタが再試行最大回数を超えていない場合、データサービスをローカルで再起動します。エラーメッセージを記録し、retries 変数の再試行カウンタをインクリメントします。
期限 (再試行最大期間) 内に再起動の回数 (再試行カウンタ) が制限 (再試行最大回数) に到達した場合、この関数は、RGM がデータサービスを別のノードに再配置することを要求します。再起動の回数が制限に到達していない場合、あるいは、再試行最大期間を過ぎていて、再試行カウンタをリセットする場合、この関数は DNS を同じノード上で再起動しようとします。この関数については、次の点に注意してください。
gettime ユーティリティーを使用すると、再起動間の時間を追跡できます。このユーティリティーは C プログラムで、(Rt_basedir) ディレクトリ内にあります。
Retry_count と Retry_interval のシステム定義リソースプロパティは、再起動を行う回数と期間を決定します。RTR ファイルのデフォルト値は、Retry_count が 2 回、Retry_interval が 5 分 (300 秒) です。クラスタ管理者はこのデフォルトを変更できます。
restart_service 関数は、同じノード上でデータサービスの再起動を試行する場合に呼び出されます。「データサービスの再起動」を参照してください。
API コマンド scha_control は、GIVEOVER オプションを指定すると、サンプルデータサービスを含むリソースグループをオフラインにし、別のノード上でオンラインにし直します。
restart_service 関数は、decide_restart_or_failover によって呼び出され、同じノード上でデータサービスの再起動を試行します。この関数は次の作業を行います。
データサービスが PMF 下にまだ登録されているかどうかを調べます。サービスが登録されている場合、この関数は次の作業を行います。
データサービスの STOP メソッド名と Stop_timeout 値を取得します。
hatimerun を使用してデータサービスの STOP メソッドを起動し、Stop_timeout 値を渡します。
(データサービスが正常に停止した場合) データサービスの START メソッド名と Start_timeout 値を取得します。
hatimerun を使用してデータサービスの START メソッドを起動し、Start_timeout 値を渡します。
データサービスが PMF 下に登録されていない場合は、データサービスが PMF 下で許可されている再試行最大回数を超えていることを示しています。したがって、GIVEOVER オプションを指定して scha_control 関数を呼び出し、データサービスを別のノードにフェイルオーバーします。
function restart_service { # データサービスを再起動するには、まず、データサービス自身が # PMF 下に登録されているかどうかを確認する。 pmfadm -q $PMF_TAG if [[ $? -eq 0 ]]; then # データサービスの TAG が PMF 下に登録されている場合、データサービスを # 停止し、起動し直す。 # 当該リソースの STOP メソッド名と STOP_TIMEOUT 値を取得する。 STOP_TIMEOUT=`scha_resource_get -O STOP_TIMEOUT ¥ -R $RESOURCE_NAME -G $RESOURCEGROUP_NAM� STOP_METHOD=`scha_resource_get -O STOP ¥ -R $RESOURCE_NAME -G $RESOURCEGROUP_NAM� hatimerun -t $STOP_TIMEOUT $RT_BASEDIR/$STOP_METHOD ¥ -R $RESOURCE_NAME -G $RESOURCEGROUP_NAME ¥ -T $RESOURCETYPE_NAME if [[ $? -ne 0 ]]; then logger-p ${SYSLOG_FACILITY}.err -t [$SYSLOG_TAG] ¥ "${ARGV0} Stop method failed." return 1 fi # 当該リソースの START メソッド名と START_TIMEOUT 値を取得する。 # this resource. START_TIMEOUT=`scha_resource_get -O START_TIMEOUT ¥ -R $RESOURCE_NAME -G $RESOURCEGROUP_NAM� START_METHOD=`scha_resource_get -O START ¥ -R $RESOURCE_NAME -G $RESOURCEGROUP_NAM� hatimerun -t $START_TIMEOUT $RT_BASEDIR/$START_METHOD ¥ -R $RESOURCE_NAME -G $RESOURCEGROUP_NAME ¥ -T $RESOURCETYPE_NAME if [[ $? -ne 0 ]]; then logger-p ${SYSLOG_FACILITY}.err -t [$SYSLOG_TAG] ¥ "${ARGV0} Start method failed." return 1 fi else # データサービスの TAG が PMF 下に登録されていない場合、 # データサービスが PMF 下で許可されている再試行最大回数を # 超えていることを示す。 したがって、データサービスを再起動 # してはならない。代わりに、同じクラスタ内にある別のノード # へのフェイルオーバーを試みる。 scha_control -O GIVEOVER -G $RESOURCEGROUP_NAME ¥ -R $RESOURCE_NAME fi return 0 } |
ローカルでの再起動が失敗したり、別のノードへのフェイルオーバーが失敗したりすると、サンプルのデータサービスの PROBE プログラムは失敗で終了し、"Failover attempt failed (フェイルオーバーは失敗しました)" というエラーメッセージを記録します。Failover attempt failed (フェイルオーバーは失敗しました)" というエラーメッセージを記録します。
サンプルのデータサービスがオンラインになった後、RGM は MONITOR_START メソッドを呼び出し、dns_probe メソッドを起動します。
この節では、サンプルアプリケーションの MONITOR_START メソッドの重要な部分だけを説明します。parse_args 関数や syslog 機能番号を取得する方法など、すべてのコールバックメソッドに共通な機能については説明しません。このような機能については、「すべてのメソッドに共通な機能の提供」を参照してください。
MONITOR_START メソッドの完全なリストについては、「MONITOR_START メソッドのコードリスト」 を参照してください。
このメソッドは、プロセス監視機能 (pmfadm) を使用して検証プログラムを起動します。
MONITOR_START メソッドは、Rt_basedir プロパティの値を取得し、PROBE プログラムへの完全パス名を構築します。このメソッドは、pmfadm の無限再試行オプション (-n -1, -t -1) を使用して検証プログラムを起動します。つまり、検証プログラムの起動に失敗しても、PMF メソッドは検証プログラムを無限に再起動します。
# リソースの RT_BASEDIR プロパティを取得することによって、検証プログラ # ムが存在する場所を見つける。 RT_BASEDIR=`scha_resource_get -O RT_BASEDIR -R $RESOURCE_NAME -G ¥ $RESOURCEGROUP_NAM� # PMF の制御下でデータサービスの検証を開始する。無限再試行オプショ # ンを使用して検証プログラムを起動する。リソースの名前、タイプ、 # グループを検証プログラムに渡す。 pmfadm -c $RESOURCE_NAME.monitor -n -1 -t -1 ¥ $RT_BASEDIR/dns_probe -R $RESOURCE_NAME -G $RESOURCEGROUP_NAME ¥ -T $RESOURCETYPE_NAME |
サンプルのデータサービスがオフラインになるとき、RGM は MONITOR_STOP メソッドを呼び出し、dns_probe の実行を停止します。
この節では、サンプルアプリケーションの MONITOR_STOP メソッドの重要な部分だけを説明します。parse_args 関数や syslog 機能番号を取得する方法など、すべてのコールバックメソッドに共通な機能については説明しません。このような機能については、「すべてのメソッドに共通な機能の提供」を参照してください。
MONITOR_STOP メソッドの完全なリストについては、「MONITOR_STOP メソッドのコードリスト」 を参照してください。
このメソッドは、プロセス監視機能 (pmfadm) を使用して検証プログラムが動作しているかどうかを判断し、動作している場合は検証プログラムを停止します。
MONITOR_STOP メソッドは、pmfadm -q を使用して検証プログラムが動作しているかどうかを判断し、動作している場合は pmfadm -s を使用して検証プログラムを停止します。検証プログラムがすでに停止している場合でも、このメソッドは成功で終了します。これによって、メソッドが呼び出し回数に依存しないことが保証されます。
# 検証プログラムが動作しているかどうかを判断し、動作している場合、 # 検証プログラムを停止する。 if pmfadm -q $PMF_TAG; then pmfadm -s $PMF_TAG KILL if [ $? -ne 0 ]; then logger -p ${SYSLOG_FACILITY}.err ¥ -t [$SYSLOG_TAG] ¥ "${ARGV0} Could not stop monitor for resource " ¥ $RESOURCE_NAME exit 1 else #検証プログラムの停止に成功。メッセージを記録する。 logger -p ${SYSLOG_FACILITY}.err ¥ -t [$SYSLOG_TAG] ¥ "${ARGV0} Monitor for resource " $RESOURCE_NAME ¥ " successfully stopped" fi fi exit 0 |
検証プログラムを停止するときは、必ず、pmfadm で KILL シグナルを使用するようにしてください。絶対に、マスク可能なシグナル (TERM など) は使用しないでください。そうしないと、MONITOR_STOP メソッドが無限にハングし、結果としてタイムアウトする可能性があります。この問題の原因は、PROBE メソッドがデータサービスを再起動またはフェイルオーバーする必要があるときに、scha_control を呼び出すところにあります。scha_control がデータサービスをオフラインにするプロセスの一部として MONITOR_STOP メソッドを呼び出したときに、MONITOR_STOP メソッドがマスク可能なシグナルを使用していると、MONITOR_STOP メソッドは scha_control が終了するのを待ち、scha_control は MONITOR_STOP メソッドが終了するのを待つため、結果として両方がハングします。
PROBE メソッドを停止できない場合、MONITOR_STOP メソッドはエラーメッセージを記録します。RGM は、主ノード上でサンプルのデータサービスを MONITOR_FAILED 状態にするため、そのノードに障害が発生することがあります。
MONITOR_STOP メソッドは、検証プログラムが停止するまで終了してはなりません。
PROBE メソッドが、データサービスを含むリソースグループを新しいノードにフェイルオーバーしようとするとき、RGM は MONITOR_CHECK メソッドを呼び出します。
この節では、サンプルアプリケーションの MONITOR_CHECK メソッドの重要な部分だけを説明します。parse_args 関数や syslog 機能番号を取得する方法など、すべてのコールバックメソッドに共通な機能については説明しません。このような機能については、「すべてのメソッドに共通な機能の提供」を参照してください。
MONITOR_CHECK メソッドの完全なリストについては、「MONITOR_CHECK メソッドのコードリスト」を参照してください。
MONITOR_CHECK メソッドは VALIDATE メソッドを呼び出し、新しいノード上で DNS 構成ディレクトリが利用可能かどうかを確認します。Confdir拡張プロパティが DNS 構成ディレクトリを指します。したがって、MONITOR_CHECK は VALIDATE メソッドのパスと名前、および Confdir の値を取得します。MONITOR_CHECK は、次のように、この値を VALIDATE に渡します。
# リソースタイプの RT_BASEDIR プロパティから VALIDATE メソッドの # 完全パスを取得する。 RT_BASEDIR=`scha_resource_get -O RT_BASEDIR -R $RESOURCE_NAME ¥ -G $RESOURCEGROUP_NAM� # 当該リソースの VALIDATE メソッド名を取得する。 VALIDATE_METHOD=`scha_resource_get -O VALIDATE ¥ -R $RESOURCE_NAME -G $RESOURCEGROUP_NAM� # データサービスを起動するための Confdir プロパティの値を取得する。入力された # リソース名とリソースグループを使用し、リソースを追加するときに設定した # Confdir の値を取得する。 config_info=`scha_resource_get -O Extension -R $RESOURCE_NAME -G $RESOURCEGROUP_NAME Confdir` # scha_resource_get は、Confdir 拡張プロパティの値とともにタイプも戻す。 # awk を使用し、Confdir 拡張プロパティの値だけを取得する。 CONFIG_DIR=`echo $config_info | awk `{print $2}'` # VALIDATE メソッドを呼び出し、データサービスを新しいノードにフェイルオーバー # できるかどうかを確認する。 $RT_BASEDIR/$VALIDATE_METHOD -R $RESOURCE_NAME -G $RESOURCEGROUP_NAME ¥ -T $RESOURCETYPE_NAME -x Confdir=$CONFIG_DIR |
ノードがデータサービスのホストとして最適であるかどうかをサンプルアプリケーションが確認する方法については、「VALIDATE メソッド」を参照してください。