複数のクライアントから一つのサーバーにログを集める事をしていたのですが、hostnameを入れておかないと後で『どこの鯖のログだこれ?(^q^』となってしまうので。
なお、今回初めてfluentd(というかtd-agentを)触りましたw
とりあえず、初心者らしく
td-agentはバージョン 1.1.19を利用しています。
なお、この項はhostnameを入れる件とは関係ないので、hostnameを入れる部分を読みたい方は、ページ中段の「hostnameを入れる」の項を参照してください。
インストール等々、以下のサイトが分かりやすかったです。
fluentd(td-agent) の導入
td-agent?
Fluentdは拡張しやすいようRubyで実装され、一部の性能に直結する部分はC言語で実装されています。
しかしライトユーザーにとってRubyのデーモンをインストールし運用することは難しい場合があります。
どんなプラグインをインストール済みなのか見たい時
基本的にgemでインストールしていくスタイルのようなので以下を見ると良いっぽいですね。
ls /usr/lib64/fluent/ruby/lib/ruby/gems/1.9.1/gems/
その他irbやrubyコマンドも以下のパスにあるので、既にインストール済みのrubyのバージョン等に影響が出なくて良いですね。
ls /usr/lib64/fluent/ruby/bin/
例えばプラグインを追加したい時は?
素でgemを叩くと既存のやつに影響が出たりして嫌なので、先程見たところにインストールされるようにしたい
$ sudo /usr/lib64/fluent/ruby/bin/fluent-gem install fluent-plugin-forest --no-rdoc --no-ri
以上で、先程のところにインストールされるようです
$ ls /usr/lib64/fluent/ruby/lib/ruby/gems/1.9.1/gems | grep forest
fluent-plugin-forest-0.2.4
hostnameを入れる
ここから本題です。
設定
今回はrecord-reformerを利用してみました。
<source>
type tail
format ltsv
path /var/log/httpd/access_log
pos_file /var/log/td-agent/access_log.pos
tag development.access_log.addHostname
</source>
<match **.addHostname.**>
type record_reformer
renew_record false
enable_ruby true
output_tag ${(tag_parts - ["addHostname"]).join(".")}
<record>
hostname ${hostname}
</record>
</match>
<match development.access_log>
type forward
flush_interval 5s
buffer_type file
buffer_path /var/log/td-agent/buffer/access_log
<server>
host logserver.example.com
port 24224
</server>
</match>
- 以上で、以下のようになります。
- tagのどこかに"addHostname"がある場合、レコードにhostnameを記録する
- 記録後tagから"addHostname"を削除して、次のmatchへ行く
- 今回の場合、サーバーへ送るmatchに拾われる
ltsvフォーマットにしている部分等は不要ですが・・・ご愛嬌でw
サーバーに送るmatchをまとめたい
上記のようにhostnameが入るようになったところで、思いました。
『全部のログをlogserver.example.comに送るのに、ログファイル毎にmatch書くの・・・?(=w=;』
以下のような感じに出来ないの?
<match **>
type forward
flush_interval 5s
buffer_type file
buffer_path /var/log/td-agent/buffer/${tag}
<server>
host logserver.example.com
port 24224
</server>
</match>
しかし、単純にコレだけだと・・・サーバーに送りたくないものがあったとしても送られてしまいます。
送られた側でほっとくという手もあるかもしれませんが、hostnameを追加した子だけ送信したい気がします。
設定
今回はforestを利用してみました
- 似たような設定をまとめたりcaseを利用して設定の上書きが出来るプラグインのようです
<source>
type tail
format ltsv
path /var/log/httpd/access_log
pos_file /var/log/td-agent/access_log.pos
tag development.access_log.addHostname
</source>
<match **.addHostname.**>
type record_reformer
renew_record false
enable_ruby true
output_tag ${(["sendLogServer"] + tag_parts - ["addHostname"]).join(".")}
<record>
hostname ${hostname}
</record>
</match>
<match sendLogServer.**>
type forest
subtype forward
remove_prefix sendLogServer
output_tag ${tag}
<template>
flush_interval 5s
buffer_type file
buffer_path /var/log/td-agent/buffer/${tag}
<server>
host logserver.example.com
port 24224
</server>
</template>
</match>
- 以上で、以下のようになります。
- tagのどこかに"addHostname"がある場合、レコードにhostnameを記録する
- 記録後tagから"addHostname"を削除して"sendLogServer"を追加し、次のmatchへ行く
- サーバーへ送るmatchに拾われ、タグから"sendLogServer"を外してサーバーに送る
こうしておけば、"addHostname"がタグにあった子は勝手にサーバーに送られます。
本当にtagの編集だけなら、forestじゃなくて違うpluginの方が良いと思います。
今回の例だと、tagの編集だけではあるのですが・・・(=w=
おまけ:サーバー側の例
こんな感じですかね?
<source>
type forward
port 24224
</source>
<match **>
type forest
subtype file
<template>
path /var/log/gathered/${tag}
time_slice_format %Y/%m/%d
flush_interval 12h
buffer_type file
buffer_path /var/log/fluentd/buffer/${tag}
</template>
</match>
あとは、S3に上げたりとか色々と設定を変えてみると良いですね。
まとめ
- record-reformerやforest等、便利なpluginを公開されている方が多数居らっしゃるので、その辺りを探して利用すると色々出来そうです!!
今回触っていて感じたのですが、使っているtd-agentのバージョンの性なのか割と再起動等に弱い印象があります。
複数起動を許可していたりもするので、設定を変えて再起動とかしていると、いつの間にかプロセス自体が増えていて、予期せぬ動作に悩まされます。
再起動毎にプロセスの数と起動時刻を見て、適切にkillをしたりして、少しゆったりとtry&errorをすると良さそうです。
全体的にもっとスマートな記述にしたいですが、自分の習熟度不足のため・・・(=w=;