はじめに
この記事は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つのサンプルデータが準備されています。
- eCommerce orders
- flight data
- web logs
kibanaの画面を数クリックするだけで、データの投入が完了します。
今回はweb logs
を使っていきます。
投入したデータはDiscoverタブで確認することができます。
今回投入したデータは、kibana_sample_data_logs
というIndex Pattern名で保存されています。
Machine Learning
Machine Learningの設定
では実際にMachine Learningで異常検知を試します。
余談①
いきなり余談ですが…
Machine Learningを行う際にはどのようなデータが含まれているのか、全体を把握することも重要になります。
Elastic Machine LearningにはData Visualizer
という機能があり、これを使うとデータを俯瞰して見ることができます。
Machine Learningの実施
今回は以下のような設定のもと、Machine Learningを行いました。
- Index Pattern: kibana_sample_data_logs
- Job: Single Metric
- Aggregation: Count
- Field: -
- Backet span: 1h
- Name(job_id): count_logs
今回はログの中身を見ているのではなく、ログが入ってきた数に注目して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が表示されます。
この内容を見ると、少なくとも2時間以上、25回のBucket Spanが含まれることを推奨しているようです。
たしかにデータ数は多いものの、1時間程度のデータでMachine Learningをかけると、正しく結果が表示されませんでした。
異常の確認
Single Metric ViewerでMachine Learningの結果を詳細に見ることができます。
今回対象にしたデータはある程度周期性を持つデータであり、だいたい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にチェックを入れないと見えません。
Machine Learningを行うと、上記のように.ml-
が頭についたindexが作成されます。
このうち、.ml-anomalies-*
というindexにanomaly_score
をfieldに持つdocumentが格納されていくので、このindexを対象にクエリを投げることになります。
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を実行する。
- 検索に引っかかったdocumentが
-
action
- ログに
info
として、There are [検索でヒットした件数] documents in your index. Threshold is 50.
と表示する。
- ログに
というものになります。
Watcherの実施
上記の設定でWatcherを実行すると、
このように最初はState: OK
となりますが、設定したconditionに合致した場合、
このように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がリリースされた当初に比べると使い始めるハードルも低くなっているので、まず使ってみることがいいのではないかと思います。