Fluentdでは出力側が詰まると、バッファがたまっていき、ある程度するとバッファが詰まり、今度はそこにForwardしているバッファが詰まり、数珠つなぎにバッファが詰まっていく。大量にたまらないときは出力側が流れ出したら、復帰してくれてとても便利だ。memoryバッファにしておくと、プロセスを再起動しないといけないときに消えちゃうので、fileバッファにするのがいまのところ王道設定である。
しかし、出力先で障害が発生し長引くと、バッファが詰まっていって回復するまでにバッファがあふれてログを取りこぼしてしまったり、いざ回復しても、今度はFluentdからバースト的にログが流れてきてまた詰まってしまったりする。また、出力先が何かの障害でログが失われてしまったとき、復旧する手段がなくて困る。
そこで、Fluentdからいろんな時に出力するときに、一旦ファイルにログを書き出して数週間ためておいて、いつでも復旧できるようにしたい。こうすると、以下のメリットがある。
- 入力側Fluentdと出力側Fluentdのプロセスを分離できる。これによって出力側が障害になっても入力側Fluentdが詰まることはないし、設定更新による再起動もそれぞれ分けて行うことができる。
- 出力先で障害が起こっても、ファイルをfluent-cat等で出力側Fluentdに流し込むだけで簡単に復旧ができる。
- 出力側Fluentdを複数プロセスに分けることができる。
図にすると、次のような感じだ。
単純に入力側Fluentdと出力側Fluentdのプロセスを分けて、fileバッファにしたforwardで受け渡しても良いんだけど、バッファの設定に困るし、出力先障害時の復旧には使うことができない。このために以前はfluent-plugin-tailexを使っていたけど、相当する機能がFluentd v0.10.45で組み込まれた。めでたい。
ということで設定。
出力側Fluentdの設定
出力側Fluentdはtype file_alternative
で適当に出力する感じだ。
<source>
type forward
# ここは適当に
</source>
<match ap.activity>
type file_alternative
path /hoge/log/%Y%m%d/access.log.%Y%m%dT%H%M
buffer_type file
flush_interval 1s
output_data_type json
output_include_time true
output_include_tag false
add_newline true
</match>
入力側Fluentdの設定
入力側はin_tail
で読み込む。ローテートに対応するため、read_from_head
とrotate_wait
を設定しておく。
rotate_wait
はローテートを検出したときに、前のファイルを何秒間読んでくれるかを設定する。1分間に1回ファイルが変わるので60秒にしておけば、1つ前のファイルと現在のファイルを読むようになる。/proc/$PID/fd
をls -al
すれば確認できる。
read_from_head
を有効にすると、ファイルの先頭から読むようになる。これを有効にしておかないと、新しいファイルの0秒付近を取りこぼしてしまう。
refresh_interval
は短めにしておく。長すぎると切り替わりの最初で、30秒分とかのログが出力され、1回のflushごとの量が偏ってしまう。しかし、短すぎると今度はファイルが切り替わるタイミングで、ファイルができる前に切り替わってしまってNo such file or directory
エラーが発生する。このNo such file or directory
は出なくて良いんだけど、どうすればいいかな……
<source>
type tail
path /hoge/log/%Y%m%d/access.log.%Y%m%dT%H%M
pos_file /hoge/log/access.log.pos
tag access.log
format json
time_key time
read_from_head true
rotate_wait 60
refresh_interval 5s
</source>
<match access.log>
...
ここに出力設定を書く
...
</match>
まとめ
こんな感じで、中間ファイルを用いることでより堅牢なログ転送が実現できた。Fluentdを複数プロセス立てるときは、monitで監視してるんだけど、in_multiprocess
を使ってもいいかもしれない。
問題としては、入力側Fluentdがファイルを書き出す前に出力側Fluentdを動かしてしまうと、前述したNo such file or directory
で起動しなくなってしまう。これを無視するオプションあっても良いかもしれない。もしくは、こんなことを実現できるbufferプラグインがあってもいいのかなーとさっき思った。