新しいCloudWatch AgentでEC2インスタンスのメモリ使用率を監視する

この記事は [**OpsJAWS Advent Calendar 2017**](https://qiita.com/advent-calendar/2017/opsjaws) 19日目の記事でした。

2018/10/01 時点の情報にUpdateしました。
2020/09/19 yum でのインストール方法を追記

#はじめに
2017年の12月に、新しいCloudWatch Agentが登場しました。
https://aws.amazon.com/jp/about-aws/whats-new/2017/12/amazon-cloudwatch-introduces-a-new-cloudwatch-agent-with-aws-systems-manager-integration-for-unified-metrics-and-logs-collection/

これまでディスク使用量やメモリ使用率といった仮想マシン上のメトリックについては
[CloudWatch Monitoring Scripts](https://aws.amazon.com/jp/code/amazon-cloudwatch-monitoring-scripts-for-linux/) 等 を設定してCloudWatchにデータを送信する必要がありました。
新しい Agent ではこれらのゲストOS上のメトリックについても収集できるようになっています。

収集可能なメトリックの一覧については以下のドキュメントを参照ください。
稼働対象(EC2 or On-premises)、OS、ログ取得レベルによっても取得出来る内容が異なります。

**CloudWatch エージェントにより収集されるメトリクス**
https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/metrics-collected-by-CloudWatch-agent.html

# やってみる
実際にAmazon Linuxサーバのメモリ使用率の監視設定を行ってみます。

## IAMロールの作成
CloudWatch Agent を実行する EC2 インスタンスにアタッチするための
IAM ロールを事前に作成しておきます。

~~まず、以下の内容でポリシーを作成します。ポリシー名は任意に設定します。~~

現在はAWS側で管理ポリシーが用意されているので、ロールにアタッチします。

* [CloudWatchAgentServerPolicy](https://console.aws.amazon.com/iam/home?region=us-east-1#/policies/arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy$jsonEditor)
* [CloudWatchAgentAdminPolicy](https://console.aws.amazon.com/iam/home?region=us-east-1#/policies/arn:aws:iam::aws:policy/CloudWatchAgentAdminPolicy$jsonEditor)

Agent の設定は AWS Systems Manager のパラメータストアに格納し、
他サーバに展開させることが可能です。
CloudWatchAgentServerPolicyとCloudWatchAgentAdminPolicyの違いですが、
CloudWatchAgentAdminPolicyは設定ファイルをパラメータストアへの書き込むための、
**ssm:PutParameter**権限を持っています。
通常、全てのインスタンスがパラメータストアへの書き込み権限を持つ必要はありませんので、
用途に応じて使い分けます。

後述するAgentインストールをAWS Systems Managerで行う場合は対象のIAMロールに
AmazonEC2RoleforSSMポリシーもアタッチしておきます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/125105/b1856678-aaba-c449-bee8-ce0083789343.png)

## CloudWactch Agent のインストール
先ほど作成したIAMロールを、インストール対象のEC2インスタンスに[アタッチ](http://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html#attach-iam-role)します。

Agent のインストール方法はいくつか用意されています。

* yum (Amazon Linux 2 のみ
* AWS Systems Managerによるインストール
* コマンドライン経由

複数台のインスタンスにインストールが必要な場合は Systems Managerによる
インストールがおすすめです。

### yum (Amazon Linux 2 のみ)
2020年9月以降、Amazon Linux 2 のパッケージとして CloudWatch Agent が含まれるようになりました。
yum コマンドで簡単にインストールできます。

```shell-session
sudo yum install amazon-cloudwatch-agent
```

### AWS Systems Managerによるインストール
対象のEC2にSSM Agentがインストールされていることを前提とします。
SSM Agentは Amazon Linux、Amazon Linux2、Ubuntu Server 16.04/18.04 ベースのAMI
であればデフォルトでインストールされています。
 
Systems Managerコンソールのランコマンドからコマンドの実行に遷移します。
コマンドのドキュメントの選択では AWS-ConfigureAWSPackage を選択します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/125105/dfd289b0-a8fa-108a-9621-75ff5d9172a4.png)

コマンドのパラメータで Name フィールドに、AmazonCloudWatchAgentを設定します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/125105/0dbf433b-d42d-b7d9-d1f3-f2924d983175.png)

ターゲットで対象のインスタンスを直接選択するか、複数台へのランコマンドであれば、
対象のインスタンスに含まれるタグを追加します
![image.png](https://qiita-image-store.s3.amazonaws.com/0/125105/21ff22e7-95e9-718f-f355-616859d02d32.png)

ランコマンドの完全なログを記録したい場合は、出力オプションにS3バケットを指定し、
コマンドを実行します。

ログからインストールが正常に終了したことを確認できます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/125105/c43f5414-c81b-639b-987b-8cbab3293e65.png)


### CLI による手動インストール
```shell-session
$ wget https://s3.amazonaws.com/amazoncloudwatch-agent/linux/amd64/latest/AmazonCloudWatchAgent.zip
$ unzip AmazonCloudWatchAgent.zip
$ sudo ./install.sh
```
## Agent 設定
### (オプション)プロキシ設定
プロキシを設定する必要がある環境の場合は、
/opt/aws/amazon-cloudwatch-agent/etc/common-config.tomlに設定します。

```toml:common-config.tml
[proxy]
http_proxy = "{http_url}"
https_proxy = "{https_url}"
no_proxy = "{domain}"
```
### Agent 設定ファイルの作成
Agent の設定ファイルは、収集するメトリックやログファイルを指定したファイルです。
JSONで作成されたファイルをAgent 起動時にTOMLに変換する形になります。
手動で作成することもできますが、ここではウィザードを使用して作成します。

```
$ sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-config-wizard
```

ウィザードでは以下を設定します。カッコ内は今回選択した内容です。
収集間隔は最短で1秒を指定できるようになっていますが、今回は60秒を選択しました。

* インストール先のOS（Linux）
* インストール先がEC2かオンプレミスか（EC2）
* StatsD デーモンを有効化するか（no）
* CollectD のメトリクスを監視するか（no）
* ホストのメトリクスを収集するか（yes）
* CPUコア毎のメトリクスを収集するか（yes）
* EC2ディメンションを全てのメトリクスに追加するか（yes）
* メトリクスを収集する間隔（60s）
* メトリクスの収集レベル（Standard）

2018年9月のアップデートでStatsD/CollectDによるカスタムメトリクスの送信に対応しましたが
今回はCloudWatchによる事前定義のメトリクスのみをStandardレベルで収集します。

**Amazon CloudWatch Agent adds Custom Metrics Support**
https://aws.amazon.com/jp/about-aws/whats-new/2018/09/amazon-cloudwatch-agent-adds-custom-metrics-support/

メトリクスの収集レベルによって取得できる事前定義のメトリクスが異なります。
詳細は以下のドキュメントを確認してください。

https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/create-cloudwatch-agent-configuration-file-wizard.html

### ログファイル監視対象の設定
既にCloudWatch Logs を使用している環境の場合は、
引き続きこのウィザードで設定を移行できます。
移行を行わない場合も監視対象のログファイルのパスを指定し、追加することができます。
ここでは デフォルト選択の syslog(/var/log/messages) を対象に指定し、
ログの監視設定を完了します。

設定ファイルは /opt/aws/amazon-cloudwatch-agent/bin/config.json に保存されます。
今回、最終的な設定内容は以下のようになります。

```json:config.json
{
        "logs": {
                "logs_collected": {
                        "files": {
                                "collect_list": [
                                        {
                                                "file_path": "/var/log/messages",
                                                "log_group_name": "messages"
                                        }
                                ]
                        }
                }
        },
        "metrics": {
                "append_dimensions": {
                        "AutoScalingGroupName": "${aws:AutoScalingGroupName}",
                        "ImageId": "${aws:ImageId}",
                        "InstanceId": "${aws:InstanceId}",
                        "InstanceType": "${aws:InstanceType}"
                },
                "metrics_collected": {
                        "cpu": {
                                "measurement": [
                                        "cpu_usage_idle",
                                        "cpu_usage_iowait",
                                        "cpu_usage_user",
                                        "cpu_usage_system"
                                ],
                                "metrics_collection_interval": 60,
                                "resources": [
                                        "*"
                                ],
                                "totalcpu": false
                        },
                        "disk": {
                                "measurement": [
                                        "used_percent",
                                        "inodes_free"
                                ],
                                "metrics_collection_interval": 60,
                                "resources": [
                                        "*"
                                ]
                        },
                        "diskio": {
                                "measurement": [
                                        "io_time"
                                ],
                                "metrics_collection_interval": 60,
                                "resources": [
                                        "*"
                                ]
                        },
                        "mem": {
                                "measurement": [
                                        "mem_used_percent"
                                ],
                                "metrics_collection_interval": 60
                        },
                        "swap": {
                                "measurement": [
                                        "swap_used_percent"
                                ],
                                "metrics_collection_interval": 60
                        }
                }
        }
}
```

### パラメータストアへの保存
ウィザードの最後に設定ファイルをSSM パラメータストアに保存するかの確認があります。
選択肢は全てデフォルトで問題ありません。

* 設定ファイルを SSM パラメータストアに保存するか（yes）
* パラメータストア名（AmazonCloudWatch-linux）
* 保存先リージョン（ap-northeast-1）
* AWSクレデンシャルの選択（From SDK）

IAMロールにAWS管理ポリシーを使用している場合は、Resource エレメントの記述に従い、
パラメータストア名が **AmazonCloudWatch-**ではじまる必要があります。

aws cliで手動アップロードすることも可能です。

```shell-session
$ cd /opt/aws/amazon-cloudwatch-agent/bin/
$ aws ssm put-parameter --name "AmazonCloudWatch-linux" --type "String" --value file://config.json
```

AWS Systems Manger のコンソールで、パラメータストアが保存されていることを確認します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/125105/dbd6dc15-8da6-8b11-3673-adef78712417.png)


### Agentの起動
SSMパラメータストアに保存した設定ファイルでAgentを起動してみます。

```shell-session
$ sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -c ssm:AmazonCloudWatch-linux -s
/opt/aws/amazon-cloudwatch-agent/bin/config-downloader --output-file /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json --download-source ssm:AmazonCloudWatch-linux --mode ec2 --config /opt/aws/amazon-cloudwatch-agent/etc/common-config.toml
Region: ap-northeast-1
credsConfig: map[]
Start configuration validation...
/opt/aws/amazon-cloudwatch-agent/bin/config-translator --input /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json --output /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.toml --mode ec2 --config /opt/aws/amazon-cloudwatch-agent/etc/common-config.toml
Valid Json input schema.
Configuration validation first phase succeeded
/opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent -schematest -config /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.toml
Configuration validation second phase succeeded
Configuration validation succeeded
amazon-cloudwatch-agent stop/waiting
amazon-cloudwatch-agent start/running, process 2222
```
メッセージの内容から、JSONの設定ファイルが
/opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.toml 
として保存されていることがわかります。

ログファイルは /opt/aws/amazon-cloudwatch-agent/logs/amazon-cloudwatch-agent.log 
に出力されています。
またAgentインストール時にサービス登録が行われていますが、

* common-config.toml
* amazon-cloudwatch-agent.toml 

の2ファイルが存在しないと、OS起動時にAgentが正常に起動できないようです。

ステータス確認、および終了コマンドは以下のように行うことができます。
また amazon-cloudwatch-agent.toml が作成されている状態であれば、
2回目以降の起動では設定ファイルのフェッチは不要です。

```shell-session
# ステータス確認
$ sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -m ec2 -a status
{
  "status": "running",
  "starttime": "2018-10-01T16:19:41+0000",
  "version": "1.203420.0"
}

# 停止
$ sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -m ec2 -a stop
amazon-cloudwatch-agent stop/waiting

# 起動
$ sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -m ec2 -a start
amazon-cloudwatch-agent start/running, process 3044
```

## 監視設定
コンソール上で取得したメトリックの確認および、アラームの設定を行います。
### メトリックの確認
カスタム名前空間の CWAgent を選択します。
少しわかりにくいですが、それぞれのメトリックを確認できます。

* ImageId, InstanceId, InstanceType, device, fstype, path: **Disk**
* ImageId, InstanceId, InstanceType, cpu: **CPU**
* ImageId, InstanceId, InstanceType, name: **Disk I/O**
* ImageId, InstanceId, InstanceType: **Memory**

![image.png](https://qiita-image-store.s3.amazonaws.com/0/125105/ad8f8a9a-51b1-f553-9779-747209db795a.png)

ImageId, InstanceId, InstanceType を選択すると、mem_used_percent および swap_used_percent の値を確認することができました。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/125105/c82ff117-fe16-d589-8fa1-1d224a67c640.png)

### アラームの設定
特に変わった手順はありません。
グラフ化したメトリクスからアクションのアラームの作成を選択します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/125105/9bbd6b9a-c35b-7b9d-49b2-20343ebe55a4.png)


アラーム名、閾値、間隔、通知先等を任意に設定し、アラームの作成を押下します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/125105/5dabb096-a347-4c33-7972-5d81d86726c6.png)

以上でメモリ使用率の監視設定が完了しました。
参考になれば幸いです。