[AWS] ECSの環境で、ディスク使用量のメトリクスを収集してみる

# はじめに
ECSには、Container Insightsという、CloudWatchにメトリクスデータを流す機能があり、コンテナのメトリクスを収集する機能があります。
ところが、ここではディスク使用量について収集することができません（収集可能なメトリクスは後述）。
そこで、さくっとContainer Insightsを使わずにディスク使用量を収集する方法について書き残しておきます。

# メトリクスの収集
まず、EC2でもそうですが、デフォルトのままでは、インスタンスの中のメトリクスを収集することができません。
メトリクスを収集するためには、CloudWatch Agentをインスタンス内にインストール、起動するなどが必要です。
ECSの場合は、「はじめに」でも触れましたが、Container Insightsという機能があり、これをクラスターに適用すると、クラスター内のコンテナについてのメトリクスが収集できるようになります。

## Container Insightsで収集可能なメトリクス
では、Container Insightsで収集可能な標準的なメトリクスについて、まとめてみましょう。

|メトリクス名|内容|
|:--|:--|
| ContainerInstanceCount | 実行中EC2インスタンスの数 |
| CpuUtilized | CPUユニット数 |
| CpuReserved | 予約されているCPUユニット数 |
| DeploymentCount | デプロイ数 |
| DesiredTaskCount | 必要なタスク数 |
| MemoryUtilized | タスクで使用中のメモリサイズ |
| MemoryReserved | タスクにより予約されているメモリサイズ |
| NetworkRxBytes | ネットワーク受信バイト数 |
| NetworkTxBytes | ネットワーク送信バイト数 |
| PendingTaskCount | PENDING状態のタスク数 |
| RunningTaskCount | RUNNING状態のタスク数 |
| ServiceCount | サービス数 |
| StorageReadBytes | ストレージのReadバイト数 |
| StorageWriteBytes | ストレージのWriteバイト数 |
| TaskCount | タスク数 |
| TaskSetCount | タスクセット数 |

# クラスターのディスク使用量を収集してみよう
方法としては、CloudWatch Agentのコンテナをサイドカーとしてタスク化する、というイメージになります。

## 前提
- ECSクラスターは既に作成済みの前提とします
- aws cliを事前にローカル環境にダウンロードして、使えるようにしておいてください

## 手順
### IAMロールを作成する
まず、2つのIAMロールを作成します。

- ECSタスク用ロール

    名称は任意です。以下のPolicyを適用してください。

    - CloudWatchAgentServerPolicy

- ECSタスク実行用ロール

    名称は任意です。以下のPolicyを適用してください。

    - AmazonSSMReadOnlyAccess
    - AmazonECSTaskExecutionRolePolicy
    - CloudWatchAgentServerPolicy

### System Manager
パラメータストアにで、収集するメトリクスの情報を記述しておきます。
内容については、CloudWatch Agentの定義にしたがってください。

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

- 名前：任意
- 種類：String
- 値
ディスク使用量だけを収集する簡単な定義例

```json
{
  "metrics": {
    "metrics_collected": {
      "disk": {  
        "resources":[  
          "/",
          "/tmp"
        ],
        "measurement":[  
          "total",
          "used"
        ],
        "append_dimensions":{  
          "stackName":"Prod"
        }
      }
    }
  },
  "logs": {
    "metrics_collected": {
      "emf": {}
    }
  }
}
```

### タスクを定義する
続いては、クラスター内で実行するタスク定義の追加です。
このタスクは、CloudWatch Agentとして動作するサイドカーになります。

以下、サンプルですが、下記定義を、ローカルにファイル保存してください。

```json
{
    "family": "ecs-cwagent-ec2",
    "taskRoleArn": "ECSタスク用ロールのARN",
    "executionRoleArn": "ECSタスク実行用ロールのARN",
    "networkMode": "bridge",
    "containerDefinitions": [
        {
            "name": "cloudwatch-agent",
            "image": "amazon/cloudwatch-agent:latest",
            "secrets": [
                {
                    "name": "CW_CONFIG_CONTENT",
                    "valueFrom": "[System Managerパラメータストア名]"
                }
            ],
            "logConfiguration": {
                "logDriver": "awslogs",
                "options": {
                  "awslogs-create-group": "True",
                  "awslogs-group": "/ecs/ecs-cwagent-ec2",
                  "awslogs-region": "[リージョン]",
                  "awslogs-stream-prefix": "ecs"
                }
            }
        }
    ],
    "requiresCompatibilities": [
        "EC2"
    ],
    "cpu": "256",
    "memory": "256"
}
```

ECSタスク用ロールのARN、ECSタスク実行用ロールのARN、System Managerパラメータストア名は、上記で作成した各IAMロール、パラメメータストアの名前に従って設定してください。
リージョンは、クラスターを作成済みのリージョンにしてください。
あと、CPU/Memoryサイズは適当に変更して大丈夫です。

ファイルを保存したら、タスク定義を追加します。

```bash
aws ecs register-task-definition --cli-input-json file://タスク定義ファイル名  --region リージョン名
```

例

```bash
aws ecs register-task-definition --cli-input-json file://./ecs.txt  --region ap-northeast-1
```

### タスクを実行する

ここまできたら、最後にタスクを実行します。

```bash
aws ecs run-task --cluster ECSクラスタ名 --task-definition タスク定義名 --region リージョン --launch-type EC2
```

これで、しばらくたつと、CloudWatchにメトリクスが収集されだします。

### CloudWatch

メトリクスができてます！
<img width="988" alt="cw1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/427998/040373f9-6692-18fc-4f02-53edb8e0033d.png">
その中がこれ！
<img width="989" alt="cw2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/427998/963b904b-1f30-8818-86d2-2f7a3d1c779a.png">
展開すると、パラメータストアに定義したディスク総サイズと使用量が取得されています。
<img width="989" alt="cw3.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/427998/01add1a3-7a67-8200-a541-3a0e739052a9.png">

# 補足
## メトリクス間隔の調整

メトリクスの収集間隔は、デフォルトで60秒です。
この間隔を変更するには、System Managerのパラメータストアに設定した定義に

```json
      "disk": {  
        "resources":[  
          "/",
          "/tmp"
        ],
        "measurement":[  
          "total",
          "used"
        ],
        "append_dimensions":{  
          "stackName":"Prod"
        },
        "metrics_collection_interval": 10
      }
```

のように、`metrics_collection_interval`の定義を追加すればOKです。

[CloudWatch エージェントを使用した一般的なシナリオ](https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/CloudWatch-Agent-common-scenarios.html)