Blog

awslogsでEC2のログをCloudWatch連携する方法

技術ブログ

こんにちは、エンジニアのよこやまです。
EC2インスタンス内のログをawslogsでCloudWatch連携する方法について紹介します。

やりたいこと

  • ログをCloudWatchに送信する
  • CloudWatchでログを監視してSlackやメールでアラートする
  • 日々溜まっていくCloudWatchログを定期的にS3にエクスポートする

awslogs_image.png

ログをCloudWatchに送信する

Amazon LinuxのログのCloudWatch連携は、「awslogs」を使うと簡単に実現できます。以下のサイトを参考に、非常に簡単に主要なログをCloudWatch連携できました。
https://qiita.com/zaburo/items/57bf357065b7391e1a9d

まず、EC2にCloudWatchログ出力可能なロールを関連付けします。リファレンスを参考に、必要なポリシーを設定します。

ロールの関連付けをしたあとは、awslogsのインストール、confファイル修正、ログ出力の定義を設定してサービス起動して終了です。設定手順は以下の通りです。

※ 3行目の「awscli.conf」は、"region"を

region = us-east-1
↓
region = ap-northeast-1

に変更します。

※ 4行目の「awslogs.conf」は、以下のように取得したいログファイルの定義を追加します。

[HttpdAccessLog]
datetime_format = %d/%b/%Y:%H/%M/%S
file = /path/to/access_log.*
buffer_duration = 5000
log_stream_name = {instance_id}
initial_position = start_of_file
log_group_name = /HttpdAccessLog

[/var/log/messages]
datetime_format = %b %d %H:%M:%S
file = /var/log/messages
buffer_duration = 5000
log_stream_name = {instance_id}
initial_position = start_of_file
log_group_name = /var/log/messages

[/var/log/mysqld.log]
datetime_format = %Y-%m-%dT%H:%M:%S%z
file = /var/log/mysqld.log
buffer_duration = 5000
log_stream_name = {instance_id}
initial_position = start_of_file
log_group_name = /var/log/mysqld.log

[/var/log/supervisord.log]
datetime_format = %Y-%m-%d %H:%M:%S
file = /var/log/supervisord.log
buffer_duration = 5000
log_stream_name = {instance_id}
initial_position = start_of_file
log_group_name = /var/log/supervisord.log

[/var/log/audit/audit.log]
file = /var/log/audit/audit.log
buffer_duration = 5000
log_stream_name = {instance_id}
initial_position = start_of_file
log_group_name = /var/log/audit/audit.log

※awslogs.confの"file"にはログファイルのパスを記述します。
※awslogs.confの"datetime_format"は、対象ログから時刻を抽出する際に設定します。

日付書式設定については、リファレンスに記載されています。正しく設定ができていれば、CloudWatch上にログが出力されます。

awslogs1.png

CloudWatchでログを監視してSlackやメールでアラートする

CloudWatchログでは、指定されたものに一致する語句や値をログから検索できる「メトリクスフィルタ」と、フィルタ結果を基にアラート通知させる「アラーム」を設定することができます。

フィルタ設定内容はログによって様々なので、本記事では具体的な手順は記載しませんが、参考にさせていただいた記事を載せておきます。

Nginxの500系エラー検知
https://remotestance.com/blog/2433/

フィルタとパターン構文
https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/logs/FilterAndPatternSyntax.html

アラーム設定時に"アクション"で通知先のSNSトピックを設定することで、アラートのメール通知ができます。通知は、アラームの状態が変化する毎に通知されます。「警告(Alert)」「OK(OK)」それぞれ通知を設定しておくと、警告〜警告の解消が把握できるので便利です。

アラートのSlack通知は、Lambdaに標準で提供されているSlack通知用のBlueprint(cloudwatch-alarm-to-slack-python3)を使うと簡単に実現できます。

参考
http://blog.serverworks.co.jp/tech/2016/02/16/lambda-cloudwatch-alarm-to-slack/

このような感じでアラートがSlack通知されます(文面はBlueprintの"slack_message"をカスタマイズします)。

awslogs_slack.png

CloudWatchログを定期的にS3にエクスポートする

Amazon LinuxのログをCloudWatchに出力して監視もできましたが、このままではCloudWatch上に延々とログが蓄積されてしまうので、自動でS3にエクスポートしてCloudWatchログは一定期間のみ保持するようにします。

S3へのエクスポートはLambdaを使って自動化できますが、CloudWatchのCreateExportTaskは複数同時に実行できないため、1つエクスポートが終わってから次...と実行していく必要があります。
そのため、今回はStepFunctionsLambdaを組み合わせて実現します。

まずは、ログをエクスポートするS3バケットを作成します。また、作成したS3バケットに以下のようにバケットボリシーを設定しておきます。

次に、作成したS3バケットにCloudWatchログをエクスポートするLambda関数を作成します。
Lambdaは以下の通り作成しました(python3.6)。

参考
https://www.soudegesu.com/aws/export-cloudwatchlogs-to-s3/

なお、Lambdaには以下のIAMロールのポリシーを設定しました。

次に、ロググループ毎に上記Lambda関数を実行するStepFunctionsステートマシンを定義します。ステートマシンでは、ロググループ毎にcreate export taskを行い、タスクが処理中の場合は数秒待ってリトライを行います。

こちらは、上記参考サイトの手順そのままに実装して実現できました。
あとは、CloudWatchの「ルール>ルールの作成」で、

  • イベントソース:任意のパターン、スケジュール
  • ターゲット:Step Functions ステートマシン
  • ステートマシン:上記で作成したステートマシン

を設定すると、自動でCloudWatchログが定期的にS3エクスポートされます。

awslogs2.png

また、S3に過去ログを退避させることで、CloudWatchのログ保持期間やS3のライフサイクルルールを設定して、

  • CloudWatchログは1週間保持
  • S3にはログを3ヶ月保持

といった管理ができます。

以上が、CloudWatchへのログ出力からログ監視、S3へのエクスポートまでの連携方法でした。
いやぁ、ほんと便利ですね。

一覧にもどる