こんにちは。小林です。
今年の夏は気温が高く、過ごしづらかったですが(毎年思う)、それも終わり、ブログの執筆が捗る涼しい季節となってきました。
それでは今回の内容ですが、
タイトルの通り「EC2(AmazonLinux2)内のログファイルをCloudWatchログに出力する」方法を紹介します。
※EC2やIAM、CloudWatchに関する基本的なことは理解している前提とします。
はじめに
もともと、EC2インスタンス内に出力されているログファイルを日に一度S3にアップロードをしていたのですが、ログ内に特定の文字列が出力された場合に通知をしたくなったことが事の発端です。
問題点
現状では以下の問題があります。
- 日に一度のアップロードのため、リアルタイムでの検知ができない
- (仮に1秒ごとにファイルをアップロードしたとしても)S3に格納されたファイルを解析する必要があり、手間がかかる
解決策
色々調べたところ、CloudWatchエージェントというものを使用して、CloudWatchログに出力することができる、ということがわかりました。
CloudWatchログに出力することができるのであれば、CloudWatchアラームにて文字列を検知すればよいので、かなり楽に実現することができます。
※CloudWatchログに出力するところまでとし、アラーム通知の設定に関しては割愛します。
CloudWatchエージェント
CloudWatchエージェントとは
統合 CloudWatch エージェントを使用すると、以下のことを実行できます。
- オペレーティングシステム全体で Amazon EC2 インスタンスから内部システムレベルのメトリクスを収集します。このメトリクスには、EC2 インスタンスのメトリクスに加えて、ゲスト内メトリクスを含めることができます。収集することができる追加のメトリクスについては、「CloudWatch エージェントにより収集されるメトリクス」を参照してください。
- オンプレミスサーバーからシステムレベルのメトリクスを収集します。これには、ハイブリッド環境のサーバーや によって管理されていないサーバーも含まれる可能性がありますAWS
- カスタムメトリクスは、
StatsDおよびcollectdプロトコルを使用して、アプリケーションまたはサービスから取得します。StatsDは、Linux サーバーと、Windows Server を実行するサーバーの両方でサポートされています。collectdは、Linux サーバーでのみサポートされています。- Linux または Windows Server を実行している Amazon EC2 インスタンスおよびオンプレミスサーバーから、ログを収集します。
引用:CloudWatch エージェントを使用した Amazon EC2 Instances インスタンスとオンプレミスサーバーからのメトリクスとログの収集
要するに、
- EC2インスタンスやオンプレミスのサーバからログやメトリクスを取得し、CloudWatchに出力することができる
ということになります。
インストール方法
既にパッケージが用意されているため、以下のコマンドで簡単にインストールできます。
sudo yum install amazon-cloudwatch-agent
/opt/aws/amazon-cloudwatch-agent/にインストールされます。
IAMポリシー
AWSが以下のポリシーを用意しているため、対象のインスタンスに設定しているIAMロールに紐づけてください。
CloudWatchAgentServerPolicy
設定ファイル
NGINXのアクセスログとエラーログをCloudWatchログに出力するために、必要最低限の設定を作成しましたので、それをベースに解説します。
ファイルの形式はJSON形式です。
| セクション | 項目 | 概要 | |||
|---|---|---|---|---|---|
| agent | region | 送信先のリージョンを指定。(EC2の場合)デフォルトはそのEC2インスタンスが存在するリージョン | |||
| run_as_user | 実行ユーザ。デフォルトはrootユーザ | ||||
| logs | log_stream_name | collect_list内にてログストリーム名が指定されなかった場合のデフォルト値を指定。必須項目 | |||
| force_flush_interval | ログをCloudWatchに出力するまでの最大秒数。バッファ内に溜めているログのサイズが1MBに達すると強制的に送信。デフォルト値は60(秒) | ||||
| logs_collected | files | 収集するログの情報を指定。collect_listの配列 | |||
| collect_list | log_group_name | 出力するロググループ名 | |||
| log_stream_name | 出力するログストリーム名 | ||||
| file_path | 対象のログファイル名 | ||||
| timezone | CloudWatchログに表示するタイムスタンプのタイムゾーンを指定。デフォルトはUTC | ||||
| timestamp_format | CloudWatchログに表示するタイムスタンプのフォーマット |
{
"agent": {
"region": "us-west-2",
"run_as_user": "root"
},
"logs": {
"log_stream_name": "{instance_id}",
"force_flush_interval": 5,
"logs_collected": {
"files": {
"collect_list": [
{
"log_group_name": "/ec2/output_log_in_ec2_to_cloudwatch",
"log_stream_name": "{instance_id}_access",
"file_path": "/var/log/nginx/access.log",
"timezone": "UTC",
"timestamp_format": "%Y/%m/%d %H:%M:%S"
},
{
"log_group_name": "/ec2/output_log_in_ec2_to_cloudwatch",
"log_stream_name": "{instance_id}_error",
"file_path": "/var/log/nginx/error.log",
"timezone": "UTC",
"timestamp_format": "%Y/%m/%d %H:%M:%S"
}
]
}
}
}
}
起動方法
以下のコマンドで起動します。
sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl \ -a fetch-config \ -m ec2 \ -s \ -c file:/opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.d/amazon-cloudwatch-agent.json
オプションはそれぞれ以下のようになっています。
a・・・最新の設定ファイルをロード-a fetch-config・・・-cオプションか-oオプション、もしくはその両方を指定
m・・・起動するサーバの種別(EC2/オンプレミス)を指定-m ec2・・・EC2を指定
s・・・起動c・・・設定ファイルの指定-c file:configuration_file_path・・・ローカルに配置されたファイルを指定
詳細や上記以外のオプションは--helpオプションにて確認ができます。
上記のコマンドを1度実行したあとは、systemctlコマンドにて起動停止を行うことができます。
補足
amazon-cloudwatch-agent-ctlコマンドを使用して起動した後に、設定ファイルに誤りを見つけ、修正しました。
しかし、systemctlコマンドを使用して、再起動をしたところ、修正内容が反映されていませんでした。
色々と調べていくと、-cオプションにて指定したJSONファイルを以下のTOMLファイルに一度変換してから、読み込まれているということがわかりました。
/opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.toml
設定ファイル(JSON)を編集しても、エージェントが読み込む設定ファイル(TOML)には反映されないため、いくら再起動しても設定が反映されないということです。
設定を変更した後には、必ずamazon-cloudwatch-agent-ctlコマンドを実行する必要があります。
起動結果
以下のように、NGINXにて出力されているログファイルの内容をCloudWatchログに出力ができるようになりました。

あとは、CloudWatchアラームにてアラーム設定をするだけで、通知をすることも可能になります。
おまけ
そういえば、みなさんはサーバの性能に関する状態を確認するのにCloudWatchを使用したことがあると思います。(ありますよね?)
しかし、(例えば)メモリ使用率のメトリクスは存在しないですよね?結構大事な項目だと思うのですが、、、
CloudWatchエージェントを使用するとこれらの値も取れるらしいです。
次回はこれをネタにブログを書こうと思います。

