Kibana4 + dstat の話
あらまし
以前に、『dstatをkibanaで可視化+3.0.0milestone5新機能』という エントリでKibana3+dstatを使った可視化について書いたのですが、この中で構築の肝としてfluent-plugin-mapがありました。 Kibana3だと同一グラフ内に同一レコードの複数のfieldを含めることが出来なかったので、 fluent-plugin-mapを使って同一@timestamp+各fieldという別々のレコードとして分割登録しました。 このやり方は@kazeburoさんも記事にされたことにより 同様の方法を利用する人が意外といるようなのですが、 Kibana4では同一グラフ内に同一レコードの複数fieldを含めることが出来るのでレコード分割する必要がありません。 性能はわかりませんがdocument数や容量は分割する場合と比べると減ると思います。 ただしfluent-plugin-dstatはネストしたjsonを返すので平らにしてあげる必要があってfluent-plugin-flatten-hashを使います。
設定とか
fluentdの設定は以下。
<source> @type dstat tag dstat option -ams delay 5 </source> <match dstat> @type flatten_hash add_tag_prefix flattened. separator _ </match> <match flattened.dstat> @type elasticsearch type_name dstat host localhost port 9200 logstash_format true logstash_prefix dstat flush_interval 3s </match
それからMapping template
$ vi template_dstat.json { "template": "dstat-*", "mappings": { "dstat": { "properties": { "@timestamp" : { "type" : "date", "format" : "dateOptionalTime" }, "dstat_dsk/total_read" : { "type" : "double" }, "dstat_dsk/total_writ" : { "type" : "double" }, "dstat_memory_usage_buff" : { "type" : "double" }, "dstat_memory_usage_cach" : { "type" : "double" }, "dstat_memory_usage_free" : { "type" : "double" }, "dstat_memory_usage_used" : { "type" : "double" }, "dstat_net/total_recv" : { "type" : "double" }, "dstat_net/total_send" : { "type" : "double" }, "dstat_paging_in" : { "type" : "double" }, "dstat_paging_out" : { "type" : "double" }, "dstat_swap_free" : { "type" : "double" }, "dstat_swap_used" : { "type" : "double" }, "dstat_system_csw" : { "type" : "double" }, "dstat_system_int" : { "type" : "double" }, "dstat_total_cpu_usage_hiq" : { "type" : "double" }, "dstat_total_cpu_usage_idl" : { "type" : "double" }, "dstat_total_cpu_usage_siq" : { "type" : "double" }, "dstat_total_cpu_usage_sys" : { "type" : "double" }, "dstat_total_cpu_usage_usr" : { "type" : "double" }, "dstat_total_cpu_usage_wai" : { "type" : "double" }, "hostname" : { "type" : "string", "index" : "not_analyzed" } } } } } $ curl -XPUT 'localhost:9200/_template/tmptelate_dstat' -d @template_dstat.json
templateは特定のパスに置いておくと自動的に読まれるのですが、
再起動が必要になるので最近はtemplate APIを呼ぶようにしてます。
変更結果を確認もできますし。
(既存のindex mappingが即時変更されるわけではありません)
mappingでなくfluent-plugin-typecastを使って先に型を定義してしまう方法もあります。
私はmappingでdoc_valuesやStringにnot_analyzedを設定することが多いのでElasticsearchでは共通的にmapping作成するようにしてます。
mappingを作るにはまず一旦設定なしでデータを入れてみてできたmappingを見て変更するとわりと簡単にできます。
curl localhost:9200/<index>?pretty
Kibana4の設定
Visualize Line chartの設定画面です。
add metricsでY軸を複数設定できます。
複数表示できましたね。
cpuやmemory, swapはArea chartの方がいいかもしれませんね。
設定方法は一緒です。
Vertical bar chartなんてのも。
レコード分割せずに複数のfieldを同一グラフに表示できました。
結論
dstat + fluentd + kibana4(Elasticsearh)ではレコード分割する必要がない。
(ただし構成上の話で性能はわかりません)
sample
github.com ansible-hands-onを再利用して構築検証用Vagrantfile作りました。
番外
grafana + influxdbの場合はレコード分割が必要(?自力では調べてない)なので その場合はwinebarrelさんの記事を参考にするといいと思います。
dstatをkibanaで可視化+3.0.0milestone5新機能
開発中の負荷試験をモニタリングしたくてdstat+Kibanaで組んでみました。
通常モニタリングは専用のツール(muninとか)で行うと思いますが、
今回はfluentdとKibanaの組み合わせにdstatを絡めてみます。
監視対象にはdstatとtd-agent、fluent-plugin-dstatを入れます。
インストール方法や細かい設定は割愛。
今回はdstat -ams 5
相当を実施する設定とします。
fluent-plugin-dstatが出力する内容(1レコード)は以下になります。
2014-02-12T07:25:18+00:00 dstat { "hostname":"large0000.example.com", "dstat":{ "total cpu usage":{"usr":"0.400","sys":"0.500","idl":"99.0","wai":"0.100","hiq":"0.0","siq":"0.0"}, "dsk/total":{"read":"0.0","writ":"18022.400"}, "net/total":{"recv":"8389.600","send":"192767.200"}, "paging":{"in":"0.0","out":"0.0"}, "system":{"int":"170.200","csw":"119.600"}, "memory usage":{"used":"562212864.0","buff":"394461184.0","cach":"6345080832.0","free":"510849024.0"}, "swap":{"used":"0.0","free":"0.0"} } }
改行は私が適宜入れてるので本来1行です。
dstat pluginはhostnameというパラメータを追加してくれるので
fluentdのタグを駆使してデータに格納したりする必要が無いです、便利。
3段目の"dstat"以下が実際にdstatで出力される内容に相当します。
モニタリング可視サーバ側にはtd-agentとElasticsearch、Kibanaを入れます。
使用したfluent-pluginはmap、elasticsearchです。
fluentdの設定は以下、
<source> type forward </source> <match dstat> type copy <store> type map tag "map.dstat.cpu-usr" time time record {"value" => record["dstat"]["total cpu usage"]["usr"], "stat" => "cpu-usr", "hostname" => record["hostname"]} </store> <store> type map tag "map.dstat.dsk-read" time time record {"value" => record["dstat"]["dsk/total"]["read"], "stat" => "dsk-read", "hostname" => record["hostname"]} </store> </match> <match map.dstat.*> type elasticsearch type_name dstat host localhost port 9200 logstash_format true logstash_prefix dstat flush_interval 3s </match>
ここで重要なのはmapの部分になります。
"total cpu usage"とか"memory usage"のような同じグループの内容を同一グラフに表示したくなると思いますが、
dstatの結果を1レコードのまま格納してしまうとkibanaでは複合グラフにできません。
そこで1レコードをパラメータ数分だけ分割して同時刻の複数レコードに変換しています。
timestamp hostname:host a:1 b:2 c:3
↓
timestamp hostname:host stat:a value:1
timestamp hostname:host stat:b value:2
timestamp hostname:host stat:c value:3
前述のfluentの設定はサンプルなのでmap2つしか書いてませんが、
実際にはElasticsearchに取り込みたいパラメータ分copyしてmapを書く必要があります。
今回のdstat設定であれば20パラメータですね。
map pluginにはmultiという1行で複数レコード作れる設定方法もあるのですが、
折り返して書くことが出来ず1行が長くなるので敢えてパラメータ毎に分けてます。
recordディレクティブを複数書くことが出来たらなーと思ったりはする。
これで準備は整いました。
ここからはKibanaの説明に移るのですが、
つい先日、Elasticsearchの1.0.0と併せてKibanaも3.0.0milestone5になっていますので、
一部、新機能の説明もしてみようと思います。
ではKibanaの画面を見てみます。
Histogramでvalueフィールドの平均値を表示しています。
"total cpu usage"と"memory usage"をそれぞれ1つのグラフにしてみました。
Elasticsearchには複数hostのdstatのデータを登録してあるのですが、
上記のグラフでは実は1台分だけにフィルタリングしてあります。
自在にフィルタリングを作成する機能もmilestone5の新機能です。
"FILTERING"一覧の右に出ている+を押すと、
こんな感じで入力画面が出るので、1台を特定可能なqueryを指定しています。
ここまでは1台のリソースを詳細にモニタリングしたい場合でした。
でも複数台を同時に見たい場合も当然ありますよね。
そこでmileston5の新機能であるtopN
を使います。
query窓の●の部分をクリックして表示される画面で最初の選択肢をluceneからtopNに変更。
Fieldの所に組み合わせたいパラメータを入れます。今回はhostnameを指定。
Countは上位何個を表示したいかです。
hostname毎にグラフが描画されました。
指定fieldをterms facetした結果を掛け合わせてグラフを作ってくれます。
並び順を変えたり表示する対象を細かく指定したりは難しいのですが、
非常に使い道がある機能です。
例えば「アクセスを国別に」とか、「売り上げを製品毎に」とかしたいときに、
わざわざqueryで1国ずつ、1製品ずつ入力しなくても良くなるわけです。
新しい機能でsparklines
というのがあります。
query設定はHistogramの時と一緒(topN併用)です。
複数のものを形(要するに傾向)でざっと見たい場合に便利。
例えば前出のHistogramではsmall0001-0003はたいした負荷じゃないために
0付近でつぶれてしまっているのですが、
実際には何となく変動していることが見えたりします。(形が他と異なる3つ)
サービスを跨いだアクセス数とか、異なるインスタンスサイズのメモリ動向とかを
まとめて表示して傾向の変化を判断するのに使えると思います。
詳細はもっと別のグラフで見としても、対象数が増えてきた時に便利そう。
もう一つ、新しい機能terms_stats
mode
terms facetをcountだけじゃなくてaggregationvalueとれるようにしたもの?
設定は色々できそうなんですがまだ把握してないので1例だけ。
色々な量を項目別に比較できます。
モニタリングというよりはデータ解析向きかも。
他にもまだ機能があったり細かく色々進化していたりしますが、今回はこんなところで。
もっと役立つユースケースとか出せるといいのですが、
まだ全然使いこなせてませんね。修行が足りない・・・
第3回elasticsearch勉強会 [2014/02/07(Fri.)]に参加してきました
http://elasticsearch.doorkeeper.jp/events/7491
メモって即UP満々な気で行って英語で挫折して何もメモらなかったので、
記憶を頼りに感想を書きます。
①「Geohashing with Elasticsearch」Florian Schilling, Elasticsearch Inc,
GeoHashという単語を始めて知ったほどに情弱でしたが、
場所検索をどうやって行っているか、ということは何となくわかったような。
マイクトラブルはありましたが楽しく話してもらえたので
また何か話に来てもらえるといいですね。
どれだけ聞き取れたか、、、という意味では皆無に近いかも。
②「AWSで構築するsharding」株式会社イプロス 外山 寛さん @toyama0919
http://toyama0919.bitbucket.org/elasticsearch.html#/
実際にProductionで使ってみて、という話。
相野谷さんもですが、AWS上での事例が出てくるのありがたいですね。
ec2pluginを使えば簡単とのこと。
Indexingにlogstash formatを使うかどうかという議論があって、
routingの特性も含めてIndexは1つにした方が良いのでは?という話でした。
データは100GBということでしたが、データ量がもっと多くなった場合にどうなるかですね。
pixivさんのsolrの事例で高速化のためにIndex分割する話があったので、
いずれ再Indexing必要になるのなら最初はlogstash formatで
後で適宜統合、、とか妄想したけど私は検索扱った事無いので妄想止まり
③「テスト駆動検索のススメ」株式会社じげん 多田 雅斗さん @tady_jp
検索でもTDDしような話
検索の仕様を最初からちゃんと設計できるのか?みたいなのもありますが、
仕様変わったら再Indexingになる可能性を考えても、
少なくとも現状を明示して検証できるのは非常に有効そうです。
検索も色々種類あるんだなーってわかって面白かったです。
④「MySQLユーザ視点での、小さく始めるElasticsearch」株式会社リブセンス 吉田 健太郎さん @yoshi_ken
MySQLからElasticsearchにデータレプリケーションするYamabiko中心の話。
検索用なんかでデータを入れるときに、
最初から分岐して平行で入れてる(絵がそうだけかもしれないが)例をよく見る気がするけど、
YamabikoだとMySQLに入った結果から連携する形になるので、
運用面でどういう違いがあるのかなーとか思ったり。
思っただけどまり。
単純にサービスにもよるのかもしれないですが。
⑤「nodeJS+DynamoDB+Elasticsearchで全社基盤を作った話」株式会社リクルートテクノロジーズ 相野谷 直樹さん @naokiainoya
スマホアプリに各種条件でPUSH通知するための全社基盤を作った話。
条件検索でPUSH対象のデバイスを一覧で返す。使い方が割りと独特。
ただこれってGeoHash検索に通じるような所が実はある気がする。
スキーマレスな部分を多様な条件登録に使っているということでした。
いろんな種類のユーザを全社共通でもっているリクルートさんならでは。
scanというAPIは正直知らなかった情弱です。
MultiAZでAutoScalingしているってのは興味深いです。
メインはあくまでDynamoなのでということでしたが、
今後、障害対策や運用系の知見が出てくるといいなぁと思いました。
あとキュー使うのもポイントなのかなーと思ったりも。
自分はKibanaとしてしか使ってないので今回はかなり検索メインでしたが、
クラスタ運用面なんかは実例が多数出てくると参考になりますね。
第4回は4/21だそうです。
Kibana向けFluentd設定例①アクセスログ可視化
どちらかというとFluentdの設定の話なのですが、
Kibana上でデータを扱うことも考慮して、くらいの感じで。
アクセスログの可視化はよくあるやつなので細かい所は飛ばします。
1段目:ログ収集先からの転送設定
<source> type tail path /path/to/apache_access.log format /(?<message>.*)/ pos_file /var/log/td-agent/apache_access.pos tag apache.access.HOSTNAME </source> <match **> type forward flush_interval 1s <server> host FORWARD_HOST </server> </match>
以前の記事ではin_tail
にパースを書いていましたが、
パラメータが増減するのに毎回対応したり、パースするための負荷がかかることを考えると、
ログ収集ホスト上のin_tail
で正規表現をゴリゴリ書くのはあまり得策じゃない気がしています。
そこで1行を1メッセージとして送るような設定にしています。
fluentdが0.10.39以降であればformat none
とすることで同様のことが出来ます。
収集ログに日付が付与する場合はin_tail
の変わりにfluent-plugin-tail-ex
を使うといいですね。
2段目:ログ受信側パース
<source> type forward </source> <match apache.access.**> type parser add_prefix parsed format /(正規表現)/ time_format %d/%b/%Y:%H:%M:%S %z key_name message </match>
ここからはログ解析サーバ上です。
forwardされたイベントをfluent-plugin-parser
でパースします。
key_name
には解析したいフィールド名、ここではmessageになります。
format
には正規表現を書きますが、ログフォーマット側でLTSV
にしておけば
format ltsv
するだけでよくて楽ですね。
3段目:データ加工
<match parsed.apache.access.**> type record_reformer output_tag reformed.${tags[1]}.${tags[2]} ip ${forwardedfor[/([^,]*),*/,1]} method ${req[/^([^ ]*) .*$/,1]} uri ${req[/^[^ ]* ([^ ]*) .*$/,1]} sessionId ${req[/^[^ ]* \/path\/to\/api\?sessinId\=(.*?)(\¶m\=[^ ]*)? .*$/,1]} log_host ${tags[3]} </match>
2段目の時点で生のデータを扱う分には十分なのですが、
時にはデータ加工したい場合があり、fluent-plugin-record-reformer
が便利です。
整形したデータを生のレコードに+αしてくれるのが良いです。
しかも複数項目書けます。
例えば「req (referer情報)」に「GET /path/to/api?sessionId=10000001¶m=1 HTTP/1.0」
という情報が入っているとして、1つ目をmethod、2つ目の部分をuriとして取り出しています。
あるいはuri全体ではなく、getパラメータに入っているsessionIdを取り出したりします。
またforwardedforにはproxyを通すとカンマ区切りで複数のアドレスが入っているので、
1番先頭だけを取り出して続くgeoipの判定に使います。
整形は${フィールド名[/(正規表現)/,n]}
のように書いて取り出したい部分をグループ化して
nで何番目のグループを取り出したいかを指定します。
この辺りはrubyの正規表現のとり扱いになるので、
rubyのコンソールとかで少し試してみればすぐわかると思います。
log_hostは以前の記事でfluent-plugin-elasticsearch
上でtag_key @log_name
で行っていた
収集元ホストの登録をここで行うように変更したものです。
fluent-plugin-elasticsearch
のtag_key
だとtagをかなりうまいこと編集する必要がありましたが、
tags
使うと簡単に必要な部分だけ取り出せますね。
${tags[3]}
はtagをカンマで分割した4番目を取得しています。
なお、fluent-plugin-record-reformer 0.1.1
からはfluent-plugin-forest
と表記を合わせて
tag_parts
が使えるようになります。
今回の記事のポイントはほぼ3段目に集約されます。
methodやuriはログフォーマットで直接指定すれば加工しなくても済みますが、
既に運用されているような場合に出力元に変更を加えるのが簡単じゃない場合も多いし、
そういう場合に受け取った先で簡単に加工できるという例です。
4段目:
<match reformed.**> type geoip geoip_lookup_key ip enable_key_country_code geoip_country add_tag_prefix es. </match>
fluent-plugin-geoip
用の設定。
pluginとは別にライブラリのインストールが必要なので注意してください。
ここまで見てきてplugin毎にtagの扱い方が異なるので若干混乱しますね。
5段目:
<match es.reformed.**> type forest subtype elasticsearch remove_prefix es.reformed <template> type_name ${tag} host localhost port 9200 logstash_format true logstash_prefix logstash flush_interval 10s </template> </match>
fluent-plugin-elasticsearch
はplaceholderに対応してないのでfluent-plugin-forest
推奨。
fluent-plugin-record-reformer
でのoutput_tag
との組み合わせにより
type_name
に入る値は今回の例では「apache.access」となります。
以前はtype_name、host名なんかを登録するのにtag操作が結構大変でしたが、
tagのplaceholderが便利になったお陰でかなり楽になりました。
fluentdではこんな感じでログ出力をいい感じに加工してデータストアに投入できます。
Kibana関係ないじゃないかって言われそうですが、Kibanaで表示する内容を考えた結果、
fluent-plugin-record-reformer
で途中で加工するのが便利っていう話です。
Kibanaで解析するときにユーザIDやセッションIDみたいなのをfacet集計したい事例はよくあると思うので、
切り出しておいてmappingをnot_analyzed
で用意するとランキング集計しやすいですね。
Kibana上ではterms
パネルで対象項目を指定するだけで表示できます。
デフォルトで5項目になってるけど数字を増やせばもっと表示可能。
(1000くらいにはしたことある)
参考例。本当はもっとランキングぽいの出したかったけど手元に出せるデータがなく。
3つ例を書くつもりだったけど、調査修正して動確してたらハマって時間かかってしまった。
record_reformerは前に設定書いた時点ではtag_parts
使えてたんだけど、
手元で実施したら0.1.1ではなく0.1.0が入ってしまって使えなかったり、
Elasticsearch-1.0.0.Beta2を使ったら0.90.7で動いてたmapping templateが動かなかった。
記事は書いたものの色々と調査するものが増えてしまった・・・
fluentd-plugin-elasticsearchでのログ時刻の扱い
これまでの自分のElasticsearch関連の記事では"request_time"という
独自に定義したラベルを用いて登録を行っていました。
一方、fluentdは"time"というラベルを用いるとログの時刻をfluentd内で扱うイベントタイムとみなします。
"time"とした場合と、それ以外でfluentd-plugin-elasticsearchの動作に
違いが見られたのでメモしておきます。
ところで"request_time"としたのには理由があったのですが、
その理由は本筋ではないので最後に書くことにします。
①ログ時刻を通常のラベルを用いて登録する場合
この場合はラベル名を"time"以外にしてパースします。
つまりこれまでの場合は"request_time"としていました。
この時点では他の項目と同じJSON(MessagePack)の一項目なので文字列です。
そしてそのラベルに対してElasticsearchのフィールドを日付型としてMappingをします。
これによりElasticsearch内で"request_time"は日付型フィールドとして扱われるようになりました。
後はこの"request_time"フィールドをKibana3でtime fieldとして設定します。
例えばtimepickerの設定画面では以下になります。
index作成にlogstash形式を指定していた場合(logstash_format true)
logstash形式indexの日付はログをimportしたfluentdで読み込んだ日付になります。
ところで上記画像のtime fieldにはデフォルトでは"@timestamp"が設定されています。
@timestampフィールドはどうやったら使えるのでしょうか?
②fluentdで"time"ラベルを使う
その答えはfluentdの"time"ラベルにありました。
fluentdのパースを以下のように設定したとします。
format /^(?<host>[^ ]*) [^ ]* (?<user>[^ ]*) \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>[^ ]*) +\S*)?" (?<code>[^ ]*) (?<size>[^ ]*)(?: "(?<referer>[^\"]*)" "(?<agent>[^\"]*)")?$/ time_format %d/%b/%Y:%H:%M:%S %z
この場合、記事の冒頭でも書きましたがログ時刻はfluentdのイベントタイムとして扱われます。
詳しくは書きませんがJSONボディ部とは異なる扱いになります。
そしてfluentd-plugin-elasticsearchでlogstash形式に設定すると、
"time"が"@timestamp"フィールドに登録されます。
更にこの場合、logstash形式index名もログ日付に追随します。
つまり、ログ日付と同じ日付でlostash-YYYY.MM.DDなindexが作成されます。
fluentdのパースの時点でちゃんと設定しておけば、
自動的にログの内容にあった登録がされるということですね。
なお、logstash形式ではなく自分でindex名を指定した場合は
"@timestamp"フィールドは出来ませんでした。
ただ以前に試した時はログ登録時刻で設定されてた気もするのでココは怪しいです。
(追記)確認しました。logstash_format trueなら@timestampフィールドが作られるが、
そうでない場合は@timestampフィールドは作られない、です。
それから、なぜ最初から"time"を使わず"request_time"にしてたのかですが、
fluentdの正規表現を書くのに@tagomorisさんのサイトを参考にテストしていたのですが、
「require 'time'」を見落として設定してなかったばっかりに
いくらやっても"time"としてパースするのに失敗したので
諦めて文字列なフィールドとして取得するようにしちゃったというオチでした。
間抜けすぎてどうしようもないですね。。。
Elasticsearchを触ってみた話の続き
「Kibana3+Elasticsearchを触ってみた話」の続き。
前回は設定周り飛ばしたのでその辺とか書くつもりだったのですが、
分割して色々書いたのでまとめっぽい。
・環境
Vagrant+VirtualBox+Ubuntu12.04で試して
1週間くらい前からテスト環境のAWS上で動いている。
ものすごく残念なことにSmallだけど。性能の話はしない!
・インストール
こちらの方を参考にしました、でフィニッシュです。
debやrpmのパッケージも既に用意されているようですね。
最近色んな人が記事あげてるのですぐ見つかると思います。
・Plugin×Proxy
各種Proxy設定頑張ってもダメで、たしかエラーからはgit://~とか見えたので
gitにProxy設定かとgit config --systemとか適当にやってダメだと思ってたら、
大谷さんが割りと最近に書いてた。大層捗りました。
とりあえずheadとbigdeskは入れておいたらいいと思います。
headは生データ見れるしindexもシャードも視覚確認できるし、
右クリメニューからindex削除とかmapping確認出来ちゃう、素敵plugin
元から同梱でもいいのではないだろうか。
(簡単に記事書きました。「Elasticsearchのhead plugin」)
bigdeskはLoadAverageとかMemory使用量とかそういうの表示するやつですね。
JVMの中を監視するのは何かしら必要なので入れておきましょう。
その他、超大量のplugin一覧はこちら
・データを入れる前に
インストールして動いたら次は本体設定をします。
クラスタ周りとか色々な設定ありますが今のところデフォルトのまま。
mappingはtemplatesで設定しました。「Elasticsearchにmappingをtemplate設定してみた」
indexの話も少し書きました。「Elasticsearchのlogstash形式indexについて」
・データを入れる
リアルタイムに入れる場合、fluentd大先生にお願いしてフィニッシュです。
簡単に説明しました。「Elasticsearchにfluentdする設定とかlabelの話」
リアルタイムじゃない場合はbulk_importとかあるのですが、
データの整形がめんどうだったのでこれもfluentdしました。
・画面の設定周りとか
Kibana3はわりと感覚的に使えます。
大谷さんのブログ見ると更にわかりやすいです。
あと、y_310さんのブログのQuery制御周りは非常にためになりました。
・monit入れた話
Vagrant+Virtualboxで検証してる時に過去ログをfluentd経由で入れたら
結構な頻度でElasticsearchが落ちました。
bin/elasticsearch -fしてると画面上にkilledとか表示されて落ちます。
これは今思うとvagrantfileにMemory割り当てしてなかったのと、
過去ログをファイル単位でそのまま投入したので、
投入した瞬間に大量のログが流れ込んだせいだと思うのですが、
AWS上で起こると怖いのでmonitを入れて自動再起動するようにしました。
最初はsupervisordにしようと思ったのですが、
bin/elasticsearchは実は内部はただのシェルだったので、
supervisordの仕組み(プロセスをforkする?)ではうまく監視できずmonit(PID制御)にしました。
この辺は自分は詳しくないし小一時間程度の調査しかしてないのでやり方はあるのかも。
とりあえず数日頑張ったKibana3+Elasticsearchの記事は一通り。
書いてる間にも色んな人が書いてて今更感漂ったけどやりきった。
自分は触りだしてから1週間とかそこらしかたってないので
そういった面から見ても非常に使いやすいツール群だなと思います。
Elasticsearchにfluentdする設定とかlabelの話
といっても設定はさほど難しくないです。
収集箇所から直接送信する場合はコチラを参照するとよさそうな感じ。
自分の場合、収集箇所と集計サーバ両方にtd-agent入れてて、
収集箇所はtail_exとforward、集計サーバで集計してgrowthforecastに投げてたり、
今回の場合、後からElasticsearch設定追加したりしてます。
本番でgrowthforecastとElasticsearchを同じサーバに入れないと思うけど、
今はテスト環境ということで。
以下は送信側設定。
<source> type tail_ex format /(正規表現)/ path /path/to/apache.log.%Y%m%d tag apache.${HOSTNAME} pos_file /path/to/apache.pos </source> <match apache.*> type forward flush_interval 1s <server> host ${FORWARD_HOST} </server> </match>
送信側はなんてことはない設定なんですが、ポイントはtagのHOSTNAMEなのかなと。
Elasticsearch内でhost毎に検索したい場合はtagからlog_nameに入れるか、
record-modifierで項目の一つとして入れてしまうかどっちかになると思います。
集計サーバみたいな構成の場合、tagについてるとmatchで対象を制御もできるのでよさげ。
なお、${HOSTNAME}と${FORWARD_HOST}はシェルとかChefで埋めてます。
tail_exの機能?で${hostname}ってtagに使えるのですが、
加工したhost名を使いたかったので設定時に埋めるようにしました。
集計サーバ側の設定は以下。
<source> type forward </source> <match apache.**> type copy <store> type forest subtype elasticsearch remove_prefix apache <template> type_name apache include_tag_key true tag_key @log_name host localhost port 9200 logstash_format true flush_interval 10s </template> </store> </match>
実際にはstoreもっとあるけど、Elasticsearchに関係ないところは省略しました。
転送元からはtagが「apache.host」の形で流れてきて、
remove_prefixされて@log_nameには「host」の形で登録されます。
これによりElasticsearch上で「@log_name="host"」な検索ができます。
まぁ、ここまでしなくてもElasticsearchは全文検索エンジンなので、
「apache.host」のままで登録されても「@log_name="host"」で絞り込み出来るはず。
こんな感じでfluentdで簡単にElasticsearchにデータ投入できます。
Elasticsearchにはbulk_importする方法も用意されているのですが、
JSONでindex指定やid付与した形に整形必要だったこともありやってません。
過去ログでもfluentd経由で入れてます。fluentd便利!
あとfluentd-plugin-elasticsearch書いてくれた人のおかげ。
ところで、Elasticsearchに関するブログ記事書いてる途中に気づいたんですけど、
自分のlabel名があまり標準的ではないものになってる気がする。
元々はfluentd公式のapache2の書式をベースに正規表現を書いてます。
(http://docs.fluentd.org/ja/articles/in_tail の中ほどの「apache2」)
それに対して追加パラメータの一部の項目名が似たようなのがあった部分を装飾したり、
timeのパースをうまくいかないと誤解したためにrequest_timeにしたり。
ところが最近LTSVお勧めというのがあることを知りました。
比較してみますと、
apache2でのlog_format | 自分のlabel | fluentdサイトのlabel | ltsv.orgのrecommended label |
---|---|---|---|
%t | request_time | time | time |
%>s | code | code | status |
%b | res_size | size | size |
%{User-agent}i | agent | agent | ua |
%l | req_size | - | reqsize |
%D | response_time | - | reqtime_microsec |
%T | - | - | reqtime |
特にrequest_timeが違う用途なのに被ってるのが泣きそう。
といっても急に変えられないのでスキーマの設定は気をつけましょう、
という残念なオチ。
私のElasticsearchの記事を見る際にはパラメータにはご注意を、、、