Dockerとログ(クラスタ構成編)

またログの話

前回といってももう半年以上も前になりますが、今回はコンテナクラスタを構築する場合を考えてみます。 ホストを意識しているコンテナではなく、ホストを意識しないコンテナ。

目的をいうと、疎結合、シンプルに、楽にログの収集を実施したいのです。

問題の定義

なぜログについて悩むのか。問題を明確にします。

コンテナとホストを疎結合にしたい

クラスタを構成するうえで、「このホストはnginxとPHPで構成する・・」、みたいなことをしたくない。 インスタンスのリソースが空いているから自由に使え、また自由にスケールできるようにしたい。 ホストの存在を忘れたい。 ログデータをホストとVolumeマウントして何かやる方法がこの問題に違反する。ホストの立場からするとどのコンテナがDocker runされているのか知る必要があり、ログファイルがどこにあるかさえも知っておく必要があるかもしれない。

ログの管理はコンテナに任せたい

コンテナ(コンテナ上で動作しているアプリケーション)が吐いたログはコンテナで管理して欲しい。 結局、1つ目の疎結合の問題と似てしまうのだが、コンテナ外の助けを必要としてしまうと、ログ管理するコンポーネントは、コンテナの情報や仕様を知る必要がある。 これは悪ではないが自分のことは自分でやって欲しい。コンテナの仕様が変わったらログ管理も変更する必要があり、バージョンの違うコンテナが混在したらどうするか?・・ありえない、面倒臭い。

解決する方法案

あくまで参考に。より良い案もあると思う。 Fluentdによるログ解析基盤が既にあったりすればまた違う答えがある気がします。

Amazon Elasticsearch Serviceを使ったログ収集基盤の構成を考えてみた | Ryuzee.com
こちらを例に取ると、全体的にFluentdが標準化されており、素敵な構成だと思います。 解析基盤もそれなりに整っていそうな感触。

Docker Log Driver

コンテナのログはそのコンテナが管理するシンプルな方法として、Docker Log Driverが非常に適当に思える。nginxだと/dev/stdoutaccess.logをリンクさせることでFluentdなりawslogsなりに集約させることができる。ただし例外がありPHP-FPMコンテナの場合は・・使えない。monologが出力するログはサブプロセスで動いているので標準出力に吐かせてどうこうできる感じでは無いっぽい。 php - Docker: Logging From Both App and Server In One Container - Stack Overflow

CloudWatchLogs Agent

phpコンテナのログ出力がLogDriverだけではうまくいかない為、 Supervisorと併用しCloudWatchLogs Agentをコンテナ内で動かすことにしてみました。 コンテナのバージョンがアプリケーションのバージョンに依存してしまいますが、 現時点ではクラスタを組むにはこの方法しかないのではなかろうかというところ。 役目ごとにコンテナを分けたい気分もあります。ローカルで動作させた場合に無駄にAgentも動くので、些細なことですがやや気になるといったところ。

まとめ

単純ですがDocker Log Driverか、使えない場合はコンテナ内にログ集約する役目を持たせる方法がベターかと思います。簡単さでいうと、ホスト側にログの集約機能を持たせるほうが簡単だと思われます。 AWS Beanstalkの簡単さには甘えてしまいますが、Beanstalkはこの簡単な方法がベストマッチします。

ちなみに、CloudWatchLogsありき前提で記載しました。 Managedされているログの集約先なのでぴったり。Aggregatorを自分で構築運用しようとか私は好きではありません。 CloudwatchLogsからESに飛ばしたり、S3に保存したりできるのも素敵です。