LoginSignup
5
7

More than 5 years have passed since last update.

Machine Learningでの異常検知をトリガーにWatcherで通知するまで

Last updated at Posted at 2018-12-20

はじめに

この記事はElastic stack (Elasticsearch) Advent Calendar 2018の21日目です。

流行りのMachine LearningがElastic StackのFeaturesでも簡単にできます。
異常の検知だけではなく、その異常に対して対処を行うまでが一連の動作だと思うので、異常を検知した後に通知をしたり、他のシステムと連携させて異常の原因を解決できてこそ、良いシステムになるのではないでしょうか。
そこで今回はElastic Machine Learningで異常検知した結果をトリガーにしてWatcherを使って通知するところまでを書いていきます。
※ここで紹介している方法が最適かどうかは別として、まずはMachine LearningとWatcherを連携させてみましょう!という趣旨です。

以前ElasticのMachine Learningについて書いた記事はこちら にあるので、基本的な部分が知りたい方はあわせてご覧ください。Elastic Machine LearningにはForecastの機能もあり、気になる方はこちらもどうぞ。

環境

elasticsearch: 6.5.1
kibana: 6.5.1

Machine LearningはPlatinum、WatcherはGoldの機能ですが、30日間はトライアルでPlatinum相当の機能を使えるので、今回はトライアル環境で構築しました。
また、最近のバージョンではサンプルデータが準備されているため、ユーザーがデータを準備しなくても機能を試すことができます。
今回使ったデータもサンプルデータなので、elasticsearchとkibanaの環境さえあれば、今回の記事の内容を試すことができます。

データの準備

バージョン6.5.1では3つのサンプルデータが準備されています。

add_data_to_kibana_2.png

  • eCommerce orders
  • flight data
  • web logs

kibanaの画面を数クリックするだけで、データの投入が完了します。
今回はweb logsを使っていきます。

投入したデータはDiscoverタブで確認することができます。
今回投入したデータは、kibana_sample_data_logsというIndex Pattern名で保存されています。

kibana_sample_data_logs.png

Machine Learning

Machine Learningの設定

では実際にMachine Learningで異常検知を試します。

余談①

いきなり余談ですが…
Machine Learningを行う際にはどのようなデータが含まれているのか、全体を把握することも重要になります。
Elastic Machine LearningにはData Visualizerという機能があり、これを使うとデータを俯瞰して見ることができます。

DV_1.png

Machine Learningの実施

今回は以下のような設定のもと、Machine Learningを行いました。

  • Index Pattern: kibana_sample_data_logs
  • Job: Single Metric
  • Aggregation: Count
  • Field: -
  • Backet span: 1h
  • Name(job_id): count_logs

ml_job.png

今回はログの中身を見ているのではなく、ログが入ってきた数に注目してMachine Learningを行なっています。
今回は静的なデータを扱っているため、このままView Resultsに移りますが、リアルタイム異常検知をしたい場合はContinue job in real-timeを使って、リアルタイムに送られてくるデータをMachine Learningにかけ続けることになります。

余談②

Backet Spanを今回は1hに設定しましたが、自分が検知したいものをきちんと検知するために、Backet Spanの設定は非常に重要です。
Backet Spanを短く設定すればよりリアルな数値を扱うことになり、長く設定すれば平滑化された数値を扱うことになります。
突発的な数値の変化を検知したいのであればBacket Spanは短く設定すべきですが、その分計算量も増えるので、マシンリソースと相談になるかもしれません。
※Machine Learning専用ノードというものもあり、本番環境でMachine Learningを行う際はこの専用ノードを使うことを推奨しているようです。

余談③

Machine Learningを行う際、事前にValidate jobをクリックすることで、設定が正しく行われているか検証することができます。
例えば、機械学習を行うにはある程度のデータ量が必要になりますが、参照するデータの期間を短く設定してValidate jobをクリックすると、以下のようなWariningが表示されます。

validate_warn.png

この内容を見ると、少なくとも2時間以上、25回のBucket Spanが含まれることを推奨しているようです。
たしかにデータ数は多いものの、1時間程度のデータでMachine Learningをかけると、正しく結果が表示されませんでした。

異常の確認

Single Metric ViewerでMachine Learningの結果を詳細に見ることができます。

smv_3.png

今回対象にしたデータはある程度周期性を持つデータであり、だいたい3周期分くらい過ぎたあとから予測値(うすい水色の値)が落ち着いてきています。
表示している範囲にはMachine Learningが予測した値よりもログの数が多く、anomaly_scoreが64を示しているデータがあることがわかります。
ではこの結果をトリガーにするような、Watcherの設定を行なっていきます。

Watcher

Watcherは大きく2通りの方法で設定することができます。

  • Create threshold alert
    • ガイドに従い、Watchの名前やIndex名を指定していくと、スクリプトを書かなくてもWatcherの設定を行うことができます。
    • ここではActionも設定することができ、E-mail、Logging、Slackを連携先に指定することができます。
  • Create advanced watch
    • threshold alertでは設定できない、細かい設定を行う際にはこちらで行います。

今回はadvanced watchで設定を行います。

Machine Learningの結果はどこに格納されているか

Watcherは

  • trigger
  • input
  • condition
  • action

の4つの設定を行う必要がありますが、inputでelasticsearchに格納されたデータに対しクエリを投げ、取得した結果を使うことができます。
Machine Learning実行後は以下のように新しいindexが作られています。
※Include system indecesにチェックを入れないと見えません。

index_management.png

Machine Learningを行うと、上記のように.ml-が頭についたindexが作成されます。
このうち、.ml-anomalies-*というindexにanomaly_scoreをfieldに持つdocumentが格納されていくので、このindexを対象にクエリを投げることになります。

log_anomaly.png

Watcherの設定

Watcherの設定例はこのような感じです。

{
  "trigger": {
    "schedule": {
      "interval": "10s"
    }
  },
  "input": {
    "search": {
      "request": {
        "search_type": "query_then_fetch",
        "indices": [
          ".ml-anomalies-*"
        ],
        "types": [],
        "body": {
          "size": 0,
          "query": {
            "bool": {
              "must": {
                "match": {
                  "job_id": "count_logs"
                }
              },
              "filter": [
                {
                  "range": {
                    "anomaly_score": {
                      "gte": 50
                    }
                  }
                },
                {
                  "range": {
                    "timestamp": {
                      "gte": "now-7d"
                    }
                  }
                }
              ]
            }
          }
        }
      }
    }
  },
  "condition": {
    "compare": {
      "ctx.payload.hits.total": {
        "gte": 1
      }
    }
  },
  "actions": {
    "my-logging-action": {
      "logging": {
        "level": "info",
        "text": "There are {{ctx.payload.hits.total}} documents in your index. Threshold is 50."
      }
    }
  }
}

それぞれの項目ごとに設定内容を確認すると、

  • trigger
    • 10秒ごとに実行する。
  • input

    • .ml-anomalies-*というindexに対して、job_idがcount_logsであり、anomaly_scoreが50以上のdocumentを探す。その際、検索対象は今から7日前までとする。

    ※今回は確実に検索に引っかかるようにするため、今から7日前まで(now-7d)とかなり長めに設定をしています。

  • condition

    • 検索に引っかかったdocumentが1件以上あれば、actionを実行する。
  • action

    • ログにinfoとして、There are [検索でヒットした件数] documents in your index. Threshold is 50.と表示する。

というものになります。

Watcherの実施

上記の設定でWatcherを実行すると、

OK.png

このように最初はState: OKとなりますが、設定したconditionに合致した場合、

Firing.png

このようにState: Firingとなり、ログに

[INFO ][o.e.x.w.a.l.ExecutableLoggingAction] [YoCA0QT] There are 2 documents in your index. Threshold is 50.

と出力されます。

おわりに

このように、Machine LearningとWatcherを連携させることができました。
実際には結果をログに出力して終了ではなく、webhookを使って外部システムと連携させて自動設定変更、ということも作り込んで行けば可能になります。
長々と書きましたが、Machine Learningがリリースされた当初に比べると使い始めるハードルも低くなっているので、まず使ってみることがいいのではないかと思います。

Elastic stack (Elasticsearch) Advent Calendar 2018も残り4日!

5
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
7