

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

CloudWatch 에이전트는 메타데이터를 사용하여 ECS 클러스터 내에서 Prometheus 대상을 스캔합니다. CloudWatch 에이전트는 다음과 같은 세 가지 서비스 검색 모드를 지원합니다.
+ 컨테이너 Docker 레이블 기반 서비스 검색
+ 이 예에서는 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 시작 유형이 있는 경우 다음과 같은 레이블 세 가지가 추가됩니다.
+ `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 에이전트는 1분마다 한 번씩 ECS 태스크의 메타데이터를 쿼리하고 검색된 대상을 CloudWatch 에이전트 컨테이너 내의 `/tmp/cwagent_ecs_auto_sd.yaml` 파일에 씁니다.

`docker_label` 섹션에 있는 `sd_port_label`의 기본값은 `ECS_PROMETHEUS_EXPORTER_PORT`입니다. ECS 태스크의 실행 중인 컨테이너에 `ECS_PROMETHEUS_EXPORTER_PORT` Docker 레이블이 있는 경우 CloudWatch 에이전트는 해당 값을 `container port`로 사용하여 컨테이너의 노출된 포트를 모두 스캔합니다. 일치하는 항목이 있다면 매핑된 호스트 포트와 컨테이너의 프라이빗 IP를 사용하여 `private_ip:host_port` 형식으로 Prometheus Exporter 대상을 구성합니다.

`docker_label` 섹션에 있는 `sd_metrics_path_label`의 기본값은 `ECS_PROMETHEUS_METRICS_PATH`입니다. 컨테이너에 이 Docker 레이블이 있는 경우 해당 값을 `__metrics_path__`로 사용합니다. 컨테이너에 이 레이블이 없다면 기본값인 `/metrics`를 사용합니다.

`docker_label` 섹션에 있는 `sd_job_name_label`의 기본값은 `job`입니다. 컨테이너에 이 Docker 레이블이 있는 경우 해당 값은 대상에 대한 레이블 중 하나로 추가되어 Prometheus 구성에 지정된 기본 작업 이름을 대체합니다. 이 Docker 레이블의 값은 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 에이전트는 15초마다 ECS 태스크의 메타데이터를 쿼리하고 검색된 대상을 CloudWatch 에이전트 컨테이너 내의 `/tmp/cwagent_ecs_auto_sd.yaml` 파일에 씁니다. `ECS_PROMETHEUS_EXPORTER_PORT_SUBSET_A`의 Docker 레이블이 있는 컨테이너를 스캔합니다. Docker 레이블 `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 에이전트는 5분마다 ECS 태스크의 메타데이터를 쿼리하고 검색된 대상을 CloudWatch 에이전트 컨테이너 내의 `/tmp/cwagent_ecs_auto_sd.yaml` 파일에 씁니다.

다음과 같이 두 태스크 정의 ARN 정규 표현식 섹션이 정의됩니다.
+  첫 번째 섹션의 경우 ECS 태스크 정의 ARN에 `javajmx`가 있는 ECS 태스크가 컨테이너 포트 스캔에 대해 필터링됩니다. 이러한 ECS 태스크 내의 컨테이너가 9404 또는 9406의 컨테이너 포트를 노출하는 경우 컨테이너의 프라이빗 IP와 함께 매핑된 호스트 포트를 사용하여 Prometheus Exporter 대상을 생성합니다. `sd_metrics_path` 값은 `__metrics_path__`를 `/metrics`로 설정합니다. 따라서 CloudWatch 에이전트는 `private_ip:host_port/metrics`에서 Prometheus 지표를 스크레이프하고, 스크레이프한 지표를 CloudWatch Logs 로그 그룹 `/aws/ecs/containerinsights/cluster_name/prometheus`의 `java-prometheus` 로그 스트림에 전송합니다.
+  두 번째 섹션의 경우 ECS 태스크 정의 ARN에 `appmesh`가 있고 `version`이 `:23`인 ECS 태스크가 컨테이너 포트 스캔에 대해 필터링됩니다. `envoy`라는 이름의 컨테이너가 `9901`의 컨테이너 포트를 노출하는 경우 컨테이너의 프라이빗 IP와 함께 매핑된 호스트 포트를 사용하여 Prometheus Exporter 대상을 생성합니다. 이러한 ECS 태스크 내의 값은 9404 또는 9406의 컨테이너 포트를 노출하며, 컨테이너의 프라이빗 IP와 함께 매핑된 호스트 포트를 사용하여 Prometheus Exporter 대상을 생성합니다. `sd_metrics_path` 값은 `__metrics_path__`를 `/stats/prometheus`로 설정합니다. 따라서 CloudWatch 에이전트는 `private_ip:host_port/stats/prometheus`에서 Prometheus 지표를 스크레이프하고, 스크레이프한 지표를 CloudWatch Logs 로그 그룹 `/aws/ecs/containerinsights/cluster_name/prometheus`의 `envoy-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 에이전트는 5분마다 ECS 서비스의 메타데이터를 쿼리하고 검색된 대상을 CloudWatch 에이전트 컨테이너 내의 `/tmp/cwagent_ecs_auto_sd.yaml` 파일에 씁니다.

다음과 같이 두 서비스 이름 정규 표현식 섹션이 정의됩니다.
+  첫 번째 섹션의 경우 이름이 정규 표현식 `^nginx-.*`와 일치하는 ECS 서비스와 연결된 ECS 태스크가 컨테이너 포트 스캔에 대해 필터링됩니다. 이러한 ECS 태스크 내의 컨테이너가 9113의 컨테이너 포트를 노출하는 경우 컨테이너의 프라이빗 IP와 함께 매핑된 호스트 포트를 사용하여 Prometheus Exporter 대상을 생성합니다. `sd_metrics_path` 값은 `__metrics_path__`를 `/metrics`로 설정합니다. 따라서 CloudWatch 에이전트는 `private_ip:host_port/metrics`에서 Prometheus 지표를 스크레이프하고, 스크레이프한 지표를 CloudWatch Logs 로그 그룹 `/aws/ecs/containerinsights/cluster_name/prometheus`의 `nginx-prometheus` 로그 스트림에 전송합니다.
+  두 번째 섹션의 경우 이름이 정규 표현식 `.*haproxy-service.*`와 일치하는 ECS 서비스와 연결된 ECS 태스크가 컨테이너 포트 스캔에 대해 필터링됩니다. `haproxy`라는 이름의 컨테이너가 8404의 컨테이너 포트를 노출하는 경우 컨테이너의 프라이빗 IP와 함께 매핑된 호스트 포트를 사용하여 Prometheus Exporter 대상을 생성합니다. `sd_metrics_path` 값은 `__metrics_path__`를 `/stats/metrics`로 설정합니다. 따라서 CloudWatch 에이전트는 `private_ip:host_port/stats/metrics`에서 Prometheus 지표를 스크레이프하고, 스크레이프한 지표를 CloudWatch Logs 로그 그룹 `/aws/ecs/containerinsights/cluster_name/prometheus`의 `haproxy-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 에이전트는 90초마다 ECS 태스크의 메타데이터를 쿼리하고 검색된 대상을 CloudWatch 에이전트 컨테이너 내의 `/tmp/cwagent_ecs_auto_sd.yaml` 파일에 씁니다.

Docker 기반 서비스 검색 구성의 경우:
+ Docker 레이블 `MY_PROMETHEUS_EXPORTER_PORT_LABEL`이 있는 ECS 태스크가 Prometheus 포트 스캔에 대해 필터링됩니다. 대상 Prometheus 컨테이너 포트는 `MY_PROMETHEUS_EXPORTER_PORT_LABEL` 레이블의 값으로 지정합니다.
+ `__metrics_path__`에 Docker 레이블 `MY_PROMETHEUS_EXPORTER_PORT_LABEL`의 값을 사용합니다. 컨테이너에 이 Docker 레이블이 없다면 기본값인 `/metrics`를 사용합니다.
+ Docker 레이블 `MY_PROMETHEUS_EXPORTER_PORT_LABEL`의 값을 작업 레이블로 사용합니다. 컨테이너에 이 Docker 레이블이 없다면 Prometheus 구성에 정의된 작업 이름을 사용합니다.

ECS 태스크 정의 ARN 정규 표현식 기반 서비스 검색 구성의 경우:
+ ECS 태스크 정의 ARN에 `memcached`가 있는 ECS 태스크가 컨테이너 포트 스캔에 대해 필터링됩니다. 대상 Prometheus 컨테이너 포트는 `sd_metrics_ports`에 정의된 대로 9150입니다. 기본 지표 경로인 `/metrics`를 사용합니다. Prometheus 구성에 정의된 작업 이름을 사용합니다.