Akatsuki Hackers Lab | 株式会社アカツキ(Akatsuki Inc.)

Akatsuki Hackers Labは株式会社アカツキが運営しています。

CloudWatch Logs + fluentdでモダンなアプリ監視をさくっと作ってみた話

背景

アカツキが提供しているサービスはリリース前に必ずテストを行っています。テストでバグが見つかったときにこれを切り分けるため、発生時のログを探すことがあります。「クライアントアプリで明らかに表示がおかしい」とか、そういったバグなら問題ないのですが、クライアントアプリからでは見えないサーバー側のバグが起きていて、それが見逃されてしまう…なんてこともあるかもしれません。

ふと、「機械的にこれを検出できるといいなー、あとログを探るためだけに毎回SSHするのもめんどくさいなー」 と思い、手を動かしてみることにしました。

今回の要件

  • テスト環境でサーバーエラーが起きたのを機械的に検出して、すぐ知らせてほしい
  • アクセスしやすいところに必要なログだけがあると嬉しい
  • できれば簡単な方法でやりたい

ツールの選定

アプリケーションの例外を検知して開発者に知らせてくれるものに、ExceptionNotifierAirbrake(有料)、Errbitなどがありますが、インストールするためにいずれもコードの修正が必要になります。

コードの修正をしなくて良い方法を模索していて、そこで目をつけたのがCloudWatch LogsというAWSのサービスでした。CloudWatch Logsではログに対してアラートを設定することが出来ます。 また、ログの保存に耐久性の高いストレージを使用することが出来ます。エラーの検知に関してはfluentd使用してログをtailすれば実現できそうです。

CloudWatch Logsとfluentdを利用する方法だとコードを変更する必要がなく、かつモジュール同士が疎結合になるので設計上とても実用的です。また、HipChatやSlackなどのチャットサービスを経由した通知もfluentdのプラグインを利用すれば比較的簡単に作ることできそうなので、アカツキ的に使いやすいということもありました。

CloudWatch Logs とは

CloudWatch LogsAWSのログファイルのリアルタイムモニタリングサービスです。

  • ログファイルの格納
  • ログファイルの監視
  • ログファイルの閲覧
  • アラートの設定
  • 保持期間の設定

などが出来ます。

2014年12月からTokyoリージョンでも利用できるようになりました。

やってみた

概要

サーバーエラーはRuby on Railsのログに全て記載されるので、ここを監視するのが比較的簡単にエラーを知る方法かなと思います。サーバーエラーが発生した時はそのログをCloudWatch Logsに投げるようにして、CloudWatch側でアラートを設定します。

IAM Userの作成

ポリシーを以下のようにして、CloudWatch Logs用のIAMユーザーを作成しました

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "logs:*",
                "s3:GetObject"
            ],
            "Resource": [
                "arn:aws:logs:us-east-1:*:*",
                "arn:aws:s3:::*"
            ]
        }
    ]
}

(参考: https://github.com/ryotarai/fluent-plugin-cloudwatch-logs/blob/master/README.md)

作成したら、AccessTokenとSecretを控えておきます。

fluentdの設定

1. fluent-plugin-cloudwatch-logs プラグインをインストールします。

$ /usr/lib64/fluent/ruby/bin/gem install fluent-plugin-cloudwatch-logs --no-ri --no-rdoc

2. td-agent.confに設定を記述する

<source>
      type tail
      path /path/to/logfile.log
      pos_file /var/log/td-agent/logfile.log.pos
      tag app.error
      format /^E, (?<log>.*)$/
</source>
<match app.error>
      type cloudwatch_logs
      log_group_name your_log_group_name
      log_stream_name your_log_stream_name
      auto_create_stream true
</match>

3. 環境変数の設定

td-agentユーザーにはログインシェルがなかったため、/etc/init.d/td-agentに以下のように記述しました。

export AWS_REGION="your_region" 
export AWS_ACCESS_KEY_ID="YOUR_ACCESS_KEY" 
export AWS_SECRET_ACCESS_KEY="YOUR_SECRET_ACCESS_KEY" 

4. td-agentの起動

$ service td-agent start

5. td-agent.logの確認

デフォルトだと/var/log/td-agentにあるtd-agent.logにエラーが表示されていないことを確認します。

アラートの設定

fluentdが起動してAWS ConsoleからCloudWatch Logsに移動すると、Log GroupとLog Streamが自動で生成されていました。Log Groupsからアラートを設定したいLog Groupを選択してCreate Metric Filterからアラートを設定します。

f:id:aktsk_hackers_lab:20161209184649p:plain

Filter Patternに検出パターンを入力して、アラートを設定したら完成です!

まとめ

簡単なアプリの監視をアプリ側の変更なしで、かつ少ない手順で作成することが出来ました。
機械的にエラーを検出することができ、通知もログの取得も簡単になりました。

このように一時的なログの置き場として利用したり、ログ自体を監視したい時にCloudWatch Logsは便利なサービスです。機会があれば利用してみてはどうでしょうか。