🧑‍💻

Dockerロギング 入門

2022/05/31に公開

今までDockerのロギングはいつも適当に設定していた。
だが、ロギングを状況に合わせて適切に設定しないと、性能・信頼性に影響するらしいので、しっかりと理解を深めておこうと思う。

Dockerログ処理の基本

image
Dockerのログ処理の仕組みを簡単に説明すると、「コンテナで標準出力/標準エラー出力に吐かれたログを、設定してるロギングドライバが処理する」というもの。
こういう仕組みなので、Dockerコンテナで動作するアプリは、原則として標準出力/エラー出力にログを吐く必要がある。
ファイルなどに吐いてしまうと、せっかく用意されてるロギングドライバの恩恵を受けることができない。

ロギングドライバは標準でいろいろ用意されてるので、システム要件に応じて使い分けるといい
loggings

アプリの要件・性質に応じて「配信モード」を使い分ける

Dockerのロギングを語る上でこの知識は確実に抑えておかないといけない。
配信モードは、基本的にロギングドライバと独立した関係ではるが...
特定のロギングドライバや状況によっては「こっちの配信モードじゃないとダメ」というものもあるので注意。

ブロッキングかノンブロキングのどちらを選択するかで、アプリ性能やロギング信頼性が変わってくる

ブロッキングモード

ログがドライバに転送される際、ドライバの処理完了までアプリケーションの動作をブロックする。

メリット: ログが出力される度にドライバが確実に取り込むので、ログが欠落する確率は低い
デメリット: 逆に性能を気にするアプリケーションだと、ログ出力の度に処理が止められるので、性能に悪影響が出る可能性もある

ノンブロッキングモード

ログをドライバに転送せずに、コンテナはメモリ内のバッファにログを書き込む
ドライバがログを処理する準備ができたときにのみログを転送する

メリット: アプリケーションがログ出力の度に止められることはないので、性能への影響が無い
デメリット: ログが一部または全て消失する可能性がある
  バッファが一杯になって、最初に保存したログが無くなったり
  コンテナがアプリ処理完了の前に壊れて、バッファのログが転送される前に消失したり

使い分けるための判断基準

ほとんどの場合は「ブロッキング」を利用すればいい。
json-file, localなどのローカルにログを保存する系のドライバであれば、I/Oもそこまで発生しないので、性能は気にならないと思われる。

ログによって性能に悪影響が出てるとなると、「ノンブロッキング」を考慮するべき。
リモートに保存する系のログドライバ(ex:awslogs, gcplogs)などは、「ブロッキング」だとネットワークI/Oの影響でアプリ性能が悪化する。

「ノンブロッキング」を採用する場合は以下の点にも注意する

  1. メモリに必要なバッファサイズを確保できるか
    • バッファサイズが十分でないと、一部のログが消失したり、性能が向上しなかったりする
  2. ログの欠如リスクの対策
    • コンテナが途中で落ちたりして、ログが消失してしまうリスクへの対策を決めておく
    • そんなに重要じゃないログなので消失しても最悪大丈夫なのか
    • 消失されると困る、念のため定期的にコンテナ外に退避しておきたい、なのか
    • 性能よりログの方が重要なら、ブロッキングモードにした方がいい

参考

Discussion