Fluentdを再起動するとバッファファイルが突然全てなくなって困ったのでどうしてそうなったのか調べてみた。
Fluentdのバッファファイル
バッファファイルというのはBufferedOutputプラグインでbuffer_type file
を指定してbuffer_path
にできるファイルのこと。ここにプラグインで使うデータが保存されているので、Fluentdを止めても次回起動時に再送が行われる。
問題
例としてout_forwardを使うと以下の設定のようにbuffer/foo.bar.baz
にバッファを保存するようにしていた。
<match test>
type forward
buffer_type file
buffer_path buffer/foo.bar.baz
...
</match>
この設定で処理が追いつかずにキューが溜まっていくとバッファファイルが以下のように溜まっていく
$ ls -1 buffer/
foo.bar.baz.test.b50b56bd280da5547.log
foo.bar.baz.test.q50b56bb78fd8ea6c.log
foo.bar.baz.test.q50b56bb9d0c2643f.log
バッファが残った状態でFluentdを再起動してしばらく待つと、以下のようなエラーがでていた。
2014-12-29 17:35:09 +0900 [error]: fluent/output.rb:155:rescue in run: error on output thread error="No such file or directory @ sys_fail2 - (buffer/foo.bar.baz.test.b50b56bd280da5547.log, buffer/foo.bar.baz.test.q50b56bd280da5547.log)"
バッファファイルが無いというエラー。そんなわけがないと思いつつバッファファイルが保存されているディレクトリを見ると全てなくなっていた。
原因
実際に使っていた設定は以下のようになっていて、forwardの前に別のBufferedOutputプラグインを設定していた。
<match other>
type exec
command cat
buffer_path buffer/foo.bar
...
</match>
<match test>
type forward
buffer_type file
buffer_path buffer/foo.bar.baz
...
</match>
ここで問題なのはbuffer_pathが前方一致するようなパスになっていること(実際にはもう少し細かい条件がありますが)。このような設定になっていると、test
のバッファファイルがother
の方のバッファファイルとしても扱われてしまうため、other側の方で処理が終わるとバッファファイルが削除されてしまいます。
処理の流れとしては以下のようになります。
- Fluentdを再起動
-
other
がbuffer/foo.bar.*.log
にマッチするファイルをバッファファイルとして登録 -
test
がbuffer/foo.bar.baz.*.log
にマッチするファイルをバッファファイルとして登録 -
other
のプラグインが先に実行され、バッファファイルを削除する -
test
を実行しようとするとバッファファイルが無いのでエラー
対応策
対応方法としてはいくつかあります。
- buffer_pathが前方一致しないように注意する(例:
foo.buffer
,foo.bar.buffer
- パスの末尾を統一する
- buffer_pathに
.
(dot)を使わない(例:foo_bar
,foo_bar_baz
)
buffer_pathに*
を使った場合は生成されるパスが異なるので上記の対応だけではうまくいきません。おそらく部分文字列にならないように注意しないといけない気がします(要確認)。
どちらにせよBufferedOutputでNo such file or directoryが出ているようならロストしている可能性が高いので注意して下さい。