Amazon ECS(以下ECS)のメトリクスを収集する方法としてContainer Insightsがあります。Container Insightsは簡単に導入できてとても便利です。Container InsightsはこちらのAmazon ECS Container Insights メトリクスにある通り、多くのメトリクスを収集します。しかし、収集するメトリクスの種類を制限できません。また、メトリクスはカスタムメトリクスとしてAmazon CloudWatch(以下CloudWatch)に取り込まれます。サービス数やインスタンス数が増えてくるとメトリクスも大量となり利用料も嵩みます。

そこで、標準のContainer Insightsを使わずに基本的なメトリクスのみを収集することでコストを抑える方法を紹介します。メトリクスはContainer Insightsと同様、CloudWatchに集約します。サービス、タスク、インスタンスそれぞれの方法を紹介します。

サービスのメトリクス

サービスでよく収集するメトリクスとしては以下のものが考えられます。
  • サービスのCPU使用率
  • サービスのメモリ使用率
  • サービスのタスク数

これらサービスのメトリクスはECSの標準メトリクスで収集されています。サービスを起動後、CloudWatch Metricsを表示すると標準メトリクスにECS名前空間があります。ClusterName,ServiceNameのディメンションを選択すればサービス単位のCPU使用率を表すCPUUtilization、メモリ使用率を表すMemoryUtilizationが確認できます。

 

タスク数のメトリクスはありませんが、CPUUtilizationまたはMemoryUtilizationの統計をサンプル数にすればタスク数を確認できます。

タスクのメトリクス

サービスの単位だけでなく特定のタスクについてはタスク単位のメトリクスを収集したいこともあります。このような場合、AWS Distro for OpenTelemetry(通称ADOT)を使うと良いでしょう。OpenTelemetryはCNCFのプロジェクトの一つです。製品に依存しないテレメトリ(メトリクス、トレース、ログ)の収集と送信を行うための規格およびツールの作成をしています。AWS Distro for OpenTelemetryはAWSが開発したOpenTelemetryのディストリビューションです。

ADOTコレクターをサイドカーコンテナとしてタスクに含むことで、タスク単位で任意のメトリクスを収集できます。ADOTコレクターを使用してタスクのメトリクスを収集する手順を紹介します。全体的にはこちらのSetting up AWS Distro for OpenTelemetry Collector in Amazon Elastic Container Serviceを参考にしています。

各リソースを作成するTerraformコードやイメージ素材はこちらのmoriryota62/ecs-adot-collectorでも公開しています。

IAMの準備

ADOTコレクターをサイドカーで起動するため、タスクにはCloudWatchメトリクスの権限を与えたIAMロールを付与します。IAMロールには以下のIAMポリシーがあれば十分です。(ADOTドキュメントの例だとX-Rayの権限も含みます。X-Rayなどを使用しない場合は削除しても動作しました。) 以下IAMポリシーを作成した後、タスク実行用のIAMロールにIAMポリシーをアタッチします。ここで用意したタスク実行用のIAMロールはタスク定義で使用します。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "logs:PutLogEvents",
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:DescribeLogStreams",
                "logs:DescribeLogGroups",
                "cloudwatch:PutMetricData"
            ],
            "Resource": "*"
        }
    ]
}

イメージの作成

ADOTコレクターのコンテナイメージはこちらのamazon/aws-otel-collectorで提供されています。ADOTコレクターで収集するメトリクスは起動時に指定するコンフィグファイルで指定します。イメージ内にはあらかじめいくつかのテンプレートが用意されています。テンプレートの内容はGitHubのaws-observability/aws-otel-collectorで確認できます。コンフィグファイルの内容を修正すれば任意のメトリクスを指定できます。ADOTで収集できるタスクのメトリクスはこちらのGetting started using AWS ECS container metrics receiver in AWS OpenTelemetry Collectorにあります。タスクでよく収集するメトリクスとしては以下が考えられます。
  • CPU予約量
  • CPU使用量
  • メモリ予約量
  • メモリ使用量
今回は上記メトリクスだけを収集する以下内容のコンフィグファイル(custom-config.yaml)を作成します。コンフィグファイルを/etc/ecs/container-insights配下に配置したADOTコレクターイメージをビルドし、ビルドしたイメージをコンテナレジストリにプッシュしておきます。ここで用意したイメージはタスク定義で使用します。
receivers:
  awsecscontainermetrics:

processors:
  filter:
    metrics:
      include:
        match_type: strict
        metric_names:
          - ecs.task.memory.reserved
          - ecs.task.memory.utilized
          - ecs.task.cpu.reserved
          - ecs.task.cpu.utilized
  metricstransform:
    transforms:
      - include: ecs.task.memory.utilized
        action: update
        new_name: MemoryUtilized
      - include: ecs.task.memory.reserved
        action: update
        new_name: MemoryReserved
      - include: ecs.task.cpu.utilized
        action: update
        new_name: CpuUtilized
      - include: ecs.task.cpu.reserved
        action: update
        new_name: CpuReserved

  resource:
    attributes:
      - key: ClusterName
        from_attribute: aws.ecs.cluster.name
        action: insert
      - key: aws.ecs.cluster.name
        action: delete
      - key: TaskDefinitionFamily
        from_attribute: aws.ecs.task.family
        action: insert
      - key: aws.ecs.task.family
        action: delete
      - key: TaskId
        from_attribute: aws.ecs.task.id
        action: insert
      - key: aws.ecs.task.id
        action: delete

exporters:
  awsemf/performance:
    namespace: ECS/ContainerInsights
    log_group_name: '/aws/ecs/containerinsights/{ClusterName}/performance'
    log_stream_name: '{TaskDefinitionFamily}-{TaskId}'
    resource_to_telemetry_conversion:
      enabled: true
    dimension_rollup_option: NoDimensionRollup
    metric_declarations:
      - dimensions: [ [ ClusterName ], [ ClusterName, TaskDefinitionFamily ] ]
        metric_name_selectors:
          - MemoryUtilized
          - MemoryReserved
          - CpuUtilized
          - CpuReserved

service:
  pipelines:
    metrics/performance:
      receivers: [awsecscontainermetrics ]
      processors: [filter, metricstransform, resource]
      exporters: [ awsemf/performance ]

タスク定義

ADOTコレクターを含むタスク定義を作成します。設定はCreate ECS Task Definition for EC2 with ADOT CollectorCreate ECS Task Definition for Fargate with ADOT Collectorを参考にします。EC2タイプかFargateタイプかでタスク定義の内容が異なります。なお、EC2タイプ用のテンプレートに含まれるUDP 2000、TCP 4317、UDP 8125はそれぞれX-Ray、OpenTelemetry SDKs (OTLP)、StatsDで使用するポートです。これらを使用しない場合、ポート設定は不要です。(参考:Install ADOT Collector By Creating Task Definition Through AWS Console

ADOTコレクターのイメージを先ほどビルドしたイメージに修正します。また、コンテナの起動コマンドで作成したカスタムコンフィグファイルを–config=/etc/ecs/container-insights/custom-config.yamlで指定します。タスク実行ロールにはあらかじめ作成したタスク実行用のIAMロールを指定します。

動作確認

タスクを起動するとCloudWatchにコンテナのメトリクスが送られます。CloudWatch Metricsを表示するとカスタムメトリクスにECS/ContainerInsights名前空間があります。ClusterName,TaskDefinitionFamilyのディメンションを選択すればタスク単位のCPU予約量を表すCpuReserved、メモリ予約量を表すMemoryReserved、CPU使用量を表すCpuUtilized、メモリ使用量を表すMemoryUtilizedが確認できます。

インスタンスのメトリクス

インスタンス(EC2)のメトリクスを収集したいこともあります。この場合もADOTを使えば任意のメトリクスを収集できます。タスクメトリクスの収集の時とは違い、ADOTコレクターをメインにしたタスクをDAEMONで各インスタンスにスケジュールさせます。Setting up AWS Distro for OpenTelemetry Collector in Amazon Elastic Container Serviceを参考にしています。

各リソースを作成するTerraformコードやイメージ素材はこちらのmoriryota62/ecs-adot-collectorでも公開しています。

IAMの準備

IAMについてはタスクメトリクスと同様です。

イメージの作成

インスタンスメトリクスもADOTコレクターコンテナの中にテンプレート(otel-instance-metrics-config.yaml)が用意されています。テンプレートの内容はGitHubのaws-observability/aws-otel-collectorで確認できます。任意のメトリクスを収集したい場合はタスクメトリクスと同様、コンフィグファイルを作成してイメージをビルドすれば良いです。メトリクスの一覧はこちらのAWS Container Insights Receiverにあります。インスタンスメトリクスはそのままテンプレートを流用し、以下のメトリクスを収集します。そのため、コンテナイメージもamazon/aws-otel-collectorを使用します。

  • CPU使用率
  • メモリ使用率
  • ネットワーク流量(送受信の合計)
  • CPU予約量の割合
  • メモリ予約量の割合
  • タスク数
  • ファイルシステムの使用率

タスク定義

ADOTコレクターを含むタスク定義を作成します。設定はSetup the ADOT Collector for ECS EC2 instance Metricsを参考にします。

ADOTコレクターのイメージはamazon/aws-otel-collectorを指定し、起動コマンドで–config=/etc/ecs/otel-instance-metrics-config.yamlを指定します。タスク実行ロールにはあらかじめ作成したタスク実行用のIAMロールを指定します。

動作確認

サービスを起動するとすべてのEC2でADOTコレクタータスクが起動し、CloudWatchにインスタンスのメトリクスが送られます。CloudWatch Metricsを表示するとカスタムメトリクスにECS/ContainerInsights名前空間があります。ClusterName,ContainerInstanceId,InstanceIdのディメンションを選択すればインスタンス単位のCPU使用率を表すinstance_cpu_utilization、メモリ使用率を表すinstance_memory_utilization、ネットワークのトータルバイト数を表すinstance_network_total_bytes、CPU予約量の割合を表すinstance_cpu_reserved_capacity、メモリ予約量の割合を表すinstance_memory_reserved_capacity、タスク数を表すinstance_number_of_running_tasks、ファイルシステムの使用率を表すinstance_filesystem_utilizationが確認できます。