ちょっと話題の記事

DockerのFluentd Logging Driverを試してみる

2015.07.01

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

ども、大瀧です。 Dockerバージョン1.6でLogging Driverというプラガブルなログ機構が追加され、DockerコンテナのログをSyslogに送信するなど柔軟なログ構成ができるようになりました。 ログアグリゲータとして著名なFluentdのLogging Driverが最近Dockerのmasterブランチにマージされたので、試してみた様子をご紹介します。

検証環境

  • OS : Ubuntu 15.04 Vivid Vervet(AMI : ubuntu-vivid-15.04-amd64-server-20150616.1 (ami-0473a904) 東京リージョン)
  • Docker : Master Binaries 1.8.0-dev/Git commit: 90024b9

まだリリースされていない段階なので、最新リリースのDockerパッケージをインストールした状態でGitHubのmasterブランチのデイリービルドから入手した/usr/bin/dockerをすげ替える形でやってみました。

$ wget -qO- https://get.docker.com/ | sh
$ sudo usermod -aG docker ubuntu
$ docker version
Client version: 1.7.0
Client API version: 1.19
Go version (client): go1.4.2
Git commit (client): 0baf609
OS/Arch (client): linux/amd64
Server version: 1.7.0
Server API version: 1.19
Go version (server): go1.4.2
Git commit (server): 0baf609
OS/Arch (server): linux/amd64
$ sudo service docker stop
$ wget https://master.dockerproject.org/linux/amd64/docker
$ chmod 755 ./docker
$ sudo mv /usr/bin/docker /usr/bin/docker17
$ sudo mv ./docker /usr/bin/
$ sudo service docker start
$ docker version
Client:
 Version:      1.8.0-dev
 API version:  1.20
 Go version:   go1.4.2
 Git commit:   90024b9
 Built:        Tue Jun 30 13:02:19 UTC 2015
 OS/Arch:      linux/amd64

Server:
 Version:      1.8.0-dev
 API version:  1.20
 Go version:   go1.4.2
 Git commit:   90024b9
 Built:        Tue Jun 30 13:02:19 UTC 2015
 OS/Arch:      linux/amd64
$

Fluentdサーバーとしてtd-agentをセットアップしておきます。

$ curl -L https://td-toolbelt.herokuapp.com/sh/install-ubuntu-trusty-td-agent2.sh | sh

デバッグ用に、td-agent.confファイルの末尾にDockerログを標準出力(td-agentのログファイル)に出力する以下を追加しました。

  :
<match docker.**>
  type stdout
</match>

td-agent.confファイルの再読込をしておきます。

$ sudo service td-agent restart

これで準備OKです。

動作確認

Dockerコンテナの実行オプション--log-driverfluentdとセットすると、コンテナのログがローカルのFluentdサーバー(localhost:24224)に送信されます。

$ docker run --log-driver=fluentd hello-world
$ tail -n 20 /var/log/td-agent/td-agent.log
</ROOT>
2015-06-30 13:39:44 +0000 [info]: listening fluent socket on 0.0.0.0:24224
2015-06-30 13:39:44 +0000 [info]: listening dRuby uri="druby://127.0.0.1:24230" object="Engine"
2015-06-30 13:39:52 +0000 docker.49cdcf66ce0c: {"container_id":"49cdcf66ce0c882f9788cbdeeea0e354bf7331eb3a1fd8ccd4746834def84ef7","container_name":"/angry_mestorf","source":"stdout","log":"Hello from Docker."}
2015-06-30 13:39:52 +0000 docker.49cdcf66ce0c: {"source":"stdout","log":"This message shows that your installation appears to be working correctly.","container_id":"49cdcf66ce0c882f9788cbdeeea0e354bf7331eb3a1fd8ccd4746834def84ef7","container_name":"/angry_mestorf"}
2015-06-30 13:39:52 +0000 docker.49cdcf66ce0c: {"source":"stdout","log":"","container_id":"49cdcf66ce0c882f9788cbdeeea0e354bf7331eb3a1fd8ccd4746834def84ef7","container_name":"/angry_mestorf"}
2015-06-30 13:39:52 +0000 docker.49cdcf66ce0c: {"container_name":"/angry_mestorf","source":"stdout","log":"To generate this message, Docker took the following steps:","container_id":"49cdcf66ce0c882f9788cbdeeea0e354bf7331eb3a1fd8ccd4746834def84ef7"}
2015-06-30 13:39:52 +0000 docker.49cdcf66ce0c: {"container_id":"49cdcf66ce0c882f9788cbdeeea0e354bf7331eb3a1fd8ccd4746834def84ef7","container_name":"/angry_mestorf","source":"stdout","log":" 1. The Docker client contacted the Docker daemon."}
2015-06-30 13:39:52 +0000 docker.49cdcf66ce0c: {"container_id":"49cdcf66ce0c882f9788cbdeeea0e354bf7331eb3a1fd8ccd4746834def84ef7","container_name":"/angry_mestorf","source":"stdout","log":" 2. The Docker daemon pulled the \"hello-world\" image from the Docker Hub."}
2015-06-30 13:39:52 +0000 docker.49cdcf66ce0c: {"container_id":"49cdcf66ce0c882f9788cbdeeea0e354bf7331eb3a1fd8ccd4746834def84ef7","container_name":"/angry_mestorf","source":"stdout","log":"    (Assuming it was not already locally available.)"}
2015-06-30 13:39:52 +0000 docker.49cdcf66ce0c: {"container_id":"49cdcf66ce0c882f9788cbdeeea0e354bf7331eb3a1fd8ccd4746834def84ef7","container_name":"/angry_mestorf","source":"stdout","log":" 3. The Docker daemon created a new container from that image which runs the"}
2015-06-30 13:39:52 +0000 docker.49cdcf66ce0c: {"source":"stdout","log":"    executable that produces the output you are currently reading.","container_id":"49cdcf66ce0c882f9788cbdeeea0e354bf7331eb3a1fd8ccd4746834def84ef7","container_name":"/angry_mestorf"}
2015-06-30 13:39:52 +0000 docker.49cdcf66ce0c: {"container_name":"/angry_mestorf","source":"stdout","log":" 4. The Docker daemon streamed that output to the Docker client, which sent it","container_id":"49cdcf66ce0c882f9788cbdeeea0e354bf7331eb3a1fd8ccd4746834def84ef7"}
2015-06-30 13:39:52 +0000 docker.49cdcf66ce0c: {"container_id":"49cdcf66ce0c882f9788cbdeeea0e354bf7331eb3a1fd8ccd4746834def84ef7","container_name":"/angry_mestorf","source":"stdout","log":"    to your terminal."}
2015-06-30 13:39:52 +0000 docker.49cdcf66ce0c: {"container_id":"49cdcf66ce0c882f9788cbdeeea0e354bf7331eb3a1fd8ccd4746834def84ef7","container_name":"/angry_mestorf","source":"stdout","log":""}
2015-06-30 13:39:52 +0000 docker.49cdcf66ce0c: {"log":"To try something more ambitious, you can run an Ubuntu container with:","container_id":"49cdcf66ce0c882f9788cbdeeea0e354bf7331eb3a1fd8ccd4746834def84ef7","container_name":"/angry_mestorf","source":"stdout"}
2015-06-30 13:39:52 +0000 docker.49cdcf66ce0c: {"container_name":"/angry_mestorf","source":"stdout","log":" $ docker run -it ubuntu bash","container_id":"49cdcf66ce0c882f9788cbdeeea0e354bf7331eb3a1fd8ccd4746834def84ef7"}
2015-06-30 13:39:52 +0000 docker.49cdcf66ce0c: {"container_name":"/angry_mestorf","source":"stdout","log":"","container_id":"49cdcf66ce0c882f9788cbdeeea0e354bf7331eb3a1fd8ccd4746834def84ef7"}
2015-06-30 13:39:52 +0000 docker.49cdcf66ce0c: {"source":"stdout","log":"For more examples and ideas, visit:","container_id":"49cdcf66ce0c882f9788cbdeeea0e354bf7331eb3a1fd8ccd4746834def84ef7","container_name":"/angry_mestorf"}
2015-06-30 13:39:52 +0000 docker.49cdcf66ce0c: {"log":" http://docs.docker.com/userguide/","container_id":"49cdcf66ce0c882f9788cbdeeea0e354bf7331eb3a1fd8ccd4746834def84ef7","container_name":"/angry_mestorf","source":"stdout"}
$

49cdcf66ce0cがコンテナIDに対応しており、DockerのコンテナログがFluentdに渡っているのがわかりますね!

まとめ

最小限の動作確認でしたが、確かにDockerコンテナのログをFluentdに送信できている様子が確認できました。

Fluentdサーバーを今回のようにホストでデーモンとして実行するのか、これはこれでFluentdのDockerコンテナとして実行するのかを次に検討しつつ、FluentdからはひとまずS3にログを格納する感じになるのではないでしょうか。リリースに入るのを心待ちにしつつ、Dockerのログアーキテクチャの構想を練っておきましょう。