【AWS構築】CloudWatchによるEC2のメモリ/CPU/ディスク/ログ取得設定ハンズオン

# 目的
EC2の各種メトリクスをCloudWatchLogsを用いて監視したい
また、特定の閾値を上回った場合にはメールやSlackで通知したい

# 前提
・監視対象のEC2は2台(作成済みとする)
・メモリ/CPU/ディスクを監視
・閾値は80%とする。


# ハンズオン

## EC2のデフォルトのメトリクス
EC2は立ち上げた直後でCloudWatchにデフォルトで収集されるメトリクスがあります。
　・CPU使用率
　・ネットワーク受信・送信量
　・ディスク書き込み量
等...

これはEC2の『モニタリング』タブで確認可能
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3801383/926a7895-5431-466e-8673-adcafd2a77c4.png)

CloudWatchの『すべてのメトリクス』⇒『EC2』から各種メトリクスを確認できる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3801383/02ce07b3-fadd-4ebd-a189-eb310df495d5.png)


しかし、これ以外のメトリクスを取得するには各種設定を行う必要性があります。

## EC2のメトリクス拡張設定

### EC2にIAMロールをアタッチ
⭐「CloudWatchAgentAdminPolicy」ロールをEC2にアタッチが必要。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3801383/b14390bd-6474-486d-a215-7a557b66c5f7.png)
↑これを含めたIAMロールを作成

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3801383/be57f6c3-646a-4ce9-a8fa-1da6aea6e51d.png)
↑EC2の『アクション』⇒IAMロールをアタッチ

### EC2にCloudWatchAgentをインストール
⭐EC2にSSH接続を行い、CloudWatchAgentをインストール

```bash
sudo yum install amazon-cloudwatch-agent
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3801383/6a0dc21f-1c3e-4fe0-912e-9f853d6b78c1.png)
↑成功すると「Complete!」と表示。

次にCloudWatchAgentの起動＆設定ファイルを作成する。
```bash
sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-config-wizard
```

設定ファイルはウィザード（質問形式）で作成するので各種質問にコンソールで対話形式で回答する。
statDは今回はなしでOK

:::note
statsDとは？
OS上で動作する常駐プログラム（デーモン）であり、アプリケーションやシステムのパフォーマンスを監視・計測するために使用
UDPを使用しているため、軽量で高速なパフォーマンス取得が可能
ただし、サーバー側（Node.js等）でプログラムを用意する必要があるため敷居が高い。
:::

最後に設定ファイルの内容がコンソールに出力されて、yを押すと作成される

⭐CloudWatchの設定ファイルに関する公式ドキュメント
https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/CloudWatch-Agent-Configuration-File-Details.html

>CloudWatch エージェント設定ファイルは、agent、metrics、logs、traces の 4 つのセクションを持つ JSON ファイルです。
agent セクションには、エージェントの全体的な設定に関するフィールドが含まれています。
metrics セクションでは、収集と CloudWatch への発行に関するカスタムメトリクスを指定します。ログを収集するためだけにエージェントを使用している場合は、ファイルから metrics セクションを省略できます。
logs セクションでは、CloudWatch Logs に発行されるログファイルを指定します。サーバーで Windows Server が実行されている場合、これには Windows イベントログからのイベントが含まれることがあります。
traces セクションでは、収集されて AWS X-Ray に送信されるトレースのソースを指定します。

CloudWatchのログ収集に関する設定ファイルは『/opt/aws/amazon-cloudwatch-agent/bin/config.json』に存在
```bash
vim /opt/aws/amazon-cloudwatch-agent/bin/config.json
```

```config.json
{
        "agent": {
                "metrics_collection_interval": 10,
                "run_as_user": "cwagent"
        },
        "logs": {
                "logs_collected": {
                        "files": {
                                "collect_list": [
                                        {
                                                "file_path": "/var/log/*.log",
                                                "log_group_class": "STANDARD",
                                                "log_group_name": "/ec2/logs",
                                                "log_stream_name": "{instance_id}-{file_name}",
                                                "retention_in_days": 30
                                        }
                                ]
                        }
                }
        },
        "metrics": {
                "aggregation_dimensions": [
                        [
                                "InstanceId"
                        ]
                ],
                "append_dimensions": {
                        "AutoScalingGroupName": "${aws:AutoScalingGroupName}",
                        "ImageId": "${aws:ImageId}",
                        "InstanceId": "${aws:InstanceId}",
                        "InstanceType": "${aws:InstanceType}"
                },
                "metrics_collected": {
                        "collectd": {
                                "metrics_aggregation_interval": 60
                        },
                        "disk": {
                                "measurement": [
                                        "used_percent"
                                ],
                                "metrics_collection_interval": 10,
                                "resources": [
                                        "*"
                                ]
                        },
                        "mem": {
                                "measurement": [
                                        "mem_used_percent"
                                ],
                                "metrics_collection_interval": 10
                        }
                }
        }
```

適当に作成したのでlogファイルのパスがなかったり突っ込みどころが多いですが気にしないでください

:::note
・aggregation_dimensions
　⇒インスタンスIDごとにメトリクスを集約する
:::

:::note warn
        "agent": {
                "metrics_collection_interval": 10,
                "run_as_user": "cwagent"
                }
run_as_userでCloudWatchAgentが使用するユーザーを指定している。
このユーザーにlogファイルへのread権限がないとログが出力されないことに注意。
必要に応じてchmodで出力対象のログフォルダのパーミッションを適切に付与しよう。
:::


次にCollectDをインストール＆サービス起動する

⭐CollectDでのカスタムメトリクス収集
https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/CloudWatch-Agent-custom-metrics-collectd.html

```bash
sudo yum install collectd
sudo systemctl enable collectd.service
sudo systemctl start collectd.service
```

CloudWatchAgentを起動する。

```bash
sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl \
  -a start \
  -m ec2 \
  -c file:/opt/aws/amazon-cloudwatch-agent/bin/config.json
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3801383/7e411c91-0fe6-4506-86b0-ae38c18c7900.png)

↑成功した

```bash
Configuration validation second phase succeeded
Configuration validation succeeded
Created symlink /etc/systemd/system/multi-user.target.wants/amazon-cloudwatch-agent.service  → /etc/systemd/system/amazon-cloudwatch-agent.service.
```


### CloudWatchログ送信用VPCエンドポイント

EC2からCloudWatchにログを送信するにはインターネット向けの通信（NAT等）がない場合は専用のCloudWatch用VPCエンドポイントが必要になる

:::note
必要なのは下記3種類
１．com.amazonaws.ap-northeast-1.monitoring
２．com.amazonaws.ap-northeast-1.ec2
３．com.amazonaws.ap-northeast-1.logs

(東京リージョン）
:::
設定方法は大方同じなので今回はmonitoringのみを代表として説明する。

コンソール画面のVPCから『エンドポイント』⇒『エンドポイントの作成』

サービス名には『com.amazonaws.<リージョン名>.monitoring』を入力。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3801383/2bd76686-5326-4314-bed2-7f233d36b001.png)
↑東京リージョンなので『ap-northeast1』


エンドポイントをどのVPC・サブネットにアタッチするかを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3801383/39ac966f-fae1-4575-b7bd-024c9b4d4967.png)


セキュリティグループはVPC(サブネット)のCIDRからのHTTPS通信を許可すれば問題ない

エンドポイントポリシーは公式サイトに載っている下記をペースト

```json（monitoring)
{
  "Statement": [
    {
      "Sid": "PutOnly",
      "Principal": "*",
      "Action": [
        "cloudwatch:PutMetricData"
      ],
      "Effect": "Allow",
      "Resource": "*"
    }
  ]
}
```

Logsのエンドポイントのポリシー

```json(logs)
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowCloudWatchLogsPut",
      "Effect": "Allow",
      "Principal": "*",
      "Action": [
        "logs:CreateLogGroup",
        "logs:CreateLogStream",
        "logs:PutLogEvents",
        "logs:DescribeLogGroups",
        "logs:DescribeLogStreams"
      ],
      "Resource": "*"
    }
  ]
}
```

上記設定が完了すると、
エンドポイントを作成する

### 疎通確認
エンドポイントとEC2が疎通を取れているかどうかをcurlやdigで確認可能
まずは、dig
```bash
dig monitoring.ap-northeast-1.amazonaws.com
```

エンドポイントがVPC内で作成されているのであれば、VPCのIPアドレスがエンドポイントに払い出され、VPC内部のDNSにも登録されている。(10.0.0.0/16のIPアドレスが応答すればよい）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3801383/32ce0a8c-da60-4cff-ad09-25658d693501.png)
↑しっかりと返ってきている（AZが異なるサブネット2つにそれぞれエンドポイントがあるので2個返ってくる)

:::note
ちなみにエンドポイントを作成していないとこんな感じ
作ってないeventbridge用のエンドポイントで試してみる
```bash
dig events.ap-northeast-1.amazonaws.com
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3801383/de1bd0cd-53bc-40a3-8f9d-b746ae4dff28.png)
↑AWSのグローバルIPアドレスのエンドポイントが返ってくる
:::

### メトリクス・ログ確認

CloudWatchコンソール画面からメトリクスを選択

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3801383/5d3e428f-57b9-4fc5-bcb5-5624cde68504.png)
↑　CWAgentというカスタム名前空間が作成されている

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3801383/4b40a042-6d9a-4edc-90e3-24365cc4107d.png)
↑ディスクのパーティションごとにメトリクスが作成されている

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3801383/1500229d-0398-4006-a292-086041ec5614.png)
↑メモリ使用率（m
em_used_parcent)も取得できている



### ログストリーム（失敗?）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3801383/2f347048-1d68-4d3a-8d91-233c24d60e63.png)
↑/var/log/直下のログは取得できたが...ファイル名は環境変数として提供されていない模様
 日付単位でログを分ける等の処理はEC2側でCloudWatchLogsに送信するスクリプトを書くorログをSQLで分析するなどが必要か


:::note warn
 ログファイルのパーミッションでCloudwatchAgentで使用しているユーザーに読み取り権限がないとログは送信されない
:::


### おまけ（自分用）

CloudWatchAgent再起動コマンド（設定ファイル再読み込み）

```bash
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
```