どうも、cloudpackのかっぱ(@inokara)です。
はじめに
最近、sensu 周りでやったことを書きます。
sensu-server で管理するクライアントの数が増えてくると純粋な sensu-server のログは目 grep では追いつかないくらいの量に増えてしまいます。このログを Elasticsearch に放り込んでみたりエラーレベルなログは Slack に通知する仕組みを fluentd を利用して作りました。
以下のようなイメージ。
尚、今回は監視対象で発生する warning や critical なログをどうこうするというお話ではなく、あくまでも sensu-server の動作ログのお話となります。ただ、同じような仕組みで可視化や通知を行うことは可能かと考えています。
実装にあたりましては以下の書籍を参考にさせて頂きました。
fluentd に関する情報がギュッと詰まった一冊となっています!
何が便利になるのかしら?
そもそもエラーが起きないこと、設定ミスらないことが重要なのですが、sensu クライアントの設定で handler の定義に sensu-server 側に存在しない handler の設定を書いてしまうと…以下のようなエラーが sensu-server のログに記録されてしまいます。
{"timestamp":"2014-10-01T22:16:52.781338+0900","level":"error","message":"unknown handler","handler_name":"default"}
このまま放置しておいても sensu-server は動きますが、クライアントからのイベントのログと混ざってしまいイケてないと思いますしウザいですね。こんなログを早めに見つけて対処しましょうというのが今回の試みとなります。
実装と運用
概要
やっていることはシンプルです。
- sensu-server のログを fluent-plugin-elasticsearch を利用して Elasticsearch に突っ込む(可視化)
- 同時に fluent-plugin-notifier と fluent-plugin-slack を利用して slack にポスト(通知)
以下、少し細かく見てみます。
sensu-server のログを Elasticsearch に突っ込む
そもそも sensu-server のログは JSON ですので以下のように in_tail プラグインの format json
で tail して Elasticsearch に飛ばしてあげます。
<source> type tail format json path /var/log/sensu/sensu-server.log tag sensu.server.log pos_file /tmp/sensu.server.log.pos </source>
細かい話ですが直接は Elasticsearch に飛ばさず、一旦、収集用の fleuntd に飛ばしてあげてから Elasticsearch に飛ばします。以下はログレベルが warn なログのみを抽出して表示させた状態です。
slack への通知
時代は ChatOps!! ということで、以下のような fluentd の設定を行い fluent-plugin-notifier でログを絞りこんで fluent-plugin-slack に飛ばしています。
<match sensu.server.log> type copy <store> (中略) </store> <store> (中略) </store> <store> type notifier default_tag_warn notifier.sensu-sevrer.warn.log default_tag_crit notifier.sensu-server.crit.log default_interval_1st 1 <def> pattern sensu_error check string_find warn_regexp warn crit_regexp error target_key_pattern ^level$ </def> </store> </match> <match notifier.sensu-sevrer.*.log> type copy <store> type stdout </store> <store> type buffered_slack api_key ${API_TOKEN} team ${TEAM_NAME} channel %23${SLACK_CHANNEL} username sensu-logging buffer_path /var/log/td-agent/buffer/slack flush_interval 60s color good icon_emoji :kappa: timezone Asia/Tokyo </store> </match>
fluent-plugin-notifier や fluent-plugin-slack のインストール方法については割愛しますが、連携の方法についてはちょっと工夫が必要でした。
特定の key パターンで通知するログを絞り込む
工夫という程ではなくデフォルトの機能ですが、fluent-plugin-notifier で record 内の特定の key パターンを利用したい場合には以下のように check string_find
を利用します。
<def> pattern sensu_error check string_find warn_regexp warn crit_regexp error target_key_pattern ^level$ </def>
上記では正規表現を利用して level から始まる key を指定していて、以下のようなログにマッチすることになります。
{"timestamp":"2014-10-01T22:16:52.781338+0900","level":"warn","message":"unknown handler","handler_name":"default"}
又は
{"timestamp":"2014-10-01T22:16:52.781338+0900","level":"error","message":"unknown handler","handler_name":"default"}
slack への通知に詳細を載せたい
fluent-plugin-notifier から出力された通知は以下のように出力されますが、当初はこの内容を slack にも送れずに悩んでおりました…(通知だけは送れていました)
2014-10-04 05:37:12 +0900 notifier.sensu-sevrer.warn.log: {"pattern":"sensu_error","target_tag":"sensu.server.log","target_key":"level","check_type":"string_find","level":"warn","regexp":"/info/","value":"info","message_time":"2014-10-04 05:36:17 +0900"}
以下のように fluent-plugin-slack に手を入れさせて頂いて送れるようになりました。
--- out_buffered_slack.rb.bk 2014-10-04 05:53:35.993848035 +0900 +++ out_buffered_slack.rb 2014-10-04 05:53:40.945725720 +0900 @@ -21,6 +21,8 @@ chunk.msgpack_each do |tag, time, record| messages[tag] = '' if messages[tag].nil? messages[tag] << "[#{Time.at(time).in_time_zone(@timezone).strftime("%H:%M:%S")}] #{record['message']}n" + messages[tag] << "#{record}n" end begin payload = {
fluent-plugin-slack は入ってくる record の message キーの値を詳細として slack に飛ばす実装になっているようですが、今回は message キーが入っていないので record そのままを出力させています。
ということで、以下はテスト的に info レベルのログを飛ばした結果です。
fluent-plugin-notifier で絞り込む target_key_pattern を細かく指定してあげることで、各クライアントで発生している event の結果も slack に飛ばしてあげることが出来そうですね。
運用
実際の運用については…
- slack で通知を受け取る
- Elasticsearch でログの詳細を確認する
- 対応する
という流れです。
通知の部分が従来はメール通知だったりするわけですが、ちゃんと振り分けしていなければ見落としてしまったり、一部の担当者にしか届いていない等の運用上の問題とログを解析してメールで送信するという実装の手間を少しでも楽に出来るのではないかなと期待しています。
また、通知を受け取った後でサーバーにログインして目 grep してという作業を止めて Elasticsearch に置き換えることで該当のログを一瞬で確認することが出来るのもかなり嬉しいかなと思っています。さらに月末等の締めの時期に視覚的に確認しながらレビューすることが出来るも運用する上では嬉しいのではと考えています。
締め
実は
このネタは自分が設定ミスったのを気づかず放置してしまったことを発端に考えました。(本当にすいませんでした)
ミスはあきませんが誰にでもミスは付き物ですので、ミスっても「速く」「効率良く」「最小限の手間」でミスをリカバリ出来るような環境を作っていくことが個人的な課題の一つかなと考えていますし、sensu や fluentd や Elasticsearch 等のツールを組み合わせることでかなりお手軽に可視化や通知の環境が構築出来ることにかなり興奮して眠れません。
今後の課題
ということで、今後の課題としては…
- Elasticsearch の運用(インデックスのメンテナンス等)をどうするか(←キメの問題だけかと)
- 監視のイベント自体も同じ運用してみたい(特に通知)
こんな事考えてます。
お疲れ様でした。
元記事はこちらです。
「sensu-server のログを fluentd を使って Elasticsearch で可視化したり Slack に通知したりする」