Amazon CloudWatch Logsを実行するDockerイメージを作ってみた
ども、大瀧です。
先日リリースされたCloudWatch Logsですが、早速弊社ブログでも取り上げています。
- Amazon CloudWatch Logsでログファイルを監視する | Developers.IO
- Amazon CloudWatch Logsによるログの収集とフィルタとアラーム設定 | Developers.IO
手軽に使えるログストアとして、AWSユーザーであれば(あるいはそれ以外のユーザーでも)検討する機会が多くなりそうです。それは、もしかしたら近いうちにデファクトのアプリ実行環境になるかもしれないDocker環境にも言えることだと思います。そこで、CloudWatch LogsにログをプッシュするDockerイメージを作成し、Docker環境でCloudWatch Logsを利用する手順をご紹介します。
動作確認環境
- AMI : Amazon Linux 2014.03.2 HVM
- Docker : バージョン1.0.0
コンテナ構成の概要
Dockerでログを集約する方法はいくつかありますが、今回は最も単純な、ボリュームを共有する方法を利用します。Dockerのログ集約については、以下のブログ記事が詳しいです。
概念図で示すと、以下の感じになります。
今回は収集対象のログをnginxのアクセスログとし、awslogエージェントを実行するコンテナがアクセスログをCloudWatch APIにPushします。DockerコンテナからCloudWatch APIにアクセスできるのか、IAMロールが動くのか気になるところですが、Dockerコンテナの既定のネットワーク構成であればどちらも問題ありません。
awslogコンテナのベースDockerイメージは、Docker Hubで公開しました。docker pullで使って下さい。
ベースDockerイメージと書いたのは、このイメージから直接コンテナーを立ち上げても監視するログファイルの定義が空のため、コンテナは何もしないためです。このイメージに設定ファイルを追加した派生イメージをdocker buildで作成し、使っていただくものになっています。docker buildを実行するマシンは、Dockerを実行する任意のマシンで構いません(今回は手元のMBAでBoot2Dockerを実行しました)。
では、手順を追って紹介していきます。
1. CloudWatch Logsの設定ファイルの作成
CloudWatch Logsの動作には、以下2つのファイルが必要です。`docker build`を実行するマシンでそれぞれ作成します。
aws.conf
[plugins] cwlogs = cwlogs [profile default] aws_access_key_id = AKIAXXXXXXXXXXXX aws_secret_access_key = XXXXXXXXXXXXXXXXXXXXXXXXXX
CloudWatch APIにアクセスするための設定を記載します。[profile default]以降のアクセスキー、シークレットキーはIAMロールをEC2インスタンスに付与している場合は省略できます。
awslogs.conf
[general] state_file = /var/awslogs/state/agent-state [/var/log/nginx/access.log] datetime_format = %b %d %H:%M:%S file = /nginx-logs/access.log push_delay = 5000 log_stream_name = {instance_id} initial_position = start_of_file log_group_name = /var/log/nginx/access.log [/var/log/nginx/error.log] datetime_format = %b %d %H:%M:%S file = /nginx-logs/error.log push_delay = 5000 log_stream_name = {instance_id} initial_position = start_of_file log_group_name = /var/log/nginx/error.log
4行目以降は監視したいファイルごとに作成します。いくつかパラメータがありますが、他のファイルを監視する場合も基本的にはファイル名のみいじる形で問題ないでしょう。
2. Dockerイメージのビルド
上記2ファイルを同じディレクトリで以下のDockerfileを作成し、Dockerイメージをビルドします。
Dockerfile
FROM takipone/docker-awslogs
1行しかないことに驚くかもしれませんが、これでOKです。先ほど作成したaws*.confファイルは、ベースのDockerイメージtakipone/docker-awslogsのDockerfileの中でONBUILDが定義されているので、以下のビルドログにもあるように今回のビルド時にDockerイメージに追加されます。では、docker buildコマンドでビルドします。-tオプションに指定するイメージ名(今回はtakipone/awslogs-nginx)は、好きなもので構いません。
$ docker build -t takipone/awslogs-nginx . Sending build context to Docker daemon 14.34 kB Sending build context to Docker daemon Step 0 : FROM takipone/docker-awslogs # Executing 2 build triggers Step onbuild-0 : ADD aws.conf /var/awslogs/etc/aws.conf ---> 0db93cfae97f Step onbuild-1 : ADD awslogs.conf /var/awslogs/etc/awslogs.conf ---> 4c3493eb04f6 ---> 4c3493eb04f6 Removing intermediate container 43e3a83a7f4f Removing intermediate container fe0a43f5d7bc Successfully built 4c3493eb04f6 $
できました!
監視するログの設定(nginxの例)
順番が前後しますが、今回の監視対象ログとなるnginxのコンテナで出力するアクセスログ(access.log)およびエラーログ(error.log)を準備します。awslogコンテナとnginxコンテナのファイルはデフォルトでは別々のchroot環境になるので、docker runコマンドの-vオプションで外部にマウントするところに注意します。今回は/nginx-logs/ディレクトリにログを出力、外部にマウントします。
$ docker pull dockerfile/nginx Pulling repository dockerfile/nginx 2a106d243809: Download complete : $ sudo mkdir /nginx-logs $ docker run -d -p 80:80 -v /nginx-logs:/var/log/nginx dockerfile/nginx 6c73622f487d2366d8fd151946c0eb7c59c2f62ad644854a61f156189665af37 $ curl localhost <!DOCTYPE html> <html> : <h1>Welcome to nginx!</h1> : </html> $ ls /nginx-logs access.log error.log $ cat /nginx-logs/access.log 172.17.42.1 - - [13/Jul/2014:09:02:22 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.36.0" $
nginxコンテナの動作は問題無さそうですね。
awslogコンテナの実行と動作確認
それでは、awslogコンテナを実行します。先ほどのnginxコンテナの実行と同様、docker run実行時に-vオプションで/nginx-logs以下をマウントします。
$ docker run -d --name awslogs -v /nginx-logs:/nginx-logs takipone/awslogs-nginx 0f9f920290560875fdb3352947a0a9458de076be3c8cc8e60ce9a46e52bd0439 $ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 0f9f92029056 takipone/awslogs-nginx:latest /bin/sh -c '/bin/sh 2 seconds ago Up 1 seconds awslogs 6c73622f487d dockerfile/nginx:latest nginx 13 hours ago Up 13 hours 443/tcp, 0.0.0.0:80->80/tcp grave_mayer $
コンテナが動きました。では、CloudWatch Logsの画面を確認してみます。
コンテナを実行するEC2インスタンスのインスタンスIDでアクセスログが確認できます!
まとめ
DockerコンテナでCloudWatch LogsにログをPushする手順をご紹介しました。コンテナ間のログのやり取りはまだまだ改善や工夫ができるところだと思うので、引き続きいろいろ試行錯誤してみたいと思います。
Dockerコンテナを使うことで、awslogエージェントのインストール無しで手軽にセットアップ出来る感じがDockerらしくていいなぁ、と感じていただけるとDocker推しとしては嬉しい限りです。