CAMPHOR- VPSのコンテナロギングを支える技術

December 16, 2020

この記事はCAMPHOR- Advent Calendar 2020の 17 日目の記事です。

11 月の終わり頃、個人的にインターンとインターンの合間で暇していた時期に CAMPHOR-のサーバーに Grafana/Loki を導入しました。

この記事では、Grafana/Loki を用いて、サーバー内の容量の圧迫を防ぎつつコンテナログの永続化を行う方法とその注意点を紹介します。

背景

現状 CAMPHOR-の各種サービスは docker に載った状態で動作しています。

元々改善を入れる前は特別なログの管理ということをしていませんでした。 CAMPHOR-ではサーバーの ssh を行うことができる人を制限しているので、ログを見たい時は ssh のできる人がdocker logsからログを調査するという形になっていました。

この状態には以下の問題点があります

  1. コンテナ再起動に伴うログの消失
  2. サーバーへのアクセス権がある人のみしかログを閲覧できない

docker はデフォルトの状態でコンテナの停止時にログが消えてしまいます。そのため、コンテナを再起動させた場合などに再起動前のログを追えなくなります。

コンテナログに求められる要件

今回のコンテナログに求められることは以下です

  1. ログがコンテナが停止しても消えない(must)
  2. ログを誰でも簡単に見れる
  3. ログを溜めすぎてサーバーの容量一杯になるとやばいので定期的に消したい
  4. 新しいコンテナが追加された際の対応が簡単である

初めは、docker の吐くログファイルを直接永続化して logrotate をかけるなどのシンプルな方法を考えていましたが、要件 2 を満たすために、WebUI からログを閲覧できる必要があると考え、今回は Grafana/Loki を使用することにしました。 要件を満たす方法は他にも「EFK スタック」と呼ばれる ElasticSearch / Fluentd / Kibana などをはじめとして色々あるかと思います。

loki-docker-driver を用いたコンテナロギングの構築

Loki にログを転送するための docker-plugin としてDocker Driver Client(grafana/loki-docker-driver)が存在します。これを docker の logging driver として使用することでコンテナの吐くログをうまくコンテナごとに label を貼りつつ loki に送ってくれます。

この plugin を入れればあとはconfigurationにのっとって設定をしていくだけになります。難しい部分が本当にひとつもなくサクッと導入をすることができました。

Loki と Grafana は公式の docker-compose.yamlをほとんどそのまま使用して立ち上げました。

と言うことで、図に表すとこんな感じになります (図をわかりやすくするために、Loki と Grafana を docker の外に出しています)

構成図

loki-docker-driver が loki に送ったログを Grafana から参照する形です。

Grafanaの図

このような形で閲覧できます。

ログの最大容量の制限

ここから少し細かい設定に関してみていきます

{
    "log-driver": "loki",
    "log-opts": {
        "mode": "non-blocking",
        "loki-url": "http://localhost:3100/loki/api/v1/push",
        "loki-batch-size": "400",
        "loki-retries": "2",
        "loki-timeout": "1s",
        "keep-file": "true",
        "max-size": "5g"
    }
}

上記が実際に使用している docker デーモンの設定ファイル(daemon.json)です。

keep-file と言う設定が入っています。

This indicates the driver to keep json log files once the container is stopped. By default files are removed, this means you won’t be able to use docker logs once the container is stopped. https://grafana.com/docs/loki/latest/clients/docker-driver/configuration/

説明にもありますが、これによってdocker logsコマンドが使用可能になります。docker logsコマンドはホストに残される json file のデータをもとに実行されるので、logging driver を loki-docker-driver に変更してしまうとデフォルトだと json file が吐かれなくなりdocker logsコマンドも使用不可能になります。 Grafana がいるとはいえ、docker logsコマンドがないと不便なのでkeep-fileを有効にしています。

「いやいや、要件 3 の「ログ溜めすぎると容量がやばい」はどうなんねん」と思われるかと思いますが、その一つ下のmax-sizeによって json-file の最大容量を制限しています。

次は Loki 自体の設定を見ていきます。

chunk_store_config:
  max_look_back_period: 2184h

table_manager:
  retention_deletes_enabled: true
  retention_period: 2184h

上記はデフォルトから変更を入れた loki の設定です。ここでは Loki に残されるログデータの容量を制限するために、約 3 ヶ月より前のログに関しては delete するように指定しています。 これによって、Loki に送られたデータが容量を圧迫すると言う心配もありません。(Loki はログを gzip 圧縮して持ってくれるので容量を取りにくいとはいえ、塵も積もればと言いますしね)

ref: Loki Storage Retention

ちなみに注意点として period に指定する値は 168h の倍数である必要があります。

Hey, Loki requires that retention (720h in your case) is divisible by the duration of each index table (168h by default). https://github.com/grafana/loki/issues/2151

Loki が死ぬと docker 全体が死ぬ問題

順調に見えた Loki の導入ですが、Loki のコンテナの再起動をしようとした時に事件は起こりました。

if loki is not reachable and loki-docker-driver is activated, containers apps stops and cannot be stopped/killed

Loki が死ぬと、loki-docker-driver がログを送ろうとして retry を続けて docker デーモン自体がクソ重くなってしまうという問題です。

これによって一回 CAMPHOR-の全サービスが落ちました(深夜 2 時だったのが不幸中の幸いだった)

esa

渾身のツイートも滑っていますね

こちらは先程のdaemon.jsonの再掲です

{
    "log-driver": "loki",
    "log-opts": {
        "mode": "non-blocking",
        "loki-url": "http://localhost:3100/loki/api/v1/push",
        "loki-batch-size": "400",
        "loki-retries": "2",
        "loki-timeout": "1s",
        "keep-file": "true",
        "max-size": "5g"
    }
}

この問題の対処のために複数の設定を入れています

  • mode: non-blocking にすることでコンテナの処理が中断されない
  • loki-retries: リトライの回数を減らす(デフォルトは 10)
  • loki-timeout: timeout までの時間を短くする(デフォルトは 10s)

これで上記の問題は抑えることができました。 しかし、ログの信頼性が代わりに落ちるので、この辺りはバランスを考えて設定すべきですね。

終わりに

今回は loki-docker-driver を使用した、コンテナロギングの構築の一例を紹介しました。

どの程度のアクセスがくるサービスのログなのか、ログを吐くプロセスがいくつ走っているのか等、状況によってログに求められるものが大きく変わってきます。 今回の構成では最後の issue に対処するためにログの信頼性が少し下がってしまう設定を入れています。しかしこれは現状の CAMPHOR-のサービス状況を考えたときに常に大量のログが吐かれているわけではないという状況も加味した上での判断です。

今回のこの一例がどなたかのお役に立てば幸いです、ここまで読んでいただきありがとうございました。

このエントリーをはてなブックマークに追加