fluentd + elasticsearch + kibana
fluentd+elasticsearch+kibanaを導入してみたのですが色々と詰まったところがあったのでこの機会に残しておきます
elasticsearchへの転送
dstatはすでにあるし、あとはcopyしてelasticsearchに流すだけだし余裕っしょ♪
とか思っていたら見事にはまりました。
送ったログをいざグラフ化しようとしても何も選択肢が無いw
レスポンスコードとか、レスポンスタイムとか数値として扱うべきメニューが出てこない
elasticsearch-headプラグインで型を確かめると全部stringになってる!!!!!
elasticsearch側でデフォルトテンプレートを用意してあげる方法もあるようですが、fluentd側で定義してあげればelasticsearchでは空気読んでくれるようなので今回はfluentd側で対応することにしました。
そもそもfluentdでは型を特に指定しないと全てstringとして扱っているようです
なのでfluentdで何か値を生成したりした場合はcastしてあげないと転送先でちゃんと動いてくれない現象に陥ります
これは運用開始前に気付いてよかった。。。。
サーバインフラ要請読本 ログ収集~可視化をよく読んだら載ってたのでちゃんと読もうねって話ですね。。
なので今回はfluent-plugin-typecastを使ってdstatでとった値を全て数値型に変換しました。
<source> type dstat tag dstat option -clmdrns --udp --tcp delay 30 </source> <match dstat> type map tag "monitor.dstat" time time record record["dstat"] </match> <match monitor.dstat> type flatten_hash add_tag_prefix string.app. separator . </match> + <match string.app.monitor.dstat> + type typecast + tag app.monitor.dstat + item_types total cpu usage.usr:float,total cpu usage.sys:float,total cpu usage.idl:float,total cpu usage.wai:float,total cpu usage.hiq:float,total cpu usage.siq:float,load avg.1m:float,load avg.5m:float,load avg.15m:float,memory usage.used:float,memory usage.buff:float,memory usage.cach:float,memory usage.free:float,dsk/total.read:float,dsk/total.writ:float,io/total.read:float,io/total.writ:float,net/total.recv:float,net/total.send:float,swap.used:float,swap.free:float,udp.lis:float,udp.act:float,tcp sockets.lis:float,tcp sockets.act:float,tcp sockets.syn:float,tcp sockets.tim:float,tcp sockets.clo:float + </match>
せっかくdstatで一項目づつ書かなくてよくしたのにだいなしでした。。。
アクセスログとかその他ログも数値で渡したいものに関してはtypeを指定できるなら指定してあげて、できないなら後でcastしてあげる必要があります
source> type tail path /var/log/httpd/access_log pos_file /var/log/td-agent/access_log.pos tag app.balancer.access_log format /^(?<host>[^ ]*) [^ ]* (?<user>[^ ]*) \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>[^ ]*) +\S*)?" (?<code>[^ ]*) (?<size>[^ ]*)(?: "(?<referer>[^\"]*)" "(?<agent>[^\"]*)" "(?<request_time>[^ ]*)" "(?<forwarded_for>[^\"]*)" "(?<cookie>[^\"]*)")?$/ time_format %d/%b/%Y:%H:%M:%S %z + types code:integer,size:integer,request_time:float </source>
ちなみにfluent-plugin-cloudwatchとかは数値型で送ってくれていたので何もする必要はなかったです。
elasticsearchへの転送2
やっと平常運転に入れたかと思ったら下記ログに出くわしました。
- td-agent.log
2015-05-19 11:35:26 +0000 [warn]: Could not push logs to Elasticsearch, resetting connection and trying again. Recv failure: Connection reset by peer
- td-agent.log
2015-05-19 11:26:29 +0000 [warn]: Size of the emitted data exceeds buffer_chunk_limit. 2015-05-19 11:26:29 +0000 [warn]: This may occur problems in the output plugins ``at this server.`` 2015-05-19 11:26:29 +0000 [warn]: To avoid problems, set a smaller number to the buffer_chunk_limit 2015-05-19 11:26:29 +0000 [warn]: in the forward output ``at the log forwarding server.``
- elasticsearch.log
[2015-05-19 11:36:00,332][WARN ][http.netty ] [app10.0.21.60] Caught exception while handling client http traffic, closing connection [id: 0x0a031f69, /10.0.21.20:57853 => /10.0.21.60:9200] org.elasticsearch.common.netty.handler.codec.frame.TooLongFrameException: HTTP content length exceeded 104857600 bytes.
fluentdの設定で、buffer_chunk_limitを多めに変更したのでelasticsearch側で受け付けきれなくなったみたいでした
なのでelasticsearch側で受け付けられるサイズをfluentdのバッファーサイズと同じにしました。
- elasticsearch.yml
http.max_content_length: 1g
また、queueサイズも変更
- elasticsearch.yml
# キューが満杯の状態でリクエストが来た際には、そのリクエストは破棄 # 制限をしたくない場合には -1 を設定 threadpool.index.queue_size: -1 # デフォルト 200 threadpool.bulk.queue_size: -1 # デフォルト 50 # threadpool.search.queue_size: -1 # threadpool.get.queue_size: -1
fluent-plugin-forest
same buffer_pathで怒られる件
まぁこれはあたりまえっちゃ当たり前なんですが、理解してないとずっと意味わからん!ってなる
複数タグでbufferに出力しているので違うタグなのに同じバッファへ出力しようとすると怒られるっていうやつですね
たとえばこんな設定にしていると怒られます
type forest subtype file_alternative <template> buffer_chunk_limit 1g path /data/var/log/monitor/${tag_parts[1]}.${tag_parts[3]} buffer_path /var/log/td-agent/${tag_parts[1]}.${tag_parts[3]} flush_interval 1s time_slice_format %Y%m%d </template>
buffer_pathに指定したファイルが違うタグでも複数存在する可能性があるためエラーになります
仮に複数ホストから受け取ったログを集めてファイルとして置いておきたいという要件だった時に
上記設定よりpathで生成されるファイル名は「log.error_log」になります
ここで
二つのサーバからのエラーログを集約する設定をしていたら
集約サーバでの二つのタグのbuffer_pathは「log.error_log」と同一になってしまうのでエラーが起こる
failed to configure sub output file: Other '' plugin already use same buffer_path: type = , buffer_path = /var/log/httpd/monitor.dstat.*
下記のようにパスが被らないように設定してあげる必要があるみたいです
- buffer_path /var/log/td-agent/${tag_parts[1]}.${tag_parts[3]} + buffer_path /var/log/td-agent/${tag_parts[1]}.${tag_parts[2]}.${tag_parts[3]}
パターン分け
この場合は転送、それ以外はこれだけっていうのをうまくひとまとまりでやりたかったんだけど断念
- app.monitor.hostname.dstat
- s3
- file_alternative
- elasticsearch
- growthforecast
- app.backend.hostname.error_log
- app.balancer.hostname.access_log
- s3
- file_alternative
- elasticsearch
下記の設定をひとまとめで<match app.**>
だけで処理したい感じですね
- 現実
<match app.monitor.**> type copy <store> type forest subtype s3 </store> <store> type forest subtype file_alternative </store> <store> type forest subtype elasticsearch </store> </match> <match app.**> type copy <store> type forest subtype growthforecast </store> <store> type forest subtype s3 </store> <store> type forest subtype file_alternative </store> <store> type forest subtype elasticsearch </store> </match>
- 最初試した設定
<match app.**> forest subtype copy <template> <store> type growthforecast </store> <store> type s3 </store> <store> type file_alternative </store> <store> type elasticsearch </store> <template> </match>
そもそもconfigtestが通せなかったので断念
- 次に試した設定
<match app.**> type copy <store> type forest subtype growthforecast </store> <store> type forest subtype s3 </store> <store> type forest subtype file_alternative </store> <store> type forest subtype elasticsearch </store> </match>
growthforecastの部分のtemplateでcase指定してログファイルはgrowthforecastに送信しないというような設定
growthforecastのpathをcaseで指定しないようにしたら怒られる、指定したら送信される、ということで断念
なんかいい方法あったら教えていただきたいです
fluent-plugin-s3
下記全く同じ現象でした
fluent-plugin-s3で、time_slice_format %Y%m%dにしてても、一日に複数ファイルがでてくる件
buffer_chunk_limitに気をつけようねっていうことですね
これは通常のファイルへの出力でもはまるので覚えておいて損はないはず
最初pathにインデックスがあるからダメなんだと思って%{index}を抜いた設定にしたら一度書き込まれてそれ以降何も書き込まれないっていう状況になった
s3の場合は追記ができないのでファイル出力以降はエラーが出てました。
ファイルだけあるの確認してOK!でも実はほとんどバックアップできてなかったなんて落ちになりそうな感じですね。。。