サービスチェックの並列化


序文

Nagiosの機能の一つにサービスチェックを並列で行う能力があります。このドキュメントではそれが何を意味するのか、定義したサービスにどうのような影響があるのかを詳細に説明するつもりです。

並列化の動作の仕組み

並列サービスチェックの動作を説明する前に、まずNagiosがどのようにイベントをスケジュールするのか少し理解しなければなりません。Nagiosの全ての内部イベント(すなわちログファイルローテーション,外部コマンドチェック、サービスチェックなど)はイベントキューに配置されています。イベントキューにあるそれぞれのアイテムには実行される予定の時間があります。Nagiosが他のことをするのに忙しくて予定が遅れることはありますが、Nagiosは全てのイベントが実行されるべき時に実行されるよう最善をつくします。

サービスチェックはイベントの一種で、Nagiosのイベントキューでスケジュールされます。サービスチェックが実行予定の時間になると、Nagiosは別のプロセスを追い出し(fork()システムコールを使って)、サービスチェックを実行します(ある種のプラグイン)。しかし、Nagiosはサービスチェックが終わるのを待ちません!代わりにNagiosはイベントキューにある他のイベントを扱うためにすぐに戻ります。

サービスチェックが終わると何がおきるの?えーと、Nagiosによって開始されたサービスチェックのプロセスがNagiosにサービスチェックの結果を含むメッセージを送り返します。その後機会のある時にチェックしたりサービスチェックの結果を調査するのはnagiosしだいです。

Nagiosが実際になんらかの監視をする順に、実行が終わったサービスチェックの結果を調査します。これはサービスチェック”リーパー”プロセス経由で行われます。サービス”リーパー”はNagiosのイベントキューでスケジュールされる別の種類のイベントです。これら”リーパー”イベントの頻度はメイン設定ファイルのservice_reaper_frequency オプションで決定されます。”リーパー”イベントが実行されると、実行終了済みのサービスチェックの結果を含むメッセージをチェックします。この後、これらのサービスチェックの結果はコアサービス監視ロジックで扱われます。これらによりNagiosはホストをチェックするか、通知を送信するかなどを決定します。サービスチェックの結果を調査すると、Nagiosはサービスの次のチェックを再スケジュールし、後の実行のためにイベントキューに置きます。これでサービスチェック/監視のサイクルは完結です!

本当に知りたいがソースを眺めたことがない人のために、NagiosはNagiosと実際にサービスチェックを行うプロセスとの間のやりとりを扱うためにメッセージキューを使っています。

潜在的な欠点

サービスチェックを並列化させることの潜在的な欠点を認識してください。一つ以上のサービスチェックが同時に実行されるので、互いに衝突するかもしれません。実行しているサービスチェックの種類を評価し、不適切な結果から守る特有の手順を踏まなければなりません。これはモデムのようなハードウェアにアクセスするサービスチェックが一つ以上ある場合、特に重要です。また、ある情報をチェックするためにリモートホストのデーモンに接続するサービスチェックが二つ以上ある場合、そのデーモンが複数の同時接続を扱えるのか確認してください。

幸いなことに、ある種のサービスチェックの衝突問題から守るために出来ることがいくつかあります。

  1. サービスチェックの衝突を避けるために出来る最も簡単なことは、service_interleave_factor 変数を使うことです。インターリービングサービスによってサービスチェックによってリモートホストから押し付けられた負荷を減らすことが出来ます。”スマート”インターリーブ要因計算を使うよう変数を設定し、必要なら手動で調整してください。
  2. 出来ることの二つ目は、それぞれのサービス定義の中でmax_check_attempts 引数を1より大きい数値に設定することです。偶然サービスチェックが別のチェックを衝突すると、Nagiosは誰かが問題に気づく前にmax_check_attempts-1 の回数サービスチェックを再試行します。
  3. 出来る可能性としては、ある種の "back-off and retry" ロジックを実際のサービスチェックのコードに実装することもありますが、大変だったり時間がかかりすぎると思います。
  4. もし全て他の方法が失敗したら、max_concurrent_checks オプションを1に設定することで有効に並列化を止めることが出来ます。めざましい解決とは言えませんが、これにより一度に一つだけのサービスチェックが行われるようになります。もしたくさんの要求があれば、サービス毎に並列化するかどうか指定できるオプションをサービス定義に追加しましょう。もしたくさん要求が無ければ、やりません.....

注意すべきもう一つ別のことは、サービスチェックの並列化にあるNagiosを運用しているマシンのシステムリソースの効果です。たくさんのサービスチェックを並列で行うと、CPUとメモリがきつくなります。inter_check_delay_method は、チェックの間隔を平等に広げ、マシンに押し付けられた負荷を小さくしようとします("smart" メソッドを設定している場合)が、確実な解決法ではありません。ある与えられた時間にどれだけのサービスチェックが実行できるかを制御するためには、max_concurrent_checks 変数を使ってください。チェックするサービスチェックの総数や、使用出来るシステムリソース(CPUスピード、メモリなど)、マシン上で動いているその他のプロセスに基づいてこの値を微調整しなければなりません。あなたの環境でmax_concurrent_checksを微調整する方法のさらなる情報は、check scheduling のドキュメントを読んでください。

並列化されないもの

サービスチェックの実行だけが並列化されることを覚えておくのは重要です。他のものは非常に安全にまたは正気な方法で並列化出来ない、というのがこのことの大きな理由になっています。特にイベントハンドラー、連絡通知、サービスチェックとホストチェックの調査は並列化されません。以下に理由をあげます....

イベントハンドラーは設計上の理由から並列化されません。イベントハンドラーのパワーの大部分は、問題に対し事前に対策を講じる能力から生じています。この実例には、ローカルマシン上のHTTPサービスがダウンと検知されるとウェブサーバを再起動するというものがあります。一つ以上のイベントハンドラーが問題を”修正”しようとするのを避けるために(互いに何をしているのか知らない)、私はこれらを並列化しないことにしました。

連絡通知は使ってる潜在的な通知方法の理由で並列化されません。例えば、もし連絡通知がダイアルアップし、あなたのページャにメッセージを送るのにモデムを使っていれば、通知が進行している間モデムに過度のアクセスが必要になります。もしそんな通知が2又はそれ以上並列で実行されると、一つ以外の全てはモデムへアクセス出来ないので失敗します。ある種の"back-off and retry" 手法を通知スクリプトに持たせるような感じでこれを回避する方法はいくつかありますが、私はユーザがそれらのスクリプトにこの種の機能を実装するようあてにしないと決めました。クイックノート もしモデムを使ってチェックするサービスがあるなら、ダイアルアップするスクリプトにモデムへのアクセスを再試行するなんらかの方法があることを確認してください。サービスチェックが通知と同時に実行されているかもしれないのでこれは必要です!

サービスチェックの結果を調査することは並列化されていません。これはホストがダウンしたり到達不能、復旧した場合に複数のホストの障害や復旧の通知が送信される状況を避けるためにそうしています。