

# Amazon ECS クラスターでの自動検出の詳細ガイド
<a name="ContainerInsights-Prometheus-Setup-autodiscovery-ecs"></a>

Prometheus には、[<scrape\$1config>](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#scrape_config)で説明されているように、多数の動的なサービス検出メカニズムが用意されています。ただし、Amazon ECS の組み込みサービス検出はありません。CloudWatch エージェントはこのメカニズムを追加します。

Amazon ECS Prometheus サービス検出を有効にするときに、CloudWatch エージェントは定期的に Amazon ECS および Amazon EC2 フロントエンドに対して次の API コールを行い、ターゲット ECS クラスターで実行中の ECS タスクのメタデータを取得します。

```
EC2:DescribeInstances
ECS:ListTasks
ECS:ListServices
ECS:DescribeContainerInstances
ECS:DescribeServices
ECS:DescribeTasks
ECS:DescribeTaskDefinition
```

このメタデータは、ECS クラスター内の Prometheus ターゲットをスキャンするために CloudWatch エージェントによって使用されます。CloudWatch エージェントは、次の 3 つのサービス検出モードをサポートします。
+ コンテナドッカーのラベルベースのサービス検出
+ ECS タスク定義 ARN 正規表現ベースのサービス検出
+ ECS サービス名正規表現ベースのサービス検出

すべてのモードを一緒に使用することができます。CloudWatch エージェントは、`{private_ip}:{port}/{metrics_path}` に基づいて検出されたターゲットの重複を解除します。

検出されたターゲットはすべて、CloudWatch エージェントコンテナ内の `sd_result_file` 設定フィールドで指定された結果ファイルに書き込まれます。次に、結果ファイルの例を示します。

```
- targets:
  - 10.6.1.95:32785
  labels:
    __metrics_path__: /metrics
    ECS_PROMETHEUS_EXPORTER_PORT: "9406"
    ECS_PROMETHEUS_JOB_NAME: demo-jar-ec2-bridge-dynamic
    ECS_PROMETHEUS_METRICS_PATH: /metrics
    InstanceType: t3.medium
    LaunchType: EC2
    SubnetId: subnet-123456789012
    TaskDefinitionFamily: demo-jar-ec2-bridge-dynamic-port
    TaskGroup: family:demo-jar-ec2-bridge-dynamic-port
    TaskRevision: "7"
    VpcId: vpc-01234567890
    container_name: demo-jar-ec2-bridge-dynamic-port
    job: demo-jar-ec2-bridge-dynamic
- targets:
  - 10.6.3.193:9404
  labels:
    __metrics_path__: /metrics
    ECS_PROMETHEUS_EXPORTER_PORT_SUBSET_B: "9404"
    ECS_PROMETHEUS_JOB_NAME: demo-tomcat-ec2-bridge-mapped-port
    ECS_PROMETHEUS_METRICS_PATH: /metrics
    InstanceType: t3.medium
    LaunchType: EC2
    SubnetId: subnet-123456789012
    TaskDefinitionFamily: demo-tomcat-ec2-bridge-mapped-port
    TaskGroup: family:demo-jar-tomcat-bridge-mapped-port
    TaskRevision: "12"
    VpcId: vpc-01234567890
    container_name: demo-tomcat-ec2-bridge-mapped-port
    job: demo-tomcat-ec2-bridge-mapped-port
```

この結果ファイルは、Prometheus ファイルベースのサービス検出と直接統合できます。Prometheus ファイルベースのサービス検出の詳細については、「[<file\$1sd\$1config>](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#file_sd_config)」を参照してください。

 結果ファイルが `/tmp/cwagent_ecs_auto_sd.yaml` に書き込まれたとします。次の Prometheus スクレイプ設定はそれを消費します。

```
global:
  scrape_interval: 1m
  scrape_timeout: 10s
scrape_configs:
  - job_name: cwagent-ecs-file-sd-config
    sample_limit: 10000
    file_sd_configs:
      - files: [ "/tmp/cwagent_ecs_auto_sd.yaml" ]
```

CloudWatch エージェントは、検出されたターゲットに対して次の追加ラベルも追加します。
+ `container_name`
+ `TaskDefinitionFamily`
+ `TaskRevision`
+ `TaskGroup`
+ `StartedBy`
+ `LaunchType`
+ `job`
+ `__metrics_path__`
+ Docker のラベル

クラスターの起動タイプが EC2 の場合、次の 3 つのラベルが追加されます。
+ `InstanceType`
+ `VpcId`
+ `SubnetId`

**注記**  
正規表現 `[a-zA-Z_][a-zA-Z0-9_]*` と一致しない Docker ラベルは除外されます。これは、Prometheus のマニュアルの「[構成ファイル](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#labelname)」 の `label_name` に記載されている Prometheus の規則と一致します。

## ECS サービス検出の設定例
<a name="ContainerInsights-Prometheus-Setup-autodiscovery-ecs-examples"></a>

このセクションでは、ECS サービスの検出を示す例について説明します。

**例 1**

```
"ecs_service_discovery": {
  "sd_frequency": "1m",
  "sd_result_file": "/tmp/cwagent_ecs_auto_sd.yaml",
  "docker_label": {
  }
}
```

この例では、Docker ラベルベースのサービス検出を有効にします。CloudWatch エージェントは、ECS タスクのメタデータを 1 分間に照会し、検出されたターゲットを CloudWatch エージェントコンテナ内の `/tmp/cwagent_ecs_auto_sd.yaml` ファイルに書き込みます。

`sd_port_label` セクションの `docker_label` のデフォルト値は `ECS_PROMETHEUS_EXPORTER_PORT` です。ECS タスク内の実行中のコンテナに `ECS_PROMETHEUS_EXPORTER_PORT` ドッカーラベルがある場合、CloudWatch エージェントはその値を `container port` として使用して、コンテナのすべての公開ポートをスキャンします。一致するものがある場合、マッピングされたホストポートとコンテナのプライベート IP を使用して、Prometheus エクスポータターゲットが `private_ip:host_port` の形式で構築されます。

`sd_metrics_path_label` セクションの `docker_label` のデフォルト値は `ECS_PROMETHEUS_METRICS_PATH` です。コンテナにこのドッカーラベルがある場合、その値は `__metrics_path__` として使用されます。コンテナにこのラベルがない場合は、デフォルト値 `/metrics` が使用されます。

`sd_job_name_label` セクションの `docker_label` のデフォルト値は `job` です。コンテナにこのドッカーラベルがある場合、その値はターゲットのラベルの 1 つとして追加され、Prometheus 設定で指定されたデフォルトのジョブ名が置き換えられます。このドッカーラベルの値は、CloudWatch Logs ロググループのログストリーム名として使用されます。

**例 2**

```
"ecs_service_discovery": {
  "sd_frequency": "15s",
  "sd_result_file": "/tmp/cwagent_ecs_auto_sd.yaml",
  "docker_label": {
    "sd_port_label": "ECS_PROMETHEUS_EXPORTER_PORT_SUBSET_A",
    "sd_job_name_label": "ECS_PROMETHEUS_JOB_NAME"  
  }
}
```

この例では、Docker ラベルベースのサービス検出を有効にします。CloudWatch エージェントは、ECS タスクのメタデータを 15 秒ごとに照会し、検出されたターゲットを CloudWatch エージェントコンテナ内の `/tmp/cwagent_ecs_auto_sd.yaml` ファイルに書き込みます。ドッカーラベルが `ECS_PROMETHEUS_EXPORTER_PORT_SUBSET_A` のコンテナがスキャンされます。ドッカーラベルが `ECS_PROMETHEUS_JOB_NAME` の値がジョブ名として使用されます。

**例 3**

```
"ecs_service_discovery": {
  "sd_frequency": "5m",
  "sd_result_file": "/tmp/cwagent_ecs_auto_sd.yaml",
  "task_definition_list": [
    {
      "sd_job_name": "java-prometheus",
      "sd_metrics_path": "/metrics",
      "sd_metrics_ports": "9404; 9406",
      "sd_task_definition_arn_pattern": ".*:task-definition/.*javajmx.*:[0-9]+"
    },
    {
      "sd_job_name": "envoy-prometheus",
      "sd_metrics_path": "/stats/prometheus",
      "sd_container_name_pattern": "^envoy$", 
      "sd_metrics_ports": "9901",
      "sd_task_definition_arn_pattern": ".*:task-definition/.*appmesh.*:23"
    }
  ]
}
```

この例では、ECS タスク定義 ARN 正規表現ベースのサービス検出をイネーブルにします。CloudWatch エージェントは、ECS タスクのメタデータを 5 分ごとに照会し、検出されたターゲットを CloudWatch エージェントコンテナ内の `/tmp/cwagent_ecs_auto_sd.yaml` ファイルに書き込みます。

2 つのタスク定義 ARN 通常記述セクションが定義されています。
+  最初のセクションでは、ECS タスク定義 ARN に `javajmx` が含まれる ECS タスクが、コンテナポートスキャン用にフィルタリングされます。これらの ECS タスク内のコンテナが 9404 または 9406 のコンテナポートを公開する場合、マップされたホストポートとコンテナのプライベート IP が Prometheus エクスポーターターゲットの作成に使用されます。`sd_metrics_path` の値は `__metrics_path__` から `/metrics` に設定します。したがって、CloudWatch エージェントは Prometheus メトリクスを `private_ip:host_port/metrics` からスクレイプし、スクレイプされたメトリクスは、`java-prometheus` ロググループ内の CloudWatch Logs の `/aws/ecs/containerinsights/cluster_name/prometheus` ログストリームに送信 されます。
+  2 番目のセクションでは、ECS タスク定義 ARN に `appmesh` があり、`version` の `:23` がある ECS タスクが、コンテナポートスキャン用にフィルタリングされます。コンテナポートを `envoy` 上に公開する `9901` という名前のコンテナの場合、マッピングされたホストポートとコンテナのプライベート IP が Prometheus エクスポーターターゲットの作成に使用されます。これらの ECS タスク内の値は、9404 または 9406 のコンテナポートを公開し、マッピングされたホストポートとコンテナのプライベート IP が Prometheus エクスポーターターゲットの作成に使用されます。`sd_metrics_path` の値は `__metrics_path__` から `/stats/prometheus` に設定します。したがって、CloudWatch エージェントは `private_ip:host_port/stats/prometheus` から Prometheus メトリクスをスクレイプし、スクレイプされたメトリクスをロググループ `envoy-prometheus` 内の CloudWatch Logs の `/aws/ecs/containerinsights/cluster_name/prometheus` ログストリームに送信します。

**例 4**

```
"ecs_service_discovery": {
  "sd_frequency": "5m",
  "sd_result_file": "/tmp/cwagent_ecs_auto_sd.yaml",
  "service_name_list_for_tasks": [
    {
      "sd_job_name": "nginx-prometheus",
      "sd_metrics_path": "/metrics",
      "sd_metrics_ports": "9113",
      "sd_service_name_pattern": "^nginx-.*"
    },
    {
      "sd_job_name": "haproxy-prometheus",
      "sd_metrics_path": "/stats/metrics",
      "sd_container_name_pattern": "^haproxy$",
      "sd_metrics_ports": "8404",
      "sd_service_name_pattern": ".*haproxy-service.*"
    }
  ]
}
```

この例では、ECS サービス名正規表現ベースのサービス検出を有効にします。CloudWatch エージェントは、ECS サービスのメタデータを 5 分ごとに照会し、検出されたターゲットを CloudWatch エージェントコンテナ内の `/tmp/cwagent_ecs_auto_sd.yaml` ファイルに書き込みます。

2 つのサービス名正規表現セクションが定義されています。
+  最初のセクションについて、正規表現 `^nginx-.*` に一致する名前を持つ ECS サービスに関連付けられた ECS タスクがコンテナポートスキャン用にフィルタリングされます。これらの ECS タスク内のコンテナが 9113 のコンテナポートを公開する場合、マップされたホストポートとコンテナのプライベート IP が Prometheus エクスポーターターゲットの作成に使用されます。`sd_metrics_path` の値は `__metrics_path__` から `/metrics` に設定します。したがって、CloudWatch エージェントは Prometheus メトリクスを `private_ip:host_port/metrics` からスクレイプし、スクレイプされたメトリクスは、`nginx-prometheus` ロググループ内の CloudWatch Logs の `/aws/ecs/containerinsights/cluster_name/prometheus` ログストリームに送信されます。
+  または、2 つ目のセクションについて、正規表現 `.*haproxy-service.*` に一致する名前を持つ ECS サービスに関連付けられた ECS タスクがコンテナポートスキャン用にフィルタリングされます。コンテナポートを 8404 上に公開する `haproxy` という名前のコンテナの場合、マッピングされたホストポートとコンテナのプライベート IP が Prometheus エクスポーターターゲットの作成に使用されます。`sd_metrics_path` の値は `__metrics_path__` から `/stats/metrics` に設定します。したがって、CloudWatch エージェントは Prometheus メトリクスを `private_ip:host_port/stats/metrics` からスクレイプし、スクレイプされたメトリクスは、`haproxy-prometheus` ロググループ内の CloudWatch Logs の `/aws/ecs/containerinsights/cluster_name/prometheus` ログストリームに送信されます。

**例 5**

```
"ecs_service_discovery": {
  "sd_frequency": "1m30s",
  "sd_result_file": "/tmp/cwagent_ecs_auto_sd.yaml",
  "docker_label": {
    "sd_port_label": "MY_PROMETHEUS_EXPORTER_PORT_LABEL",
    "sd_metrics_path_label": "MY_PROMETHEUS_METRICS_PATH_LABEL",
    "sd_job_name_label": "MY_PROMETHEUS_METRICS_NAME_LABEL"  
  }
  "task_definition_list": [
    {
      "sd_metrics_ports": "9150",
      "sd_task_definition_arn_pattern": "*memcached.*"
    }
  ]
}
```

この例では、両方の ECS サービス検出モードを有効にします。CloudWatch エージェントは、ECS タスクのメタデータを 90 秒ごとに照会し、検出されたターゲットを CloudWatch エージェントコンテナ内の `/tmp/cwagent_ecs_auto_sd.yaml` ファイルに書き込みます。

ドッカーベースのサービス検出設定の場合。
+ ドッカーラベル `MY_PROMETHEUS_EXPORTER_PORT_LABEL` 付きの ECS タスクは、Prometheus ポートスキャン用にフィルタリングされます。ターゲットの Prometheus コンテナポートは、ラベル `MY_PROMETHEUS_EXPORTER_PORT_LABEL` の値によって指定されます。
+ ドッカーラベル `MY_PROMETHEUS_EXPORTER_PORT_LABEL` の値は、`__metrics_path__` に使用されます。コンテナにこのドッカーラベルがない場合は、デフォルト値 `/metrics` が使用されます。
+ ドッカーラベル `MY_PROMETHEUS_EXPORTER_PORT_LABEL` の値は、ジョブラベルとして使用されます。コンテナにこのドッカーラベルがない場合は、Prometheus 設定で定義されたジョブ名が使用されます。

ECS タスク定義 ARN 正規表現ベースのサービス検出設定の場合。
+ ECS タスク定義 ARN `memcached` 内の ECS タスクは、コンテナポートスキャン用にフィルタリングされます。ターゲットの Prometheus コンテナポートは、`sd_metrics_ports` で定義されている 9150 です。デフォルトのメトリクスパス `/metrics` が使用されます。Prometheus 設定で定義されているジョブ名が使用されます。