FireLens が OOM で死んでしまう

ECS でログを管理するために,FireLens を利用しています.ちょっと前に,FireLens で複数行のログを連結して出力することがサポートされました. 僕も一つのエラーログが改行で複数行で分割されるのを避けるために,これを利用して設定を書いたんですが,うまく動きません.起動してしばらくするとFireLensを動かしているコンテナがOOMで死んでしまうんです….

何が起こったか

以下のような設定をしました.抜粋です.

[SERVICE]
    Parsers_File /fluent-bit/parsers/parsers.conf
    Parsers_File /fluent-bit/etc/parsers_multiline.conf

[FILTER]
    name                  multiline
    match                 *
    multiline.key_content log
    multiline.parser      multiline-regex

[FILTER]
    Name         parser
    Match        *
    Key_Name     log
    Parser       json
    Reserve_Data True

[FILTER]
    Name  rewrite_tag
    Match xxxxx
    Rule  xxxx

[FILTER]
    Name  rewrite_tag
    Match xxxxx
    Rule  xxxx

[OUTPUT]
    Name               cloudwatch_logs

こういった設定でFireLensを動かしていると,以下のようなエラーメッセージを出力しOOMでFireLensのコンテナがOOMで死にます.

[2022/02/25 15:40:27] [error] [input:emitter:emitter_for_multiline.0] error registering chunk with tag: xxxxx

どうやって解決したん?

仮説を立てる

エラーメッセージでググってみると,以下のGitHubのイシューがヒットします.

これは,multiline filter を複数利用すると,ログが無限ループしてしまうというものです.今回の件は,multiline filter を複数使っているわけではない,という以外はこのイシューにぴったりでした.なので,FILTERが複数ありそれぞれ * でMATCHさせている場合でも同じような問題が起こるのではと仮説を立てました.

検証環境を作る

これが原因である,という確証がそこまで高くないので(イシュー通りの設定をしているわけじゃないので)ECSに検証環境を用意し,今回のエラーを再現します.以下のブログを参考にしました.

ほぼこのまま環境を作り,ログを出力するプログラムだけ,今回,実際にエラーになったログを出力するように置き換えました. そうすると,エラーが再現しました.

設定を作る

ここはもう単純に FILTER の Match と Rule を工夫して必要なログが必要なフィルタしか通らないように書き換えただけです. そうすると,エラーが出なくなりました.

まとめ

結論は

FILTERが複数ありそれぞれ * でMATCHさせている場合でも同じような問題が起こるのでは

という仮説が正しかったということです.

結論だけ見ると,検証環境を作るコストが大きく見えてしまいます.しかしそうではなくて,今回はたまたまエラーが再現でき,問題を回避する設定がうまくいっただけです. エラーを再現できなかったり,想定していた設定ではうまくいかなかった可能性は十分あります.まぁ,設定も決して一発でかけたわけじゃなくて,予想外のハマりどころはありましたし….

ということで,問題解決の王道である仮説を立てて検証をして…というやつはやっぱり効きますよ,という話でした.