
Elasticsearchのデータを元にアラート通知できるElastAlertは、X-Pack(Watcher Alert)を導入しない環境において、ログ監視を実装する有用な方法として広く使用されている。
しかし、ElastAlertはコマンド・設定ファイル(YAML)ベースでの動作のみをサポートしており、アラートルール編集・抑止等は(CIなどでの操作は可能だが)サーバ操作が必要となる。アラートを受け取りたいのはKibanaのみを操作する一般ユーザであるケースが多く、ElastAlertのルール運用はやや面倒だ。ElastAlertをKibanaのタブとして組み込める ElastAlert Kibana Pluginはあるが、シンプルなアラート作成のみが可能...
そこで、ElastAlertの機能一式をサポートしているPraecoを使用する。
Praecoでは、ElastAlert Kibana Pluginの開発元のElastAlert Serverを使用している。
Note:
Praecoは2019/3/23時点で Beta 4 - "Italica" とベータリリースとなっています。また、ElastAlert, ElastAlert Server, Praecoと、三者が関連するため、開発・アップデートサイクルにやや不安があります。採用の際は注意して検討ください。
(追記) 2019/9/27にv1.0がリリースされました🎉 (※記事中の動作確認はBeta 4 - "Italica"のままです)
2020/2/10時点で ElastAlert v2.0.1の不具合の影響で各種機能が正常動作しないことがあります。こちらの記事に書いたとおり、修正を独自実装して動かせた。
- Open Distro for Elasticsearch
- Praecoをインストールする
- Praecoでアラート設定する
- まとめ - Praeco (ElastAlert GUI)でElasticsearchログアラートする
Open Distro for Elasticsearch
AWSがOpen Distro for Elasticsearchをリリースし、X-Pack相当の機能がオープンソースで公開されるようになったが、Elasticでは以下のようなニュースを出していたり、賛否両論あるため様子見している。
Praecoをインストールする
今回はDocker-ComposeでPraecoを起動する。Dockerを使用しない場合はnpmで起動する方法がオフィシャルで案内されている。
Praecoダウンロード
[root@h-cent-doc01 docker-compose]# git clone https://github.com/ServerCentral/praeco Cloning into 'praeco'... remote: Enumerating objects: 52, done. ... Resolving deltas: 100% (1567/1567), done. [root@h-cent-doc01 docker-compose]# cd praeco/
通知先設定
Praeco起動前にElastAlertの通知先を設定する。今回はSlackに通知する。
vi rules/BaseRule.config
slack_webhook_url: 'https://hooks.slack.com/services/XXXXXXXXX/XXXXXXXXX/XXXXXXXXXXXXXXXXXXXXXXXX' smtp_host: '' smtp_port: 25 slack_emoji_override: ':postal_horn:'
Slack通知のリンク先はpublic/praeco.config.jsonで設定されている。
vi public/praeco.config.json
{
"appUrl": "http://localhost:8080",
"errorLoggerUrl": "",
"hidePreconfiguredFields": []
}
Praeco起動
[root@h-cent-doc01 praeco]# export PRAECO_ELASTICSEARCH=<ELASTICSEARCH_IP or FQDN>
[root@h-cent-doc01 praeco]# docker-compose up
Creating network "praeco_default" with the default driver
Pulling webapp (servercentral/praeco:latest)...
latest: Pulling from servercentral/praeco
22dbe790f715: Pull complete
...
Digest: sha256:89f4c18f3e336ec216e9eed3e0a21211ad4d7205dd0ea1d4c5332de6911c4291
Status: Downloaded newer image for servercentral/praeco:latest
Pulling elastalert (servercentral/elastalert:latest)...
latest: Pulling from servercentral/elastalert
8e402f1a9c57: Pull complete
...
Digest: sha256:707e813613f66ba9628801ed0cd847e0e374d613aae893e59d821d64360be370
Status: Downloaded newer image for servercentral/elastalert:latest
Creating praeco_webapp_1 ...
Creating praeco_elastalert_1 ...
Creating praeco_webapp_1
Creating praeco_webapp_1 ... done
Attaching to praeco_elastalert_1, praeco_webapp_1
elastalert_1 |
elastalert_1 | > @bitsensor/elastalert@0.0.14 start /opt/elastalert-server
elastalert_1 | > sh ./scripts/start.sh
elastalert_1 |
elastalert_1 | 05:47:03.951Z INFO elastalert-server: Config: No config.dev.json file was found in /opt/elastalert-server/config/config.dev.json.
elastalert_1 | 05:47:03.954Z INFO elastalert-server: Config: Proceeding to look for normal config file.
elastalert_1 | 05:47:03.960Z INFO elastalert-server: Config: A config file was found in /opt/elastalert-server/config/config.json. Using that config.
elastalert_1 | 05:47:03.991Z INFO elastalert-server: Router: Listening for GET request on /.
...
elastalert_1 | 05:47:03.996Z INFO elastalert-server: Router: Listening for GET request on /config.
elastalert_1 | 05:47:04.001Z INFO elastalert-server: ProcessController: Starting ElastAlert
elastalert_1 | 05:47:04.001Z INFO elastalert-server: ProcessController: Creating index
elastalert_1 | 05:47:09.697Z INFO elastalert-server:
elastalert_1 | ProcessController: Elastic Version:6
elastalert_1 | Mapping used for string:{'type': 'keyword'}
elastalert_1 | New index praeco_elastalert_status created
elastalert_1 | Done!
elastalert_1 |
elastalert_1 | 05:47:09.697Z INFO elastalert-server: ProcessController: Index create exited with code 0
elastalert_1 | 05:47:09.697Z INFO elastalert-server: ProcessController: Starting elastalert with arguments [none]
elastalert_1 | 05:47:09.704Z INFO elastalert-server: ProcessController: Started Elastalert (PID: 47)
elastalert_1 | 05:47:09.706Z INFO elastalert-server: Server: Server listening on port 3030
elastalert_1 | 05:47:09.707Z INFO elastalert-server: Server: Websocket listening on port 3333
elastalert_1 | 05:47:09.709Z INFO elastalert-server: Server: Server started
Praecoが起動すると、指定したElasticserchにElastAlert用のindexが作成される。prefixはpraecoとして作成される。
GET _cat/indices?v&s=index health status index uuid pri rep docs.count docs.deleted store.size pri.store.size green open .kibana_1 XppKrqwlQ0WCJuD_ZA75uA 1 0 345 0 286.8kb 286.8kb yellow open elastiflow-3.4.1-2019.03.22 QKhlIUdCTpmeqDox_nvjkw 3 1 28050 0 10.6mb 10.6mb yellow open elastiflow-3.4.1-2019.03.23 B2f_KpS0RxCGYHl7UbhJuQ 3 1 22340 0 8.6mb 8.6mb green open praeco_elastalert_status clr-u5uKSLqZEsrVVhNmhQ 1 0 0 0 230b 230b green open praeco_elastalert_status_error T4-SRO3SQxyrg5Xv4x2v8w 1 0 0 0 230b 230b green open praeco_elastalert_status_past xMMWoEtgSNG7YtAT7SVmGQ 1 0 0 0 230b 230b green open praeco_elastalert_status_silence 2_2o8DcvSBOoU3UXRirmxg 1 0 0 0 230b 230b green open praeco_elastalert_status_status 9qnRPpPpR4GjELOMdSMgzQ 1 0 0 0 230b 230b
Praecoでアラート設定する
Praeco Web GUIを使用して、Elasticsearchのログからアラート通知できるよう設定する。
Praeco Web GUIにアクセスする
http://<docker-host>:8080

ElastAlert APIには3030番ポートでアクセスできる。
http://<docker-host>:3030

アラートルールを作成する
Elasticsearchを参照しているため、Indexをプルダウンから選択する。Indexを選択したら、クエリを編集する。

クエリはリアルタイムにマッチ状況を確認しながら編集できる。

ISの項目でしきい値を調整できる。クエリが正しく設定されていると、しきい値のラインが表示される。分かりやすい。

Aggregationを有効化すると、アラート単位を編集できる。(ElastAlert標準機能の通り) ここでも、Indexの情報が引き継がれているため、プルダウンから選択することができる。

通知の設定も分かりやすい。


クエリのTestも可能。

ルールはDisable状態で作成されているため、Enableする。

Confirm.

アラートルールはrules配下に生成される。
[root@h-cent-doc01 praeco]# ls -la rules/ 合計 12 drwxr-xr-x. 2 root root 52 3月 23 17:29 . drwxr-xr-x. 10 root root 4096 3月 23 14:46 .. -rw-r--r--. 1 root root 165 3月 23 17:14 BaseRule.config -rw-r--r--. 1 root root 1014 3月 23 17:23 ElastiFlow.yaml
アラートと各種ログ
ログのしきい値超過を検知したら、設定した通り通知を受け取れる。

アラート履歴

クエリ履歴


Silence設定
アラートルールは一定期間Silence(無効化)することができる。※5 minutes, 1 hour, 1 daysのボタンはエラーになって使えなかった...

無効化中はNoticeが表示される。

Silence解除(Unsilence) ※動作検証途中
現状、GUIではSilence設定を解除する項目がない。ElastAlert自身に該当するコマンド等がないため納得。記載の方法でSilence解除は可能だが、運用を考慮して要検討。
Silence設定はpraeco_elastalert_status_silenceのindexに保存されている。
GET praeco_elastalert_status_silence/_search
{
"query": {
"range" : {
"until" : {
"gt" : "now"
}
}
}
}
---
{
"hits" : {
"total" : 1,
"max_score" : 1.0,
"hits" : [
{
"_index" : "praeco_elastalert_status_silence",
"_type" : "silence",
"_id" : "vcKqqWkBYbvXPV6quKBd",
"_score" : 1.0,
"_source" : {
"rule_name" : "ElastiFlow._silence",
"@timestamp" : "2019-03-23T08:28:51.674337Z",
"exponent" : 0,
"until" : "2019-03-23T10:28:51.674328Z"
}
}
]
}
}
untilの内容を現在時刻で更新し、Praecoを再起動することで、Silenceを実質解除できる。ドキュメントIDを検索・使用するため運用に難あり...。また、ElastAlert単体で--silenceを使用した際は再起動不要でSilence解除できたが、Praecoとの組み合わせ時は再起動が必要だった。(詳細動作仕様は未調査)
POST praeco_elastalert_status_silence/silence/<id>/_update
{
"script" : {
"source": "DateFormat df = new SimpleDateFormat(\"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'\");\ndf.setTimeZone(TimeZone.getTimeZone(\"UTC\"));\nDate date = new Date();\nctx._source.until = df.format(date);",
"lang": "painless"
}
}
---
{
"_index" : "praeco_elastalert_status_silence",
"_type" : "silence",
"_id" : "vcKqqWkBYbvXPV6quKBd",
"_version" : 2,
"result" : "updated",
"_shards" : {
"total" : 1,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 2,
"_primary_term" : 1
}
GET praeco_elastalert_status_silence/_search
{
...
"rule_name" : "ElastiFlow._silence",
"@timestamp" : "2019-03-23T08:28:51.674337Z",
"exponent" : 0,
"until" : "2019-03-23T09:11:32.912Z"
...
}
(非推奨)rule_name指定でドキュメントを削除してもよいが、Silence履歴も消えてしまうため注意。
POST praeco_elastalert_status_silence/_delete_by_query
{
"query":{
"match": {
"rule_name": "ElastiFlow._silence"
}
}
}
まとめ - Praeco (ElastAlert GUI)でElasticsearchログアラートする
Praecoを使用することでGUIベースでElastAlertを操作することができるようになった。ルール作成画面は非常に洗練されており、Kibana本家に搭載されているWatcher(X-Pack)よりも使い勝手が良いように思う。
引き続きテンプレート機能なども動作確認をし、効率的な運用方法を検討する。
BOSH Releaseも作成中
github.com