Skip to content

✍️ 필사 모드: Prometheus 서비스 디스커버리 메커니즘 완전 분석

한국어
0%
정확도 0%
💡 왼쪽 원문을 읽으면서 오른쪽에 따라 써보세요. Tab 키로 힌트를 받을 수 있습니다.

1. 개요

Prometheus의 서비스 디스커버리(Service Discovery)는 모니터링 타겟을 자동으로 발견하고 관리하는 핵심 서브시스템입니다. 클라우드 네이티브 환경에서 서비스 인스턴스가 동적으로 생성/삭제되므로, 정적 설정만으로는 모든 타겟을 추적할 수 없습니다.

이 글에서는 Discovery Manager의 아키텍처, Provider 인터페이스, 각 SD 구현체의 동작 방식, relabeling 메커니즘, 타겟 생명주기를 소스코드 레벨에서 분석합니다.

2. Discovery Manager 아키텍처

2.1 전체 구조

prometheus.yml의 scrape_configs
        |
        v
+-------------------+
| Discovery Manager |
|                   |
|  +-- Provider 1 (kubernetes_sd)  -- goroutine
|  +-- Provider 2 (consul_sd)     -- goroutine
|  +-- Provider 3 (file_sd)       -- goroutine
|  +-- Provider 4 (static_config) -- goroutine
|                   |
+--------+----------+
         |
    Target Groups Channel
         |
         v
+-------------------+
| Scrape Manager    |
+-------------------+

2.2 Discovery Manager의 역할

Discovery Manager는 다음을 담당합니다:

  1. 프로바이더 관리: 각 서비스 디스커버리 프로바이더의 생명주기 관리
  2. 업데이트 수집: 프로바이더로부터 타겟 그룹 변경 사항 수집
  3. 일괄 전달: 변경 사항을 버퍼링하여 Scrape Manager에 일괄 전달
  4. 설정 리로드: 새 설정 적용 시 프로바이더 재생성

2.3 업데이트 흐름

Provider 변경 감지
    |
    v
업데이트를 내부 채널로 전송
    |
    v
Discovery Manager가 수신
    |
    v
5초간 추가 업데이트 대기 (디바운싱)
    |
    v
모든 프로바이더의 최신 타겟 그룹 병합
    |
    v
Scrape Manager에 전체 타겟 맵 전달

디바운싱(debouncing)은 빈번한 변경이 발생하는 환경에서 Scrape Manager의 과도한 업데이트를 방지합니다.

3. Provider 인터페이스

3.1 Discoverer 인터페이스

모든 서비스 디스커버리 프로바이더는 Discoverer 인터페이스를 구현합니다:

type Discoverer interface {
    Run(ctx context.Context, up chan<- []*targetgroup.Group)
}

Run 메서드의 계약:

  • context가 취소될 때까지 실행을 유지
  • 타겟 그룹 변경 시 up 채널로 전체 그룹 목록 전송
  • 초기 실행 시 현재 알고 있는 전체 타겟 전송

3.2 TargetGroup 구조

TargetGroup:
  Source: "kubernetes/pod/default/nginx-abc123"  (고유 식별자)
  Targets:
    - __address__: "10.0.1.5:8080"
    - __address__: "10.0.1.6:8080"
  Labels:
    __meta_kubernetes_namespace: "default"
    __meta_kubernetes_pod_name: "nginx-abc123"
    ...

3.3 프로바이더 등록

프로바이더는 팩토리 함수로 등록됩니다:

등록 과정:
1. 설정 파일에서 *_sd_config 섹션 파싱
2. 해당 SD 타입의 NewDiscoverer 팩토리 호출
3. Discovery Manager에 프로바이더 등록
4. 별도 goroutine에서 Run() 실행

4. Kubernetes SD

4.1 kubernetes_sd 개요

Kubernetes SD는 Prometheus에서 가장 많이 사용되는 서비스 디스커버리입니다. Kubernetes API 서버의 Watch 메커니즘을 사용하여 리소스 변경을 실시간으로 감지합니다.

4.2 역할(Role) 타입

kubernetes_sd는 6가지 역할 타입을 지원합니다:

1. node:
   - Kubernetes 노드 목록
   - __address__: 노드의 Kubelet 주소
   - __meta_kubernetes_node_name, __meta_kubernetes_node_label_*

2. service:
   - Kubernetes Service 목록
   - __address__: Service의 ClusterIP:Port
   - __meta_kubernetes_service_name, __meta_kubernetes_service_port_name

3. pod:
   - Kubernetes Pod 목록
   - __address__: Pod IP:Container Port
   - __meta_kubernetes_pod_name, __meta_kubernetes_pod_container_name

4. endpoints:
   - Kubernetes Endpoints 목록
   - __address__: 개별 엔드포인트 주소
   - __meta_kubernetes_endpoints_name

5. endpointslice:
   - Kubernetes EndpointSlice 목록 (Endpoints의 확장형)
   - 대규모 클러스터에서 더 효율적

6. ingress:
   - Kubernetes Ingress 목록
   - __address__: Ingress 호스트
   - __meta_kubernetes_ingress_name, __meta_kubernetes_ingress_path

4.3 Watch 메커니즘

Kubernetes SD Watch 동작:

1. 초기 동기화:
   a. List API로 전체 리소스 목록 조회
   b. 모든 리소스를 TargetGroup으로 변환
   c. 전체 목록을 Discovery Manager에 전송

2. Watch 시작:
   a. Watch API로 이벤트 스트림 연결
   b. resourceVersion 기반 증분 업데이트

3. 이벤트 처리:
   ADDED   -> 새 TargetGroup 생성
   MODIFIED -> 기존 TargetGroup 업데이트
   DELETED  -> 빈 Targets로 TargetGroup 업데이트

4. 에러 처리:
   Watch 연결 끊김 -> 자동 재연결
   410 Gone 에러   -> 전체 재목록화(re-list)
   타임아웃        -> Watch 재시작

4.4 Informer/Reflector 패턴

kubernetes_sd는 client-go의 Informer 패턴을 활용합니다:

Informer 구조:
  Reflector
    |-- List: 초기 전체 동기화
    |-- Watch: 증분 업데이트 수신
    |-- Store: 로컬 캐시에 저장
    v
  Informer
    |-- EventHandler: 이벤트 콜백 등록
    |-- Indexer: 효율적인 검색을 위한 인덱스
    v
  Prometheus SD
    |-- 이벤트를 TargetGroup으로 변환
    |-- Discovery Manager에 전달

4.5 __meta 레이블

kubernetes_sd는 풍부한 메타 레이블을 제공합니다:

공통:
  __meta_kubernetes_namespace

Pod 역할:
  __meta_kubernetes_pod_name
  __meta_kubernetes_pod_ip
  __meta_kubernetes_pod_container_name
  __meta_kubernetes_pod_container_port_name
  __meta_kubernetes_pod_container_port_number
  __meta_kubernetes_pod_label_*
  __meta_kubernetes_pod_annotation_*
  __meta_kubernetes_pod_node_name
  __meta_kubernetes_pod_ready
  __meta_kubernetes_pod_phase

Node 역할:
  __meta_kubernetes_node_name
  __meta_kubernetes_node_label_*
  __meta_kubernetes_node_annotation_*
  __meta_kubernetes_node_address_*

Service 역할:
  __meta_kubernetes_service_name
  __meta_kubernetes_service_port_name
  __meta_kubernetes_service_port_number
  __meta_kubernetes_service_label_*
  __meta_kubernetes_service_annotation_*

5. Relabeling 메커니즘

5.1 Relabeling 개요

Relabeling은 타겟의 레이블을 변환하는 강력한 메커니즘입니다. 두 단계에서 적용됩니다:

1단계: relabel_configs (스크래핑 전)
  - 디스커버리에서 받은 __meta_* 레이블 처리
  - 타겟 레이블 결정 (job, instance 등)
  - 타겟 유지/삭제 결정

2단계: metric_relabel_configs (스크래핑 후)
  - 수집된 메트릭의 레이블 변환
  - 불필요한 메트릭 삭제
  - 레이블 이름/값 변환

5.2 Relabeling 액션

replace:     소스 레이블 값을 정규식 매칭 후 대상 레이블에 설정
keep:        정규식에 매칭되지 않는 타겟 삭제
drop:        정규식에 매칭되는 타겟 삭제
hashmod:     소스 레이블의 해시값을 모듈로 연산하여 대상 레이블에 설정
labelmap:    정규식에 매칭되는 레이블 이름을 변환
labeldrop:   정규식에 매칭되는 레이블 삭제
labelkeep:   정규식에 매칭되지 않는 레이블 삭제
lowercase:   대상 레이블 값을 소문자로 변환
uppercase:   대상 레이블 값을 대문자로 변환
keepequal:   소스와 대상 레이블 값이 같은 타겟만 유지
dropequal:   소스와 대상 레이블 값이 같은 타겟 삭제

5.3 Relabeling 처리 흐름

__meta_* 레이블 + __address__ + __scheme__ + __metrics_path__
                    |
                    v
          relabel_configs 순차 적용
                    |
                    v
          __address__ -> instance 레이블로 복사
          __scheme__, __metrics_path__ 등 내부 레이블 제거
                    |
                    v
          최종 타겟 레이블 셋 결정

5.4 일반적인 Relabeling 패턴

Pod 어노테이션 기반 스크래핑:

relabel_configs:
  # prometheus.io/scrape 어노테이션이 true인 Pod만 스크래핑
  - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
    action: keep
    regex: true
  # 포트 변경
  - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_port]
    action: replace
    target_label: __address__
    regex: (.+)
    replacement: __meta_kubernetes_pod_ip:$1
  # 경로 변경
  - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path]
    action: replace
    target_label: __metrics_path__
    regex: (.+)

네임스페이스 필터링:

relabel_configs:
  - source_labels: [__meta_kubernetes_namespace]
    action: keep
    regex: production|staging

6. File-based SD

6.1 개요

File SD는 JSON 또는 YAML 파일에서 타겟을 읽는 가장 단순한 동적 디스커버리입니다:

# prometheus.yml
scrape_configs:
  - job_name: 'file_sd'
    file_sd_configs:
      - files:
          - '/etc/prometheus/targets/*.json'
        refresh_interval: 5m

6.2 타겟 파일 형식

JSON 형식:

[
  {
    "targets": ["10.0.1.1:9090", "10.0.1.2:9090"],
    "labels": {
      "env": "production",
      "team": "backend"
    }
  }
]

YAML 형식:

- targets:
    - '10.0.1.1:9090'
    - '10.0.1.2:9090'
  labels:
    env: production
    team: backend

6.3 파일 감시 메커니즘

File SD 동작:
1. 초기 로드: 지정된 파일 패턴에 매칭되는 모든 파일 읽기
2. inotify 감시: Linux에서 파일 변경 이벤트 구독
3. 주기적 폴링: refresh_interval(기본 5분)마다 전체 재로드
4. 파일 변경 시: 변경된 파일만 재파싱하여 TargetGroup 업데이트
5. 파일 삭제 시: 해당 파일의 모든 타겟 제거

6.4 Custom SD Bridge 패턴

File SD는 커스텀 서비스 디스커버리의 브릿지로 활용됩니다:

커스텀 SD 프로세스 (외부):
1. 자체 서비스 레지스트리 조회
2. 결과를 JSON/YAML 파일로 생성
3. Prometheus가 감시하는 디렉토리에 저장

Prometheus (File SD):
1. 파일 변경 감지
2. 타겟 목록 업데이트
3. 스크래핑 시작/중지

이 패턴은 Prometheus에 직접 통합되지 않은 서비스 레지스트리(Zookeeper, etcd 등)와 연동할 때 유용합니다.

7. HTTP SD

7.1 개요

HTTP SD는 HTTP 엔드포인트에서 타겟 목록을 주기적으로 폴링합니다:

scrape_configs:
  - job_name: 'http_sd'
    http_sd_configs:
      - url: 'http://service-registry:8080/targets'
        refresh_interval: 30s

7.2 응답 형식

HTTP SD 엔드포인트는 JSON 배열을 반환해야 합니다:

[
  {
    "targets": ["10.0.1.1:9090"],
    "labels": {
      "__meta_datacenter": "us-east",
      "__meta_env": "production"
    }
  }
]

7.3 동작 방식

HTTP SD 처리:
1. refresh_interval마다 URL에 GET 요청
2. 응답 JSON 파싱
3. TargetGroup으로 변환
4. Discovery Manager에 전달
5. HTTP 에러 시 이전 결과 유지
6. 연속 실패 시 메트릭으로 알림

8. 기타 SD 구현체

8.1 Consul SD

Consul SD:
- Consul의 Service Catalog API 사용
- Watch/Blocking Query로 변경 감지
- 서비스 이름, 태그, 데이터센터 기반 필터링
- __meta_consul_service, __meta_consul_tags 등 메타 레이블

8.2 EC2 SD

EC2 SD:
- AWS EC2 DescribeInstances API 사용
- 리전, 가용 영역, 태그 기반 필터링
- IAM 역할 또는 액세스 키 인증
- __meta_ec2_instance_id, __meta_ec2_tag_* 등 메타 레이블
- refresh_interval 기반 폴링 (Watch 미지원)

8.3 DNS SD

DNS SD:
- DNS SRV 또는 A/AAAA 레코드 조회
- 주기적 폴링 방식
- 간단한 환경에서 유용
- __meta_dns_name 메타 레이블

8.4 Static Config

Static Config:
- 가장 단순한 타겟 정의 방식
- 설정 파일에 직접 타겟 주소 기입
- 테스트나 고정 인프라에 적합
- 동적 업데이트 불가 (리로드 필요)

9. 타겟 생명주기

9.1 타겟 상태 전이

타겟 생명주기:
  Discovered (발견됨)
      |
      v
  Relabeled (레이블 적용됨)
      |
      +-- 삭제 결정 --> Dropped (삭제됨)
      |
      v
  Active (활성화됨, 스크래핑 시작)
      |
      +-- 스크래핑 성공 --> up=1
      +-- 스크래핑 실패 --> up=0
      |
      v
  Disappeared (사라짐)
      |
      v
  Stale (stale marker 추가)
      |
      v
  Removed (Scrape Loop 종료)

9.2 Dropped 타겟

타겟이 삭제(Drop)되는 조건:

1. relabel_configs에서 drop 액션 적용
2. relabel_configs에서 keep 액션에 매칭되지 않음
3. __address__ 레이블이 비어있음
4. 중복 타겟 (동일 레이블 셋)

삭제된 타겟은 /targets UI의 "Dropped Targets" 섹션에 표시됩니다.
이를 통해 디스커버리와 relabeling 설정을 디버깅할 수 있습니다.

9.3 타겟 건강 상태 모니터링

내장 메트릭:
  up: 0 또는 1 (스크래핑 성공 여부)
  scrape_duration_seconds: 스크래핑 소요 시간
  scrape_samples_scraped: 수집된 샘플 수
  scrape_samples_post_metric_relabeling: relabeling 후 샘플 수
  scrape_series_added: 새로 추가된 시계열 수

API 엔드포인트:
  GET /api/v1/targets: 전체 타겟 목록과 상태
  GET /api/v1/targets/metadata: 타겟별 메트릭 메타데이터

10. 성능 고려사항

10.1 대규모 클러스터에서의 최적화

Kubernetes SD 성능 팁:
1. 네임스페이스 제한: namespaces 필드로 감시 범위 축소
2. 레이블 셀렉터: selectors 필드로 리소스 필터링
3. attach_metadata: 불필요하면 비활성화
4. EndpointSlice 사용: 대규모 클러스터에서 Endpoints보다 효율적

10.2 디스커버리 부하 모니터링

주요 메트릭:
  prometheus_sd_discovered_targets: 발견된 타겟 수 (SD 타입별)
  prometheus_sd_received_updates_total: 수신된 업데이트 수
  prometheus_sd_updates_total: 전달된 업데이트 수
  prometheus_sd_updates_delayed_total: 지연된 업데이트 수

경고 신호:
  - 발견된 타겟 수의 급격한 변동
  - 높은 업데이트 빈도
  - 지연된 업데이트 증가

11. 디버깅과 문제 해결

11.1 일반적인 문제

1. 타겟이 발견되지 않음:
   - SD 설정 확인 (namespace, selector 등)
   - Prometheus 로그에서 SD 에러 확인
   - /service-discovery UI 페이지에서 발견된 타겟 확인

2. 타겟이 Dropped 상태:
   - relabel_configs 규칙 순서 확인
   - keep/drop 액션의 regex 검증
   - /targets 페이지에서 Dropped Targets 확인

3. 타겟 레이블이 예상과 다름:
   - __meta_* 레이블 확인 (/service-discovery 페이지)
   - relabel_configs의 replace 규칙 확인
   - 레이블 충돌 시 honor_labels 설정 확인

11.2 디버깅 도구

1. /service-discovery UI:
   - 각 SD 프로바이더에서 발견된 원시 타겟 그룹 표시
   - __meta_* 레이블 전체 확인 가능

2. /targets UI:
   - 활성/삭제된 타겟 목록
   - 각 타겟의 건강 상태, 마지막 스크래핑 시간
   - 적용된 레이블 확인

3. Prometheus 로그:
   - --log.level=debug로 상세 SD 로그 활성화
   - SD 프로바이더별 연결/에러 로그

12. 정리

Prometheus의 서비스 디스커버리는 플러그인 아키텍처를 통해 다양한 인프라 환경을 지원합니다. Kubernetes SD의 Watch 메커니즘, relabeling의 강력한 레이블 변환, 그리고 File SD/HTTP SD를 통한 커스텀 확장이 핵심입니다.

다음 글에서는 Prometheus의 알림 파이프라인을 분석합니다. Rule Manager의 평가 메커니즘, Alert 상태 머신, Alertmanager의 라우팅과 알림 전달 과정을 살펴볼 예정입니다.

현재 단락 (1/356)

Prometheus의 서비스 디스커버리(Service Discovery)는 모니터링 타겟을 자동으로 발견하고 관리하는 핵심 서브시스템입니다. 클라우드 네이티브 환경에서 서비스 인스...

작성 글자: 0원문 글자: 8,650작성 단락: 0/356