EC2のインスタンスのポータビリティを考慮すると、インスタンス上に展開してるアプリケーションサーバやOSのログをどう確保しておくかというのは大事なポイントになります。よくある方法としては、

  • 定期的にS3に保存する
  • Fluentdのようなツールを使ってログを収集する

といったアプローチが挙げられます。今回は別の方法として、少し前にAWSに追加されたCloudWatch Logsを使ったログの収集を行ってみました。(CloudWatch自体はAWSリソースのモニタリングを行うサービスですが、2014年7月にOS及びアプリケーションのカスタムログファイルを格納する機能と、ログのモニタリングを行う機能が追加されてます。)

IAMのパーミッション設定

ログを収集する対象のインスタンスにCloudWatch Logs agentによるログ収集を許可するためのパーミッションを設定します。CloudWatch Logs agentはIAM Roleをサポートしてるので、対象のインスタンスに適用されてれいるIAM Roleに↓のPolicyを適用します。

{
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "logs:*"
      ],
      "Resource": [
        "arn:aws:logs:*:*:*"
      ]
    }
  ]
}
CloudWatch Logs agentのインストール

続いてログを収集するEC2インスタンスにCloudWatch Logs agentをインストールします。セットアップ用のスクリプトを実行するだけで簡単にインストールできます。
AWSのAccess KeyとSecret Access KeyはIAM Roleから取得するためのここでは設定していません。ここではOSのログ(/var/log/messages)を収集対象にしてます。

$ wget https://s3.amazonaws.com/aws-cloudwatch/downloads/awslogs-agent-setup-v1.0.py 
$ sudo python ./awslogs-agent-setup-v1.0.py --region us-east-1
Launching interactive setup of CloudWatch Logs agent ... 

Step 1 of 5: Installing pip ...DONE

Step 2 of 5: Downloading the latest CloudWatch Logs agent bits ... DONE

Step 3 of 5: Configuring AWS CLI ... 
AWS Access Key ID [None]: 
AWS Secret Access Key [None]: 
Default region name [None]: 
Default output format [None]: 

Step 4 of 5: Configuring the CloudWatch Logs Agent ... 
Path of log file to upload [/var/log/messages]: 
Destination Log Group name [/var/log/messages]: 

Choose Log Stream name:
 1. Use EC2 instance id.
 2. Use hostname.
 3. Custom.
Enter choice [1]: 3
Enter Log Stream name [None]: sample

Choose Log Event timestamp format:
 1. %b %d %H:%M:%S (Dec 31 23:59:59)
 2. %d/%b/%Y:%H:%M:%S (10/Oct/2000:13:55:36)
 3. %Y-%m-%d %H:%M:%S (2008-09-08 11:52:54)
 4. Custom
Enter choice [1]: 3

Choose initial position of upload:
 1. From start of file.
 2. From end of file.
Enter choice [1]: 
More log files to configure? [Y]: n

Step 5 of 5: Setting up agent as a daemon ...DONE


------------------------------------------------------
- Configuration file successfully saved at: /var/awslogs/etc/awslogs.conf
- You can begin accessing new log events after a few moments at https://console.aws.amazon.com/cloudwatch/home?region=us-east-1#logs:
- You can use 'sudo service awslogs start|stop|status|restart' to control the daemon.
- To see diagnostic information for the CloudWatch Logs Agent, see /var/log/awslogs.log
- You can rerun interactive setup using 'sudo ./awslogs-agent-setup.py --region us-east-1 --only-generate-config'
------------------------------------------------------

この設定内容は/var/awslogs/etcに保存されてます。これだけでログの収集が有効になるので、Management Consoleで確認すると↓のように早速ログが収集されているのを確認できます。

logs

現状CloudWatch Logsが利用可能なのはUS-EastとUS-WestとEUのみです。(ログを収集対象のEC2インスタンスのリージョンの制約はありません。今回ログを収集するEC2インスタンスはTokyoリージョンのインスタンスです。おそらく同一リージョンのCloudWatch Logsが利用できるなら、その方がリージョン間の転送料金が発生しないと思われます。)

収集するログの追加

収集するログを追加したい場合は/var/awslogs/etc/awslogs.confを編集します。ログストリームの設定は以下のフォーマットで定義します。

[ログストリーム名]
log_group_name = ロググループ名
log_stream_name = ログストリーム名(定義済変数として{instance_id}, {hostname}, {ip_address}を利用するか任意の名称をセット)
datetime_format = 日付フォーマットを定義(例:%Y-%m-%d %H:%M:%S)
time_zone = タイムゾーンを指定。利用可能なのはLOCALかUTCのいずれか
file = 収集対象のログファイルのパス
file_fingerprint_lines = ファイルを識別するための行範囲を指定。
multi_line_start_pattern = ログメッセージの開始位置を識別するためのパターン。正規表現か{datetime_format}のいずれかを設定
initial_position = どこからデータを読み込むかの設定start_of_fileかend_of_fileのいずれかを指定
encoding = ログファイルのエンコーディング[ascii|utf_8|..]
buffer_duration = ログイベントのバッチ処理の期間。最小値:5000msでデフォルト。

fileにはワイルドカードを使って複数のファイルを定義することも可能です。CloudWatch Logsにログがプッシュされるのは、fileに定義されたファイルリストの内、変更日時が最新のものみのようです。そのため、Webサーバのアクセスログのようにaccess_log.2014-06-01-01, access_log.2014-06-01-02といったログはワイルドカードを使って同じタイプとして設定するのが推奨されてます。

今回はGlassfishのログを収集したかったので↓の設定を追加しました。

[/opt/glassfish4/glassfish/domains/domain1/logs/server.log]
datetime_format = %Y-%m-%d %H:%M:%S
file = /opt/glassfish4/glassfish/domains/domain1/logs/server.log* 
buffer_duration = 5000
log_stream_name = sample
initial_position = start_of_file
log_group_name = /opt/glassfish4/glassfish/domains/domain1/logs/server.log

変更を反映するにはagentを再起動する必要があります。

$ sudo service awslogs restart

再起動すると先ほどのManagement ConsoleにGlassfishのログが追加されているのが分かります。

料金体系

CloudWatch Logsではデータの収集とアーカイブに対してそれぞれ以下の料金(2014.11.18時点)が発生します。

  • ログデータの収集1GBあたり$0.5
  • ひと月のログアーカイブ1GBあたり$0.03
  • ログのデータ転送送信料(EC2からのデータ転送送信料と同額)

ログアーカイブはgzipで圧縮され保存されます。

 まとめ

インストールから設定までとても簡単にログ収集の仕組みを導入することが可能です。
ログ保管用のストレージ費用もS3ベースだからか安価で導入しやすく、ロググループ名やログストリーム名を適切に設定しておくことで、ログの確認もManagement Console経由で統一的に行なえます。また、収集したログに対して、Metric Filterを追加するこでログに指定した値が含まれるか判定するFilterを追加し、そのFilterを元にCloudWatch¥のアラームを作成するといったことも可能です。

現状はS3に定期的にバックアップを取ってるというケースでは是非CloudWatch Logsの利用をオススメします!