flunetd、forward先がダメだった時にforward元である程度ログを担保したい

fluentdのbufferとforwardについて調べたのでメモ。

fluentd v0.10.45

追記( 04/02 00:27)

とのことです。

こちらも参照してください。

fluentd の buffer あふれ改善議論 - togetter

flush_intervalはあくまでflushするだけであって
貯まる分は

buffer_chunk_limit x buffer_queue_limit

が影響する。ということですね。

update( 04/02 11:40 )

参考

fluentd - Buffer Plugin Overview
tagomorisのメモ置き場 - FluentdでバッファつきOutputPluginを使うときのデフォルト値

構成

  • 各ホストから集約サーバへfowardしている
  • 集約サーバはログを受け取ってゴニョゴニョしている

Buffer

BasicBuffer
FileBuffer
MemoryBuffer

buffer_chunk_limit

FileBuffer = デフォルト(8MB)
MemoryBuffer = デフォルト(8MB)

buffer_queue_limit

FileBuffer = デフォルト(256)
MemoryBuffer = 64

総バッファサイズ

  • FileBuffer
    = 8 * 256 = 2048(2GB)

  • MemoryBuffer
    = 8 * 64 = 512(512MB)

flush_interval

flush_interval = デフォルト(60s)

Bufferされる値を算出する

fluentd - Buffer Plugin Overview

When the top chunk exceeds the specified size or time limit
(buffer_chunk_limit and flush_interval, respectively),
a new empty chunk is pushed to the top of the queue.
The bottom chunk is written out immediately when new chunk is pushed.

例えば

<match **>
  type forward
  flush_interval 1s
  buffer_queue_limit 128
  buffer_chunk_limit 1g
  <server>
    host localhost
    port 24225
  </server>
</match>

と設定していた場合、buffer_queue_limit 1Gflush_interval 1s
どちらかの閾値を超えた場合にflushされます。

If the bottom chunk write out fails,
it will remain in the queue and Fluentd will
retry after waiting several seconds (retry_wait).
If the retry count exceeds the specified limit (retry_limit),
the chunk is trashed. The retry wait time doubles each time
(1.0sec, 2.0sec, 4.0sec, …).
If the queue length exceeds the specified limit (buffer_queue_limit),
new events are rejected.

例えば上記設定例で

  • forward先にデータが転送できなかった
  • ログファイルは1kB/secの書き込み

である場合、buffer_chunk_limit 1gに達する前にflush_interval 1sに引っかかり
flush_interval 1s x buffer_queue_limit 128(128kB)分のバッファを確保した後
新しいqueueは受け付けられなくなるかと思いきや、flushはあくまでflushなので
バッファする量は

  • buffer_chunk_limit x buffer_queue_limit

で決まるとのこと。

forward時にログの転送元でどれだけのバッファを担保したいかは
ログの流量と転送元と転送先のスペックによって変わるので
みんなよしなにやっているのではないかと思います。

forward

結論から先に書いておくと

<match **>
  type forward
  hard_timeout 180s
  phi_threshold 100
  <server>
    host a
    port 24224
  </server>
  <server>
    host un
    port 24224
    standby
  </server>
  <secondary>
    type file
    path /var/log/fluent/forward-failed
  </secondary>
</match>

上記のような冗長構成にできるのは、forward先が
いずれのサーバであっても同様の処理が行える時に限る。
ということです。

例えばaに障害があってhard_timeoutで設定している
180秒を超えた場合、転送先がunに変わります。
しかし、結局aで処理していたログとunに流れたログを
どこかでmergeしたりする必要があるのであれば、
冗長構成を設定しない方が運用は楽かと。

デフォルトの設定であれば

  • retry_limit 17
  • retry_wait 1.0s

となっており、最大131072 secリトライしてくれます。
ログの流量によってはその前に

  • buffer_chunk_limit x buffer_queue_limit

上記の閾値に引っかかる可能性がありますが、
閾値に引っかかる前にaのサーバの状態を復活させた方が
オペレーション的には楽だと思います。

絶対ロストしてはいけないデータだから冗長構成は必須!!!
という場合はそもそもfluentdの冗長構成の前にやることがあると思います。

というようなことを書いたのですが、認識に誤りなどあれば
ご指摘頂ければ幸いです。

fluentd の buffer あふれ改善議論 - togetter