CloudWatchエージェントでEC2インスタンスのカスタムメトリクスを取得する

EC2のCPU使用率やネットワークI/OなどはCloudWatchの標準メトリクスで監視可能ですが、メモリやディスクの使用率などはカスタムメトリクスを使用しなければ取得することができません。
今回は[CloudWatch エージェント](https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/Install-CloudWatch-Agent.html)を使用したカスタムメトリクスの収集方法を紹介します。

# カスタムメトリクス

EC2インスタンスのカスタムメトリクスを取得する方法は以下の方法があります。

- CloudWatch エージェントを使用する。
- AWSが配布している[CloudWatch Monitoring Script](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/mon-scripts.html)を使用する。
- [AWS SDK](https://docs.aws.amazon.com/ja_jp/sdk-for-java/v1/developer-guide/examples-cloudwatch-publish-custom-metrics.html)を使用してスクリプトを自作する。
- [AWS CLI](https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/publishingMetrics.html)を使用してスクリプトを自作する。

現在AWSでは、CloudWatch Monitoring Scriptなどのスクリプトを使用するのではなく、CloudWatch エージェントを用いてカスタムメトリクスを収集することを推奨しています。

# CloudWatch エージェント

インスタンスにCloudWatch エージェントをインストールすることで、メモリやディスクなどの標準メトリクスでは取得できないメトリクスやログを収集することができます。
CloudWatch エージェントを使用する利点としては以下があげられます。

- Amazon EC2インスタンスとオンプレミスサーバーからメトリクスとログを収集することができる
- LinuxとWindowsサーバーからメトリクスを収集することができる
- 設定値をAWS Systems Managerに保存できるため、複数のサーバーで同じ設定を共有することができる

個人的には3つ目のSystem Managerを使用することで、設定を他のサーバーでも共有できることがおすすめです。複数のサーバーの監視項目設定を一括で変更と反映ができます。

CloudWatch エージェントの導入プロセスは以下のようになります。

1. IAMロールの作成
2. インスタンスにCloudWatch エージェントをインストールする
3. AWS System Managerで設定ファイル(パラメーター)を作成する
4. CloudWatch エージェントを起動する

## IAMロールの作成

まずがIAMロールを作成します。
CloudWatch エージェントがCloudWatchにメトリクスを書込み、CloudWatch エージェントがEC2インスタンス及びSystem Managerと通信するために必要なアクセス権限を作成する必要があります。
ロールに設定するポリシーは以下の3つです。

- CloudWatchAgentServerPolicy
- AmazonEC2RoleforSSM
- AmazonSSMReadOnlyAccess

![role.PNG](https://qiita-image-store.s3.amazonaws.com/0/239179/e41ee2e6-3bc2-715f-58d7-e135ae4463b6.png)

ロール名は「CloudWatchAgentRole」とします。
IAMロール作成は割愛します。以下のサイトを参考にしてください。

[CloudWatch エージェントで使用する IAM ロールおよびユーザーを作成する](https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/create-iam-roles-for-cloudwatch-agent.html)

## インスタンスにCloudWatch Agentをインストールする

EC2インスタンスは`Red Hat Enterprise Linux 7.5 (HVM), SSD Volume Type`を利用します。

- instance Type : t2.micro
- IAM Role      : CloudWatchAgentRole

インスタンスには先ほど作成したIAMロールをアタッチします。
インストールを行うために、`wget`と`unzip`が必要なのでインストールします。

```
$ sudo yum install wget
$ sudo yum install unzip
```

次にCloudWatch エージェントをダウンロードし解凍とインストール用のシェルを起動します。

```
$ sudo mkdir /media/install
$ sudo mkdir /usr/share/cloudwatchagent
$ cd /media/install
$ sudo wget https://s3.amazonaws.com/amazoncloudwatch-agent/linux/amd64/latest/AmazonCloudWatchAgent.zip
$ sudo unzip AmazonCloudWatchAgent.zip -d /usr/share/cloudwatchagent
$ cd /usr/share/cloudwatchagent
$ sudo ./install.sh
```

シェルを実行するとRPM経由でCloudWatch Agentが`/opt/aws/amazon-cloudwatch-agent`のディレクトリにインストールされます。

```
$ cd /opt/aws/amazon-cloudwatch-agent
$ ls
bin  doc  etc  LICENSE  logs  NOTICE  RELEASE_NOTES  THIRD-PARTY-LICENSES  var
```

## AWS System Managerで設定ファイルを作成する

AWS System Mangerで収集するメトリクスとその収集間隔を設定します。今回はメモリ使用率(mem_used_percent)とディスク使用率(disk_used_percent)を収集します。
設定はJSON形式で記述します。
System Managerのコンソールからパラメーターストアに移動しパラメータの作成を行います。

![system_manager1.PNG](https://qiita-image-store.s3.amazonaws.com/0/239179/d61f8b6c-7a7d-cc04-44ef-f3d71291c298.png)

以下の設定を行い、パラメータの作成を押すと完了です。

- 名前   : CloudWatchAgentParemeter
- 説明   : Parameter for CloudWatchAgent
- タイプ : 文字列
- 値     : 以下のJson形式の文字列を張り付け

```
{
    "agent": {
        "metrics_collection_interval": 60,
        "region": "ap-northeast-1",
        "logfile": "/opt/aws/amazon-cloudwatch-agent/logs/amazon-cloudwatch-agent.log",
        "debug": false
    },
    "metrics": {
        "namespace":"CustmeMetrics Sample",
        "append_dimensions": {
            "ImageId": "${aws:ImageId}",
            "InstanceId": "${aws:InstanceId}",
            "InstanceType": "${aws:InstanceType}"
        },
        "metrics_collected": {
            "disk": {
                "measurement": [
                    "used_percent"
                ],
                "metrics_collection_interval": 60,
                "resources": [
                    "*"
                ]
            },
            "mem": {
                "measurement": [
                    "mem_used_percent"
                ],
                "metrics_collection_interval": 60
            }
        }
    }
}
```

![system_manager2.PNG](https://qiita-image-store.s3.amazonaws.com/0/239179/62c24c8a-7ba8-81e4-9be8-1607ac8aa233.png)


各項目について簡単に紹介しますが、設定ファイルの記述方法は以下のサイトに詳しく掲載されています。

[CloudWatch エージェント設定ファイルを手動で作成または編集する](https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/CloudWatch-Agent-Configuration-File-Details.html)

CloudWatch エージェントの設定ファイルは、agent、metrics、logsの3つのセクションからなるJSONファイルです。

- agent   : エージェントの全体的な設置に関するフィールド
- metrics : 収集するカスタムメトリクスの項目と収集間隔を設定するフィールド
- logs    : CloudWatch Logsに発行されるログファイルの設定をするフィールド

今回はログファイルの収集は行わないので省略しています。
`metrics`セクションでは収集するカスタムメトリクスについて以下の設定を行っています。

- `namespace`         : CloudWatchに表示されるメトリクスの名前空間の設定
- `append_dimensions` : メトリクスに付与するタグの設定
- `metrics_collected` : 収集するメトリクスの項目とその収集間隔の設定

カスタムメトリクスの収集の設定を行う`metrics_collected`タグについて、インスタンスのメモリ情報の取得を例に紹介します。

- `mem`                         : メモリを取得する設定。ディスクの情報を取得する際は`disk`と記述する。
- `measurement`                 : 取得するメトリクス名を設定。[CloudWatch エージェントにより収集されるメトリクス](https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/metrics-collected-by-CloudWatch-agent.html#linux-metrics-enabled-by-CloudWatch-agent)のメトリクス名を指定します。
- `metrics_collection_interval` : メトリクスの取得間隔を秒単位で設定します。

## CloudWatch エージェントを起動する

設定ファイルをSystem Managerで作成し終えると、あとはエージェントをインストールしたインスタンスで設定ファイルを指定してAgentを実行するのみです。
CloudWatch Agentの起動は以下のコマンドで行います。

```
$ sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -c ssm:CloudWatchAgentParemeter -s
```

`-a fetch-config`オプションでSystem Managerのパラメーターストアから設定ファイルを読み込むように指定し、`-c`オプションで設定ファイルを指定しています。指定方法は、`ssm:"パラメーター名"`となります。
以下のようなログが出力されれば成功です。

```
/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.
No log configuration found.
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
```

CloudWatch エージェントを停止するには以下のコマンドを実行します。

```
$ sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -m ec2 -a stop
```

## 確認

CloudWatchのコンソールからメトリクスに移動しカスタム名前空間を確認してください。
設定ファイルの`metrics`フィールドの`namespace`タグで設定した名前空間が作成されています。

![result1.PNG](https://qiita-image-store.s3.amazonaws.com/0/239179/707534ed-2ea1-f033-d750-18c1330cc1ae.png)

- メモリ使用率
![result_mem.PNG](https://qiita-image-store.s3.amazonaws.com/0/239179/a9944a28-eb4d-1acd-a76d-004fb314b502.png)

- ディスク利用率
![result_disck.PNG](https://qiita-image-store.s3.amazonaws.com/0/239179/d529f440-f589-616f-097a-d1d6fac37d76.png)


# まとめ

CloudWatch エージェントを使用してEC2インスタンスのカスタムメトリクスを取得する方法を紹介しました。
標準メトリクスと同様に、取得したメトリクスに対してアラームを設定すればカスタムメトリクスの監視を行うことができます。
スクリプトを使用または自作するよりも、設定が簡単でAutoScalingなどの冗長性にも簡単に対応できると思います。
また、CloudWatch エージェント自体のサーバーへの負荷も低いので安心して使用できると思います。