こんにちは @sonots です。Haikanko OSS化への道と称した Fluentd 連載第六回です。過去の記事はこちら
- Haikanko という FLuentd クラスタ管理ツールの話をしてきた #fluentdcasual
- fluent-plugin-grepcounter をリリースしました 〜 Haikanko OSS化への道(1)
- fluent-agent-lite と fluentd agent の比較 〜 Haikanko OSS化への道(2)
- fluentdを使ったログ監視 ~ Haikanko OSS化への道(3)
- FluentdとGrowthForecastを使った可視化 〜 Haikanko OSS化への道(4)
- fluent-agent-lite と fluentd の keepalive 〜 Haikanko OSS化への道(5)
今回は Haikanko が提供する1つのフィーチャー(SIer 的に言うソリューション!)であるログ収集の機能についてお話したいと思います。
やりたいこと
簡単にいうと syslog-ng の代わりに使いたい。つまり
- アプリサーバのログを転送して、そのままログ保存サーバのファイルシステム(実際はNFSかもしれないし、そうじゃないかもしれない)に保存したい
- ログ保存サーバが1台だと不安なので、レプリケーションしておくりたい
実現方法
fluent-agent-lite を agent として利用する場合は、fluent-agent-lite にはレプリケーションして複数サーバに送る機能はないので、1度別の fluentd ノード (deliver と呼ぶことにします)に送って、deliver で out_copy プラグインを使ってレプリケーションした上で、ログ保存の fluentd ノード (archiverと呼ぶことにします)に送信する形になります。
fluentd を agent として利用すると (便宜上、sender と呼ぶことにします)、out_copy プラグインを利用してログをレプリケーションして複数 archiver に送ることができるようになります。
Haikanko では
deliver ノードを用意するのが面倒だったので、 後者のアプローチを取ることにしました。
アプリサーバのネットワークトラフィックが archiver の数だけ倍になっているので、アプリサーバに負担をかけたくない場合は、前者の fluent-agent-lite の仕組みのほうがよいのかもしれませんが、deliver ノードにトラフィックが集中するのもどうかなぁ、と思ってこうしています。置き換え対象の syslog-ng も後者のアーキテクチャだったので、同じ仕組みなら問題ないだろうという算段もありました。
設定ファイル(sender)
fluent-agent-lite と fluentd agent の比較 で書いた fluentd agent とほとんど同じなのですが、負荷分散の代わりに out_copy を利用してレプリケーションした上で、out_forward プラグインで複数サーバにデータを送信するようにしています。
<source>
type config_expander
<config>
type tail_asis
path /var/log/applog
pos_file /var/tmp/_var_log_applog.pos
asis_key message
tag raw.applog.${hostname}
</config>
</source>
<match **>
type copy
<store>
type forward
flush_interval 1s
<server>
host host1
port 24000
</server>
</store>
<store>
type forward
flush_interval 1s
<server>
host host2
port 24000
</server>
</store>
</match> |
設定ファイル(archiver)
tagomoris 先生のFluentdでログ収集「だけ」やる話 を参考に fluent-plugin-file-alternative を利用して実現しています。fluentd 標準の out_file プラグインだと、タグや時間が付いたり、出力がJSONになってしまったりと(今回のケースでは)余計なものが付いてしまいますが、fluent-plugin-file-alternative を使うと受け取ったログ行だけ出力できます。簡単ですね!
<source>
type forward
port 24000
</source>
<match raw.applog.**>
type file_alternative
path /var/log/applog.%Y%m%d
output_include_time false
output_include_tag false
output_data_type attr:message
add_newline true
compress gz
</match>
|
と思っていたのですが、以下の設定のように、
<source>
type forward
port 24000
</source>
<match raw.applog.**>
type file_alternative
path /var/log/applog.%Y%m%d
output_include_time false
output_include_tag false
output_data_type attr:message
add_newline true
compress gz
</match>
<match raw.applog2.**>
type file_alternative
path /var/log/applog.%Y%m%d
output_include_time false
output_include_tag false
output_data_type attr:message
add_newline true
compress gz
</match>
|
タグは違うけれど(raw.applog と raw.applog2)、保存先の path が同じ、という設定を書いてしまった場合に、
$ ls /var/log/ | grep applog /var/log/applog.yyyymmdd.20130412.b4da171215ae3fdd3.log /var/log/applog.yyyymmdd.20130412.b4da172062a515bb2.log |
のように一時ファイルが2つ作られてしまい、rename の処理でエラーが出たり、最終的に /var/log/applog.20130412.gz と /var/log/applog.20130412.0.gz という2つのファイルに分かれて保存されてしまうといった現象が発生してしまいました。
これはどうも fujiwara 先生のfluentdで複数箇所から同一のファイルに出力するで既知の問題だったようで、そこで解決方法を真似して fluent-plugin-rewrite を利用して、同一のファイル出力する file_alternative 設定は1箇所だけになるように調整しています。
こんなかんじですね。※ タグにパスそのまま入れて動いているんですが、これってアリなんですかね?
<source>
type forward
port 24000
</source>
<match raw.applog.**>
type rewrite
add_prefix /var/log/applog.%Y%m%d
</match>
<match raw.applog2.**>
type rewrite
add_prefix /var/log/applog.%Y%m%d
</match>
<match /var/log/applog.%Y%m%d.raw.**> type file_alternative
path /var/log/applog.%Y%m%d
output_include_time false
output_include_tag false
output_data_type attr:message
add_newline true
compress gz
</match>
|
まとめ
こんなかんじでログ収集ができるようになりました。
Haikanko としては、設定項目から sender と archiver の設定ファイルをループでまわして自動生成してデプロイしているかんじですね。
それでは!