Dockerのログが16Kで分割されてしまう制限について

背景

ブラウザからデータを受け取り、それをS3に保存するアプリケーションの構築をAWS ECS Fargateで行いました。

フロントはnginx + nodejsを利用しています。フロントはブラウザから受けとったデータを加工して標準出力に出力するだけの役割です。

データはログルーターのFireLensを経由して、Kinesis Data Firehoseに送られ、LambdaをS3に保存するようにしました。

構成は上記の画像のようになります。

実際にデータを送ってみると、S3に保存された1つのJSONが途中で分割され2行になってしまっていました。

原因の調査

Lambdaでの調査

Kinesis Data Firehoseから起動しているLambdaでは、FireLensから送られてくるデータの必要な箇所(logというキーで取得できるログ本体)のみを取得し、改行をつけるだけの処理を行なっていました。(Kinesisからのデータなので、Base64デコードエンコードは行なっています)

なぜ分割されるのかがわからないのですが、なにか法則性がないかを調査したところ、分割されたデータの前半の長さは必ず16384バイト(16K)ということがわかりました。

しかも、Kinesis Data Firehoseに送られてくるデータには、データ本体のlog以外にも、partial_idpartial_messagepartial_lastなどのキーが含まれていました。

つまり、Kinesis Data Firehoseに入ってくる前にデータは分割されていたということです。

コンテナの調査

ECS Fargateで出力したデータを調査しました。nodejsアプリケーションから出力するデータをCLoudWatchで見てみると、その段階ですでに分割されていました。

ということはFireLensが原因ではないようです。

原因はDockerのロギングドライバの制限

調査の結果、原因はDockerロギングドライバの制限でした。1行あたり16Kが上限になっていて、現時点では変更できないようです。

https://github.com/moby/moby/issues/32923

まとめと次回予告

Dockerのロギングドライバの制限によってデータが16Kを超えると分割されてしまうということがわかりました。調べても意外と載っていないので、原因がわかるまで時間がかかりました。

次回はこの問題についてどう対応したかを記載したいと思います。