実践的な異常検知

2015年6月18日筆者: Brian Brazil

ジョン・オールスパウは、彼の「Open Letter To Monitoring/Metrics/Alerting Companies」の中で、「異常を完璧なタイミングで検知することは不可能である」と主張しています。

才能あるエンジニアたちが時系列データに基づいて問題を自動的に検知し診断するシステムを構築しようとする試みをいくつか見てきました。デモンストレーションを動作させることは確かに可能ですが、実際のシステムではデータが常にノイズが多すぎて、このアプローチは最も単純なもの以外には機能しませんでした。

しかし、希望が失われたわけではありません。カスタム構築されたルールで検知して対処できる一般的な異常はたくさんあります。Prometheusのクエリ言語は、誤検知を回避しながらこれらの異常を発見するためのツールを提供します。

クエリの構築

サービス内のよくある問題は、一部のサーバーが他のサーバーほどパフォーマンスが良くない場合、例えば応答時間が長くなるなどです。

サービスインスタンスごとの平均クエリレイテンシを表すメトリック`instance:latency_seconds:mean5m`があるとしましょう。これは記録ルールによってサマリーメトリックから計算されます。

まず、平均より2標準偏差以上高いレイテンシを持つインスタンスを探すという簡単な方法があります。

  instance:latency_seconds:mean5m
> on (job) group_left()
  (
      avg by (job)(instance:latency_seconds:mean5m)
    + on (job)
      2 * stddev by (job)(instance:latency_seconds:mean5m)
  )

これを試してみると、レイテンシが非常に密接にクラスター化されている場合に誤検知が発生することを発見します。そこで、インスタンスのレイテンシが平均よりも20%高くなければならないという要件を追加します。

  (
      instance:latency_seconds:mean5m
    > on (job) group_left()
      (
          avg by (job)(instance:latency_seconds:mean5m)
        + on (job)
          2 * stddev by (job)(instance:latency_seconds:mean5m)
      )
  )
> on (job) group_left()
  1.2 * avg by (job)(instance:latency_seconds:mean5m)

最後に、トラフィックが少ないレベルで誤検知が発生する傾向があることがわかります。そこで、各インスタンスに1秒あたり1クエリの十分なトラフィックがあることを要件に追加します。これらすべてに対するアラート定義を作成します。

groups:
- name: Practical Anomaly Detection
  rules:
  - alert: InstanceLatencyOutlier
    expr: >
      (
            (
                instance:latency_seconds:mean5m
              > on (job) group_left()
                (
                    avg by (job)(instance:latency_seconds:mean5m)
                  + on (job)
                    2 * stddev by (job)(instance:latency_seconds:mean5m)
                )
            )
          > on (job) group_left()
            1.2 * avg by (job)(instance:latency_seconds:mean5m)
        and on (job)
            avg by (job)(instance:latency_seconds_count:rate5m)
          >
            1
      )
    for: 30m

自動アクション

上記のアラートはAlertmanagerに送られ、そこからチャット、チケット発行、またはページングシステムに送られます。しばらくすると、アラートの通常の原因は適切な修正がないものですが、再起動、再起動、またはマシン交換などの自動アクションで問題を解決できることがわかるかもしれません。

人間がこの反復的なタスクを処理する代わりに、Alertmanagerにアラートをウェブサービスに送信させ、適切なスロットリングと安全機能を備えたアクションを実行させるという選択肢があります。

汎用ウェブフックは、選択したHTTPエンドポイントにアラート通知を送信します。それを使用する簡単なAlertmanager設定は次のようになります。

# A simple notification configuration which only sends alert notifications to
# an external webhook.
receivers:
- name: restart_webhook
  webhook_configs:
    url: "http://example.org/my/hook"

route:
  receiver: restart_webhook

概要

Prometheusのクエリ言語は、監視データを豊富に処理することを可能にします。これにより、良好な信号対雑音比を持つアラートを作成でき、Alertmanagerの汎用ウェブフックサポートは自動的な修復をトリガーできます。これらすべてが組み合わさることで、オンコールエンジニアは最も影響力のある問題に集中できるようになります。

サービスの警告を定義する際には、私たちの警告のベストプラクティスも参照してください。