ElastAlert による Elasticsearch のインデックス監視・通知
こんにちは、藤本です。
Elasticsearch を利用していて、インデキシングされるドキュメントのデータを監視したいことはないでしょうか。例えば、よくユースケースの紹介に挙げられるアクセスログを Elasticsearch にインデキシングしているケースでは、500番台のステータスコードが5分間に10回以上記録があった時に、Slack で通知したい。ログファイルの集約に Elasticsearch にインデキシングしている場合、ERROR のメッセージを含むメッセージを検知した時に、メール通知したい。など、Elasticsearch のインデックスを監視・通知したいケースは多々あるかと思います。
先日、X-Pack の Watcher による Elasticsearch のインデックス監視・通知をご紹介しました。
Elastic StackのX-Packを試す(Watcher編)
今回はもっと手軽に利用できる OSS ツールをご紹介します。
ElastAlert
ElastAlert は Yelp が開発している Elasticsearch のインデックスにあるドキュメントを監視、通知する OSS ツールです。2016/11/14現在は Elasticsearch 1系、2系に対応しており、まだ5系は未対応です。ElastAlert は大きく監視ルール、通知の2つのコンポーネントから成り立ちます。監視ルールはどのくらいの間隔で、どういう Elasticsearchクエリを発行して、何を条件として通知するのか定義します。通知は監視ルールの条件に合致した時にどういう通知を行うのかを定義します。設定はグローバルコンフィグ、個別監視設定をYAML形式で記述します。
監視ルールタイプ
ElastAlert は現在9種類のルールタイプをサポートしています。
監視ルールタイプの説明は下記サイトが参考になります。
elastalertでアプリの異常を自動検知して通知したい
Any
常に通知します
Blacklist
指定したフィールドが指定した値にマッチした時に通知します。
Whitelist
指定したフィールドが指定した値にマッチしなかった時に通知します。
Change
指定したフィールドの値が変化した時に通知します。
Frequency
指定した期間内に指定したクエリのドキュメント件数が指定した値以上の時に通知します。システム異常を検知できます。
Flatline
指定した期間内に指定したクエリのドキュメント件数が指定した値より少ない時に通知します。システム異常を検知できます。
Spike
指定したクエリのドキュメント件数が前回取得のクエリ結果の指定した値の倍数以上の時に通知します。突発的なアクセス増加を発見できます。
New Term
指定したフィールドの値が指定した期間内に同じ値がない時に通知します。未知のログ出力を発見できます。
Cardinality
インデックスのフィールド数が増えた時に通知します。データソースのフォーマットの変化を発見できます。
設定可能な項目はソースコード内にある schema.yaml に定義されています。
通知方法
ElastAlert は現在11種類の通知方法をサポートしています。
指定したメールアドレスへメール通知します。
JIRA
Atlassian の JIRA へチケットを起票します。
OpsGenie
OpsGenie を介して様々な通知を行えます。
Commands
ElastAlert が動作する OS 内で指定したコマンドを実行します。
HipChat
HipChat のチャットルームへ通知します。
Slack
Slack のチャットルームへ通知します。
Gitter
Gitter のチャットルームへ通知します。
Telegram
Telegram へ通知します。
AWS SNS
AWS の SNS Topic をパブリッシュします。
VictorOps
VictorOps を介して様々な通知を行えます。
PagerDuty
PagerDuty を介して様々な通知を行えます。
X-Pack と ElastAlert の比較
ザックリ表にまとめました。有償プロダクトの X-Pack は充実した機能、Elasticsearch のバージョンとの安定性、Elastic社からのサポートがあり、安心して利用できます。一方の ElastAlert は無償利用、シンプルなPython実装のOSSなのでフォークして拡張したり、動作が分からない時にソースコードから原因解析することができます。実際、検証していてちょっとハマった時もソースコード読めば原因を特定することができました。またAWS専業の弊社としては Amazon ES、Amazon SNS に対応しているのは嬉しいです。特に Amazon SNS と連携しているので、Amazon SNS から AWS Lambda をキックすれば、ユースケースはかなり広がるでしょう。
X-Pack | ElastAlert | |
---|---|---|
コスト | 要サブスクリプション | OSS(Python実装) |
トリガー | お互いスケジューリング | |
監視方法 | ElasticsearchクエリWebリクエスト固定値上記の組み合わせ | Elasticsearchクエリ |
条件 | 柔軟な条件 | 特定の条件(前述) |
通知方法 | EmailWebhookIndexLoggingHipChatSlackPagerDuty | EmailJIRAOpsGenieCommandsHipChatSlackTelegramAWS SNSVictorOpsPagerDutyGitter |
設定管理 | インデックス | YAMLファイル |
バージョン対応 | 基本的に最新バージョンに追従 | 1.X、2.X対応(2016/11/06時点) |
サポート | サブスクリプションによるElastic社からのサポート | なしOSSなのでGithubのIssueなどで |
AWS対応 | − | Amazon ES対応通知にAmazon SNS利用可 |
試してみた
今回は最初に記載したユースケースのアクセスログの500番のステータスコードが5分間に10回以上記録があった時に、Slack で通知したい、を実装します。Webサーバのアクセスログを Logstash を利用して、準リアルタイムで Elasticsearch に取り込んでいます。監視したいステータスコードはresponse
というフィールド名でデータを保持します。
環境
- Elasticsearch Node
- OS : CentOS 7.2
- Elasticsearch : 2.4.1
- ElastAlert動作環境
- OS : MacOS
- Python : 2.7.12
- ElastAlert : 0.1.3
インストール
ElastAlert は pip でインストールできます。現在サポートされている ElastAlert のPythonバージョンは 2.6系、2.7系となります。ElastAlert は ElasticsearchとのインタフェースにElasticsearch-py を利用します。なので、基本的には Elasticsearch のメジャーバージョンに合わせたバージョンの Elasticsearch-py を利用してください。現在、pip にてインストールすると Elasticsearch-py の5系がインストールされます。今回は Elasticsearch 2.4.1 を利用したので、Elasticseach-py の2系の最新バージョンをインストールしています。
# pip install "elasticsearch>2.0.0,<3.0.0" elastalert Collecting elasticsearch<3.0.0,>2.0.0 Using cached elasticsearch-2.4.0-py2.py3-none-any.whl Collecting elastalert : Installing collected packages: urllib3, elasticsearch, simplejson, six, python-dateutil, requests, oauthlib, requests-oauthlib, tlslite, jira, boto, blist, functools32, jsonschema, croniter, aws-requests-auth, texttable, jmespath, docutils, botocore, funcsigs, pbr, mock, configparser, argparse, pyyaml, PyStaticConfiguration, elastalert Successfully installed PyStaticConfiguration-0.10.2 argparse-1.4.0 aws-requests-auth-0.3.0 blist-1.3.6 boto-2.43.0 botocore-1.4.70 configparser-3.5.0 croniter-0.3.13 docutils-0.12 elastalert-0.1.3 elasticsearch-2.4.0 funcsigs-1.0.2 functools32-3.2.3.post2 jira-0.32 jmespath-0.9.0 jsonschema-2.5.1 mock-2.0.0 oauthlib-2.0.0 pbr-1.10.0 python-dateutil-2.5.3 pyyaml-3.12 requests-2.11.1 requests-oauthlib-0.7.0 simplejson-3.10.0 six-1.10.0 texttable-0.8.6 tlslite-0.4.9 urllib3-1.19
インストールはこれだけです。
初期設定
ElastAlert は Elasticsearch のインデックスで ElastAlert の実行履歴、差分情報を管理します。まずは管理用のインデックスを生成します。コマンドで対話形式で設定します。
# elastalert-create-index New index name? (Default elastalert_status) ⇐ デフォルトの場合はそのままEnter Name of existing index to copy? (Default None) ⇐ デフォルトの場合はそのままEnter New index elastalert_status created Done!
設定ファイル作成
ElastAlert の設定ファイルはグローバルコンフィグ、個別監視設定の2つのYAMLファイルから成り立ちます。
グローバルコンフィグ作成
個別監視設定を横断した共通設定のコンフィグファイルを作成します。設定値は個別監視設定が優先され、個別監視設定になければ、グローバルコンフィグから参照する関係性となります。例えば、各監視ルールの通知先 Slack チャンネルが共通であれば、Incoming Webhook URL をグローバルコンフィグに指定することが可能です。
グローバルコンフィグでは以下の設定項目が必須となります。
設定キー | 説明 |
---|---|
es_host | 接続する Elasticsearch のホスト名・IPアドレス |
es_port | 接続する Elasticsearch のポート番号 |
rules_folder | 個別監視設定のYAMLファイルが配置されたディレクトリパス |
buffer_time | データ取得期間 |
run_every | 監視する間隔 |
writeback_index | 実行履歴を管理するインデックス名 |
config.yaml
es_host: 10.255.0.100 es_port: 9200 rules_folder: rules buffer_time: hours: 1 run_every: minutes: 1 writeback_index: elastalert_status
個別監視設定
個別監視設定では監視ルール、通知方法を定義します。
監視ルール設定
今回はある期間内にしきい値を超えるドキュメント数があった時にアラートを上げたいので、監視ルールタイプに Frequency を利用します。Frequency ルールでは以下の設定が必要となります。
設定キー | 説明 |
---|---|
type | frequency |
name | 監視ルールの名前 |
index | 監視対象のインデックス名(ワイルドカード(*)を利用可) |
num_events | しきい値。期間内にしきい値を超えたらアラート |
timeframe | 監視期間 |
アラート設定
今回は Slack チャンネルに通知したいので、通知方法は Slack を利用します。また Slack 通知する場合、通知を受け取りたいチャンネルで Incoming Webhook を有効化してください。Slack 通知では以下の設定が可能です。
設定キー | 説明 |
---|---|
alert | slack |
slack_webhook_url | 通知を受け取りたいチャンネルの Incoming Webhook URL |
slack_username_override | 通知ユーザー名 デフォルト値は elastalert |
slack_emoji_override | 通知ユーザーアイコン デフォルト値はゴーストアイコン |
slack_icon_url_override | 通知ユーザーアイコン |
slack_msg_color | 通知メッセージの引用ラインの色 |
slack_parse_override | 通知メッセージのエスケープの有無 |
slack_text_string | 付加したい通知メッセージ |
rules/status500-moniroting.yaml
今回は最低限の設定としています。
監視したい Elasticsearch のインデックスは logstash- から始まる全てとします。5分間に10回という条件はnum_events
、timeframe
で指定します。今回は response フィールドが 500 の値だけをカウントしたいので term クエリでフィルターします。
アラート設定のslack_webhook_url
は利用するチャンネルのURLに置き換えてください。
name: status500-moniroting type: frequency index: logstash-* num_events: 10 timeframe: minutes: 5 filter: - term: response: 500 alert: - slack slack_webhook_url: "https://hooks.slack.com/services/xxxxxxxxx/xxxxxxxx/xxxxxxxxxxxxxxxxxxx"
動作確認
ElastAlert を起動します。
# elastalert
config.yaml のbuffer_time
で指定した期間内に監視ルールの条件にマッチしなければ、特に何も起きません。今回の設定では過去1時間の中で5分間にステータスコード500のリクエストが10回発生していなければ、通知されません。
次に監視条件にマッチするようにステータスコード500が発生するリクエストを10回以上送信します。
config.yaml のrun_every
の次のクエリで検知します。
Slack 通知が発生します。
通知メッセージは監視ルールに応じたメッセージと検知した最新のドキュメントを受信します。
まとめ
いかがでしたでしょうか?
インストールはpipで、設定はYAMLファイルだけですので、非常に簡単に利用することができました。機能も豊富で、公開されて1年半ぐらい経過していますが、現在も定期的にコミットされていてメンテナンスされているようですので安心して使えそうです。