【AWS】CloudWatch Logs で EC2 のログを集約する

背景

業務で CloudWatch Logs に触れる機会がありました。自分の AWS アカウントで再現したものをスクショとして張りつつ備忘録としておきます。最近は AI に聞けばいいだけなのですが、まあブログネタとして。

はじめに

EC2 でリソースの負荷状況に応じて、インスタンスの台数を増減させる Auto Scaling を実装しているサービスがあります。増えたインスタンスでエラーログが吐き出されたとき、調査を行う前にインスタンスが役目を終えて Terminate されてしまうとログごと消えてしまいます。このエラーログが発生したときに CloudWatch Logs に保管しておくことでログの消失を防ぐことができ、インシデントの調査がしやすくなります。

手順

CloudWatch agent の導入

まず使用している EC2 インスタンスに、CloudWatch agent を導入しましょう。

Download the CloudWatch agent package - Amazon CloudWatch
Explains how to use an Amazon S3 download link to install the CloudWatch agent.

AWS の記事ではsudo yum install amazon-cloudwatch-agentというコマンドでパッケージを導入していますが、私が導入したインスタンスの OS は Cent OS 7 だったので RPM 経由で導入しました。

# インストーラのダウンロード
wget https://amazoncloudwatch-agent.s3.amazonaws.com/centos/amd64/latest/amazon-cloudwatch-agent.rpm
// ...		 
   Saving to: 'amazon-cloudwatch-agent.rpm'
   
   100%[============================================================================================================>] 66,702,068  8.87MB/s   in 8.2s

# インストーラを使って導入
sudo rpm -U ./amazon-cloudwatch-agent.rpm

OS が分からない場合は下記辺りで分かるかも。

cat /etc/os-release

EC2 に CloudWatch を操作するための Role を割り当てる

インストールした agent は設定に応じた収集先からログを集めて、EC2 から CloudWatch Logs へ書き込みを行います。そのため、導入した EC2 自体に CloudWatch を操作するための権限を割り当てる必要があります。今回はドキュメントに提示されている、CloudWatchAgentServerPolicy を IAM で作って割り当てましょう。

IAM >ロール > ロールを作成 でロール作成画面に進みます。今回は画像のように、AWS のサービスとして、EC2 のユースケースを選びました。

CloudWatchAgentServer を検索して許可ポリシーに追加します。

その後は好ましい名前を命名して作成します。作成後、EC2 > Instances から作ったロールを割り当てましょう。

こちらで準備完了です。

agent を起動する

Manually create or edit the CloudWatch agent configuration file - Amazon CloudWatch
Explains how to manually create the CloudWatch agent configuration file, including the sections and settings inside the CloudWatch agent configuration file.

(ドキュメントでは、設定ファイルは amazon-cloudwatch-agent.json と名付けるのが好ましいと書いていますが、config.json という名前で作ってしまったので、今回はそのまま進めます)

インストールした agent に読ませるための設定ファイル config.json を用意します。

cd /opt/aws/amazon-cloudwatch-agent/bin/
sudo touch config.json

中身を編集しましょう。とりあえず最低限で。

# sudo vim config.json などで編集
{
  "agent": {
    "run_as_user": "root"
  },
  "logs": {
    "logs_collected": {
      "files": {
        "collect_list": [
          {
            "file_path": "/Laravelのログのパス/storage/logs/laravel-*.log",
            "log_group_name": "kir_thread_laravel_log",
            "log_stream_name": "{instance_id}"
          }
        ]
      }
    }
  }
}

こちらの config に沿って、agent がログを収集することになります。今回は Laravel でローテート設定しているエラーログを収集するような形で設定してみました。

  • run_as_user で root 指定することで、 root でないと読めないログの場所も読めるようにする
  • file_path は取得したいログのパスを書く
  • {instance_id} はそのまま書くことで、起動インスタンスの ID として agent に読ませる

実際にagentにconfigを読ませて起動させてみましょう。

# ステータスチェック
sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a status
{
  "status": "stopped", # 停止中
  "starttime": "",
  "configstatus": "not configured",
  "version": "1.300041.1"
}

# 起動する
sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -s -c file:/opt/aws/amazon-cloudwatch-agent/bin/config.json
// ...
****** processing amazon-cloudwatch-agent ******

# 再度ステータスを確認
sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a status
{
  "status": "running", # 起動した
  "starttime": "2026-04-07T15:32:39+00:00",
  "configstatus": "configured",
  "version": "1.300041.1"
}

起動しました。ちなみに失敗する場合は、config.json の構成ミスであることが多いです。

CloudWatch Logs で実際に確認する

設定出来たら実際に AWS で見てみましょう。CloudWatch > ログ管理 から、config.jsonlog_group_name として指定した名前でロググループが作られています。

階層に潜ると、ログストリームという階層で Instance ID ごとに仕分けされています。このおかげで、Auto Scaling で増減した場合でも ID ごとに保管してくれるので、ログが無くならずに管理できるようになるわけですね。

以上で終了です。

おわりに

アーキテクチャとしてはこのあと Firehose を使用して S3 バケットにログを保存する流れが基本です(CloudWatch Logs にログを保管し続けるより S3 に移したほうが安価)。あと上記で収集したログはずっと残りっぱなしになるので、ロググループの詳細 > 保持設定を編集 などでローテートを設定しておきましょう。

CloudWatch Logs で取得したログを Firehose を使って S3 に移行する処理についてはまた別の記事で書こうと思います。

コメント

タイトルとURLをコピーしました