Fusic Tech Blog

Fusion of Society, IT and Culture

ログファイルをCloudWatchで表示する
2020/12/12

ログファイルをCloudWatchで表示する

本記事はFusic Advent Calendar 2020の12日目の記事です。

前日の@kwashiさんの自律ロボット × 深層学習の記事、すごかったですね!

常々の論文を読んでる@kwashiさんらしい記事でした。まだ見てない、深層学習に興味ある方はぜひ読んでみてください!

というわけで本日の記事です。

初めまして、2020年7月からFusicに入社した小林です。

AWSの構築も数件関わらせて頂いたおかげか、先日AWS認定ソリューションアーキテクトに無事合格することができました。AWS初心者になりました!という気分です。

前職ではオンプレミス環境でWEBアプリケーションを構築することが多かったので、高負荷時にEC2をスケールアウトできるAuto Scaling最高だぜ!と感じてます。

ただ、便利とはいえスケールアウト・スケールインが発生する環境で障害が起こったときログを調査できるようにしておかないと原因調査も報告もできません。

スケールインでログファイルが消えても追えない!みたいなことでは困るので、今回はApacheとLaravelのログをCloudWatchで見れるようにしてみます。

事前準備

今回の設定に必要な以下は用意済みとします。

  • ログファイルを出力するEC2インスタンス

    • EC2でAmazon Linux 2 AMIのインスタンスを作成
    • EC2にApache、Laravelのインストール・設定済み

IAMロールを用意する

IAMロールで以下のポリシーをアタッチしたロールを用意します

  • CloudWatchAgentServerPolicy
  • CloudWatchAgentAdminPolicy

このIAMロールをEC2にアタッチしてください。

CloudWatchAgentのインストール

以下のドキュメンを参考にしてインストールを行います。

https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Install-CloudWatch-Agent.html

ログファイルを監視してCloudWatchに送るにはCloudWatchAgentが必要です。

というわけでEC2内でインストールします。

$ sudo yum -y install amazon-cloudwatch-agent

$ amazon-cloudwatch-agent-ctl
# usageが出ればOK!

CloudWatchAgentの設定ファイル作成

以下の記事を参考に設定ファイルを作成します。

https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/CloudWatch-Agent-Configuration-File-Details.html

ウィザードあるらしいので折角なので使ってみます(あとで結局、手動修正するのでウィザードに興味無い方はスキップOK!)

$ sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-config-wizard
=============================================================
= Welcome to the AWS CloudWatch Agent Configuration Manager =
=============================================================
On which OS are you planning to use the agent?
1. linux
2. windows
default choice: [1]:
1
# linux使うので1

Trying to fetch the default region based on ec2 metadata...
Are you using EC2 or On-Premises hosts?
1. EC2
2. On-Premises
default choice: [1]:
1
# EC2環境のインスタンスなので1

Which user are you planning to run the agent?
1. root
2. cwagent
3. others
default choice: [1]:
1
# root権限でagent動いてほしいので1

Do you want to turn on StatsD daemon?
1. yes
2. no
default choice: [1]:
2
# カスタムメトリクスを取得できるStatsDは今回使わないので2

Do you want to monitor metrics from CollectD?
1. yes
2. no
default choice: [1]:
2
# 統計情報も特に使わないので2

Do you want to monitor any host metrics? e.g. CPU, memory, etc.
1. yes
2. no
default choice: [1]:
2
# ホストメトリクスは使わないので2

Do you have any existing CloudWatch Log Agent (http://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/AgentReference.html) configuration file to import for migration?
1. yes
2. no
default choice: [2]:
2
# 新規作成なので2

Do you want to monitor any log files?
1. yes
2. no
default choice: [1]:
1
# ログファイルをモニターしたいので1
# ここからモニターしたいファイルを指定する

Log file path:
/var/log/httpd/access_log
# ログファイルのパス
Log group name:
default choice: [access_log]
# ロググループ名
ec2_httpd_access_log
Log stream name:
default choice: [{instance_id}]
# ログストリーム名

Do you want to specify any additional log files to monitor?
1. yes
2. no
default choice: [1]:
1
Log file path:
/var/log/httpd/error_log
Log group name:
default choice: [error_log]
ec2_httpd_error_log
Log stream name:
default choice: [{instance_id}]

Do you want to specify any additional log files to monitor?
1. yes
2. no
default choice: [1]:
2

Saved config file to /opt/aws/amazon-cloudwatch-agent/bin/config.json successfully.
Current config as follows:
{
	"agent": {
		"run_as_user": "root"
	},
	"logs": {
		"logs_collected": {
			"files": {
				"collect_list": [
					{
						"file_path": "/var/log/httpd/access_log",
						"log_group_name": "ec2_httpd_access_log",
						"log_stream_name": "{instance_id}"
					},
					{
						"file_path": "/var/log/httpd/error_log",
						"log_group_name": "ec2_httpd_error_log",
						"log_stream_name": "{instance_id}"
					}
				]
			}
		}
	}
}
Please check the above content of the config.
The config file is also located at /opt/aws/amazon-cloudwatch-agent/bin/config.json.
Edit it manually if needed.
Do you want to store the config in the SSM parameter store?
1. yes
2. no
default choice: [1]:
1
# SSMparameterをstoreに保存

What parameter store name do you want to use to store your config? (Use 'AmazonCloudWatch-' prefix if you use our managed AWS policy)
default choice: [AmazonCloudWatch-linux]

Trying to fetch the default region based on ec2 metadata...
Which region do you want to store the config in the parameter store?
default choice: [ap-northeast-1]

Which AWS credential should be used to send json config to parameter store?
1. XXXXXXXXXXXXXXXXXXXX(From SDK)
2. Other
default choice: [1]:
1
Please make sure the creds you used have the right permissions configured for SSM access.
Which AWS credential should be used to send json config to parameter store?
1. XXXXXXXXXXXXXXXXXXXX(From SDK)
2. Other
default choice: [1]:
1
Successfully put config to parameter store AmazonCloudWatch-linux.
Program exits now.

Apacheのアクセスログとエラーログの2つ設定して完了。

/opt/aws/amazon-cloudwatch-agent/bin/config.jsonのファイルを実際に見てみるとこんな感じでてました。

{
        "agent": {
                "run_as_user": "root",
        },
        "logs": {
                "logs_collected": {
                        "files": {
                                "collect_list": [
                                        {
                                                "file_path": "/var/log/httpd/access_log",
                                                "log_group_name": "ec2_httpd_access_log",
                                                "log_stream_name": "{instance_id}",
                                        },
                                        {
                                                "file_path": "/var/log/httpd/error_log",
                                                "log_group_name": "ec2_httpd_error_log",
                                                "log_stream_name": "{instance_id}",
                                        }
                                ]
                        }
                }
        }
}

CloudWatchAgentの起動

設定ファイルを作ったので、これを元にCloudWatchAgentを起動します。

$ sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -c file:/opt/aws/amazon-cloudwatch-agent/bin/config.json -s

# -a fetch-config: 1つ目の設定ファイルを指定する
# -m ec2: ec2がhostのモード
# -c file:${filepath} ファイルパス(設定のjsonファイル)
# -s :オプションでエージェントを設定して再起動する

# 起動確認
$ sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -m ec2 -a status
{
  "status": "running",
  "starttime": "2020-12-08T08:11:09+0000",
  "version": "1.247345.35"
}

# systemctlでも見れます
$ sudo systemctl status amazon-cloudwatch-agent

# 停止する場合は以下どちらか
$ sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -m ec2 -a stop
$ sudo systemctl stop amazon-cloudwatch-agent

\ というわけで起動したので、AWSのコンソールから見てみます。

ロググループとログストリームが作られてました!

そしてログストリームを選択してログを見てみると・・・

ログが取れてますね!

ただ、ログを見てみるとCloudWatchのタイムスタンプとメッセージ内のタイムスタンプが異なっています。

これだとCloudWatch上からフィルターするとき困るので揃えるためにtimestamp_formatの設定をconfig.jsonに追加してみましょう。

{
        "agent": {
                "run_as_user": "root",
        },
        "logs": {
                "logs_collected": {
                        "files": {
                                "collect_list": [
                                        {
                                                "file_path": "/var/log/httpd/access_log",
                                                "log_group_name": "ec2_httpd_access_log",
                                                "log_stream_name": "{instance_id}",
                                                timestamp_format": "%d/%b/%Y:%H:%M:%S %z"
                                        },
                                        {
                                                "file_path": "/var/log/httpd/error_log",
                                                "log_group_name": "ec2_httpd_error_log",
                                                "log_stream_name": "{instance_id}",
                                                timestamp_format": "%d/%b/%Y:%H:%M:%S %z"
                                        }
                                ]
                        }
                }
        }
}

この設定ファイルで再度fetch-configしてCloudWatchAgentを起動すると・・・

揃いましたね!

Agentが動いてない、という人は/opt/aws/amazon-cloudwatch-agent/logs/ディレクトリにログ出てるので確認してみてください。

Laravelのログファイル監視に追加してみる

次にLaravelのログファイルも追加してみましょう。

/opt/aws/amazon-cloudwatch-agent/bin/config.jsonにLaravelログファイルの設定を追加します。

{
        "agent": {
                "run_as_user": "root",
        },
        "logs": {
                "logs_collected": {
                        "files": {
                                "collect_list": [
                                        {
                                                "file_path": "/var/log/httpd/access_log",
                                                "log_group_name": "ec2_httpd_access_log",
                                                "log_stream_name": "{instance_id}",
                                                timestamp_format": "%d/%b/%Y:%H:%M:%S %z"
                                        },
                                        {
                                                "file_path": "/var/log/httpd/error_log",
                                                "log_group_name": "ec2_httpd_error_log",
                                                "log_stream_name": "{instance_id}",
                                                timestamp_format": "%d/%b/%Y:%H:%M:%S %z"
                                        },
                                        {
                                                "file_path": "/var/www/html/logsample/storage/logs/laravel.log",
                                                "log_group_name": "laravel_log",
                                                "log_stream_name": "{instance_id}",
                                                "timestamp_format": "[%Y-%m-%d %H:%M:%S]",
                                                "multi_line_start_pattern": "{timestamp_format}"
                                        }
                                ]
                        }
                }
        }
}

Apacheのログとは少し設定が違いますね。

multi_line_start_patternは複数行のログファイルを1行としてまとめてくれるものです。

LaravelのログではExceptionログやarrayのログなどが複数行で表示されるため、そのための設定になります。

設定してないと・・

こんな感じで複数行になっちゃいますね。これは見づらい&フィルターしづらいですね。

というわけでmulti_line_start_patternをつけると・・・

1行になってますね!

最後の設定

これで設定はできたのですが、最後にやることがあります。

まず忘れず自動起動設定。

$ sudo systemctl enable amazon-cloudwatch-agent

よし!これで設定完了!と言いたいところですが、以下を忘れず実施しましょう。

  • Apacheを停止して、監視するログを掃除する

これをやってないとEC2をAMIイメージを作ってAuto Scalingした際にすでにあるファイル内容まで出てしまうので忘れず削除しましょう。

まとめ

これで当初の目的であるCloudWatchにログを送れることができました。

CloudWatchはCloudWatch EventやLambdaなど使ってできることもまだまだあるので使いこなせると出来ることが増えていくでしょう。

構築ももちろん大事ですが運用観点も重要なので、自分もまだまだ勉強していきたいと思います。

このTechBlog内で他にもCloudWatchの記事があるので興味ある方はぜひ御覧ください。

fumiya kobayashi

fumiya kobayashi

Company: Fusic CO., LTD.