この記事では、オンプレの非コンテナ環境で動くAPIをコンテナ環境(AWS Fargate)に移した時にやったこと、学んだことをログ周りに絞って書きます。
この記事から分かること
- コンテナ環境と非コンテナ環境でログをはじめとするデータの取り扱い方の違い
- Fargateで動作するコンテナからのログをFireLens, fluent-bitで取得する設定
環境はNginx+Flask+uWSGIで、uWSGI・fluent-bit・Nginxのコンテナをサイドカー構成でFargateで動かしています。
コンテナのステートレス性を担保しよう
非コンテナ環境とコンテナ環境では多くの面で、勝手がかなり異なります。
コンテナ開発では、コンテナのステートレス性 コンテナは何らかの形の永続データ(状態)を内部に保持しないという性質
を常に担保しなければなりません。
これを担保してあげることで、データを損失する心配がなくなり頻繁にいつでもデプロイを行うことができるようになります。
これはコンテナの大きな利点の一つなので、是非担保したいところ。
このステートレス性を担保するには、非コンテナ環境のオンプレからコンテナ環境に移す時、それまで通りログファイルにログを出力していてはまずいということになります。
オンプレとコンテナの、ログに関する違い
まず、ログについてオンプレとコンテナでの違いについて整理します。
オンプレ
- ログはファイルに出力
- ログを一定の期間(数十日単位)サーバ内に保持
- 一定の期間が過ぎた後はログを削除、もしくは別の場所に移す
コンテナ
- ログは標準出力、標準エラー出力に出力して他サービスを使用して外部ストレージにログファイルを保存
- ログファイルをはじめ一切の永続データをコンテナ内部に残さない
ログの管理方針はあるかと思いますが、上記で大きく外れてはいないかと思います。
よくあるエラー
開発段階でオンプレで動いていたAPIをそのままFargateに移行してロングラン検証などを行うと、例えばNginxのアクセスログファイルが肥大化してすぐに容量不足で書き込みできないエラーが発生します。
write() to "/var/log/nginx/api_access.log" failed (28: No space left on device) while logging request
これはおそらくコンテナではデータを外部に出力するのが基本なため、AWS側もあえてFargateに大きなストレージを用意していないのだと思います。
fluentdなどを使ってログをS3など外部データストレージに送っていると思いますが、リリースのタイミングでfluentdのバッファに存在していたログは消えてしまうはずなので、ファイルに出力→fluentdでS3に送信というやり方では問題が起きます。
Fargate上のコンテナが標準出力に出すログをFireLens、fluent-bitを使って集める
ここまでで、ログ周りに関するオンプレとコンテナの違い、オンプレのログ出力の方法を変える必要性があることがわかったと思います。
そこで、ログをファイルに出すのではなく標準出力に出すことになるのですが、
Nginxのアクセスログとエラーログを標準出力と標準エラー出力に出すとして、uWSGIのログもそこに出したいけどごっちゃにならないのかな
と思っていましたが、FireLensとfluent-bitを使用して、
- どのコンテナからのログであるか
- stdout, stderrどちらのエラーなのか
というのが分かる形でログを取得できます。fluent-bitの設定についての詳しい記事は終わりの方に載せてあります。
uWSGIのログについて
uWSGIでは安易にlogto: /dev/stdout
を設定すると
uwsgi_check_logrotate()/lseek(): Illegal seek [core/logging.c line 494]
というログで一杯になります。デフォルトで標準出力、標準エラー出力にログが吐かれるようなので、logtoの設定は消してしまって大丈夫です。
以下ドキュメント↓
The most basic form of logging in uWSGI is writing requests, errors, and informational messages to stdout/stderr. This happens in the default configuration.
Fargateの場合、
その他、困ったらこのページを見ればだいたいは解決すると思います。
https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/using_firelens.html
fluent-bitを使った詳しいFargateコンテナからのログの取得は別記事にまとめましたのでそちらを読んでください。
以上、参考になれば幸いです。
参考リンク
https://aws.amazon.com/jp/blogs/opensource/splitting-application-logs-multiple-streams-fluent/
https://cloud.google.com/solutions/best-practices-for-operating-containers?hl=ja#immutability
https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/using_firelens.html
https://uwsgi-docs.readthedocs.io/en/latest/Logging.html