フラッピング状態の検知とハンドリング


序文

Nagiosはオプションでホストとサービスの"フラッピング"を検知する機能があります。フラッピングはホストやサービスの状態が頻繁に変化し、障害と復旧の通知の嵐になったときに発生します。フラッピングは設定の問題(しきい値が低すぎるとか)もしくは実際のネットワーク障害を示すことができます。

説明に移る前に、フラッピング検知機能を実装するのは困難だったと言わざるを得ません。その理由の1つにどのようにしてホストやサービスの状態変化が"とても頻繁"であると決めればいいかということがあげられます。フラップ検知の最初に実装を始める際に、どのようにフラッピングを検知できる/すべきかいくつかの情報を見つけようとしました。何も情報が見つからなかったので、私は合理的な解決方法と思えるやり方で実装を行いました。Nagiosがサービスやホストのステートがフラッピングを検知するその方法についてこれから説明します・・・。

サービスフラップ検知

サービスチェックの結果がハードステートもしくはソフト復旧ステートになる場合はいつでも、Nagiosはそのサービスがフラッピングを始めた、またはフラッピングが止まったかどうかチェックします。これは過去21回分のチェック結果を配列に入れソートします。その配列のより古いチェック結果はより最近のチェック結果により上書きされます。

過去のステート履歴配列の中身は過去21回のサービスチェックの間のステート変化のパーセンテージの合計を調査します(古い結果から新しい結果順で)。 配列内のアーカイブされたステートが今アーカイブされたステートと異なる場合ステートの変化が発生します。配列内に過去21個のサービスチェックの結果が保存されているので、配列内には20個のステート変化が入る可能性があります。

下の図1ではサービスチェックの年代順のはい順を示しています。 OKステートは緑、WARNINGステートは黄色、CRITICALステートは赤で、UNKNOWNステートはオレンジです。青い矢印はステートチェンジが発生した時間を示しています。

図1.
Service State Transitions

ステータスが滅多に変わらないサービスは頻繁にステートチェンジが発生するサービスに比べて合計パーセンテージは低いでしょう。フラッピングは頻繁なステートチェンジに関係しているので、サービスがフラッピングしているかどうか判断するために一定の期間(この例では過去21回のサービスチェック)内でのステート変化の総量を計算しています。しかしながら十分に良い方法ではないでしょうが・・・

より最近のステート変化は過去のステート変化よりもより重要であることは自明の理ですので、実際にはある種の曲線を使ってそのサービスのステート変化率を再計算してやる必要があります・・・。単純な構造にするため、ステート変化率の計算には時間とウエイトの関係を線形にすることにしました。図2で特定のサービスのステート変化率を計算する際に古いステート変化より最近のステート変化のウエイトをどのように与えているかを示しています。もし実際にどうやってウエイトを計算しているかを実際に見たい場合は、base/flapping.cのソースコードを読んでください・・・。

図 2.
Weighted Service State Transitions

では、簡単にどの様にフラッピング検知を行っているかの例を見ていきます。上の図1ではあるサービスのサービスチェック結果の履歴を示しています。左から古い順で右になるほどより最近の結果を示しています。以下の例では合計7回のステート変化(t3, t4, t5, t9, t12, t16, t19)が見られます。時間によるウエイトを与えない状態では、合計ステート変化率は35%(20回ぐらいのステート変化中7回変化)になります。個々のステート変化に変化した時間をベースにしたウエイトが加えられると、そのサービスのステート変化率は35%より低くなります。これはステート変化が最近頻繁に発生しているためそうなります。発生時間によるウエイトを加えた状態でのステート変化率は31%であると言えるでしょう。

そうすると、31%のステート変化がどんな重要性があるでしょう? そうですね、もしそのサービスが過去31%フラッピングしていないかもしくは、サービス定義の high_service_flap_thresholdオプションで指定した値より同等あるいはそれ以上の場合、Nagiosはそのサービスがフラッピングし始めたと考えます。もしそのサービスが過去にフラッピングしており、31%という値がサービス定義のlow_service_flap_thresholdオプションの値より以下か同等である場合、Nagiosはそのサービスがフラッピング停止と考えます。この2つの条件いずれもマッチしない場合、そのサービスは現在もフラッピングしているか、フラッピングしていないかのいずれかなので、Nagiosは何もしません・・・。

ホストフラップ検知

ホストフラップ検知は1つの重要な違いを除いてサービスフラップ検知と同じような感じで働きます:その重要な違いとは、Nagiosはそのホストがチェックされる時、そしてそのホストに属しているサービスがチェックされる時のいずれもホストがフラッピングしているかどうかチェックを試みることです。なぜそうなっているのか? それはサービスに関しては連続したフラップ検知ルーチンの間の最小時間間隔というのはサービスチェック間隔と同等なので知ることができます。一方でホストに関しては通常の方法で監視が行われない - ホストは必要な時にのみチェックされる - ため、チェック間隔を取得できません。ホストについては、そのホストが最後にフラップチェックされてからステート変化が起こった場合、もしくはステートは変化していないが、フラップチェック以来、少なくともx時間フラップ検知をパスした場合にフラッピングのチェックが行われます。この方法は、ホストにフラップ検知をどれぐらいの頻度で実行するか決定するということの、私が見つけだすことができた最良の方法です...

単純にサービスを持って、Nagiosはフラップ検知ロジックのため過去21個のホストチェックの結果を配列に蓄えます。ステート変化は発生時間に基づいてウエイトが与えられ、ステート変化率はサービスフラップ検知のロジックと同じやり方で計算されます。

もしホストが以前よりフラッピングしていないか、ステート変化率がhigh_host_flap_thresholdオプションで指定した値に同等かそれ以上の場合、Nagiosはそのホストがフラッピングし始めたと考えます。もし、そのホストが以前よりフラッピングしているか、ステート変化率が low_host_flap_thresholdオプションで指定した値よりも低いか同等の場合、Nagiosはそのホストがフラッピング停止したと考えます。それら2つの条件にマッチしない場合は、そのホストが現在もフラッピングしているか、していないかのどちらかなので、Nagiosはなにもしません・・・

ホストおよびサービス特有のフラップ検知しきい値

テンプレートオブジェクト定義を使用しているなら、個々のホストやサービス定義のlow_flap_thresholdhigh_flap_thresholdオプションを追加することで、ホストおよびサービス特有のフラップ検知しきい値を設定することが出来ます。もしこれらのディレクティブを設定していない場合は、ホストやサービスフラップ検知のしきい値はグローバルなものが使用されます。

同様に、それぞれのオブジェクト定義でenable_flap_detectionを使用することで個々のホストやサービスに対してフラップ検知を有効にしたり/無効にしたり出来ます。ただし特定のサービスやホストのフラップ検知を有効にするためには、プログラムワイドでフラップ検知を有効にしていなくてはなりません(メイン設定ファイルのenable_flap_detectionディレクティブを使用します)。

フラップのハンドリング

サービスやホストのフラッピングを最初に検知した時、Nagiosは次の3つを行います:

  1. そのサービスやホストがフラッピングしたことをログに書き出します。
  2. そのサービスやホストがフラッピングしたことを保存されないコメントに追加します。
  3. そのサービスやホストの通知を回避します(これが通知ロジックの最初のフィルタです)。

サービスやホストがフラッピングを停止した際、Nagiosは以下のことを行います:

  1. そのサービスやホストがフラッピングを停止したことをログに書き出します。
  2. フラッピングが始まったときに記録したコメントを消去します。
  3. そのサービスやホストの通知を回避するフィルタを除去します(通常の通知ロジックで通知が働きます)。