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/[email protected] 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