Post

[Monitoring] ServiceMonitor 완전 정리: Prometheus Operator 메트릭 자동 수집

📌 들어가며

이번 글에서는 Prometheus가 모니터링 대상을 자동으로 발견하게 해주는 ServiceMonitor를 정리한다. Prometheus 설정 파일을 직접 고치지 않고, YAML 선언만으로 타겟을 관리하는 방식이다. 기본 구조부터 Relabeling·Spring Boot 연동·트러블슈팅까지 다룬다.

ServiceMonitor란? Prometheus Operator가 모니터링 대상을 자동 발견·수집하기 위한 CRD. ServiceMonitor를 만들면 Operator가 이를 감지해 Prometheus 설정을 자동 업데이트(Hot Reload)하고, Service의 Endpoint를 스크래핑한다.

flowchart LR
    SM["ServiceMonitor(CRD)"] --> Op["Prometheus Operator<br/>(Watch)"]
    Op --> Cfg["Prometheus 설정<br/>자동 업데이트(Hot Reload)"]
    Cfg --> Ep["Service Endpoint 스크래핑"]

1. 핵심 개념

Operator의 역할

ServiceMonitor·PodMonitor·PrometheusRule 같은 CRD를 Watch하며, Prometheus Pod 재시작 없이 설정을 반영한다.

ServiceMonitor vs PodMonitor

항목ServiceMonitorPodMonitor
타겟Service → EndpointPod 직접
사용Service가 있는 경우(일반)Service 없이 Pod만
웹앱·API 서버StatefulSet·DaemonSet

💡 선언적 설정이 핵심이다. 예전엔 Prometheus 설정 파일에 타겟을 직접 적었지만, ServiceMonitor는 앱 배포 시 모니터링도 YAML로 함께 선언해 자동화한다. 앱이 늘어도 설정을 손댈 필요가 없다.


2. 기본 구조 — Label로 연결

ServiceMonitor의 selector와 Service의 labels, endpoints.port와 Service의 ports.name반드시 일치해야 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: my-app-monitor
  labels:
    prometheus: kube-prometheus   # Prometheus가 선택할 Label
spec:
  selector:
    matchLabels:
      app: my-app                 # ← Service의 label과 일치
  namespaceSelector:
    matchNames: [default]
  endpoints:
  - port: metrics                 # ← Service의 port name과 일치
    interval: 30s
    path: /metrics
1
2
3
4
5
6
7
8
9
10
11
apiVersion: v1
kind: Service
metadata:
  name: my-app-service
  labels:
    app: my-app                   # ← selector와 일치
spec:
  ports:
  - name: metrics                 # ← endpoints.port와 일치
    port: 8080
    targetPort: 8080
flowchart LR
    SM["ServiceMonitor<br/>selector: app=my-app<br/>port: metrics"]
    Svc["Service<br/>labels: app=my-app<br/>port name: metrics"]
    SM -- "Label 매칭" --> Svc --> Pod["Pod /metrics"]

3. 주요 패턴

패턴방법
여러 엔드포인트endpoints에 포트별(app/jvm/custom) 여러 항목
여러 네임스페이스namespaceSelector.matchNames에 나열 + Service에 공통 label(monitoring: "true")
HTTPS/인증scheme: https + tlsConfig + basicAuth(Secret 참조)

Relabeling — Label 가공 & 메트릭 필터

1
2
3
4
5
6
7
8
9
10
11
12
endpoints:
- port: metrics
  relabelings:                    # 스크래핑 전 Label 가공
  - sourceLabels: [__meta_kubernetes_pod_label_environment]
    regex: production
    action: keep                  # production만 수집
  metricRelabelings:              # 수집 후 처리
  - sourceLabels: [__name__]
    regex: "(http_requests_total|http_request_duration_seconds.*)"
    action: keep                  # 특정 메트릭만 유지
  - regex: "pod_template_hash"
    action: labeldrop             # 불필요 Label 제거

💡 relabelings(수집 전) vs metricRelabelings(수집 후) — 전자는 어떤 타겟을 스크래핑할지·어떤 Label을 붙일지 결정하고, 후자는 이미 가져온 메트릭 중 무엇을 저장할지 거른다. metricRelabelings로 불필요한 메트릭을 버리면 스토리지가 크게 절약된다.

Spring Boot Actuator 연동

1
2
3
4
5
# ServiceMonitor
endpoints:
- port: actuator
  interval: 15s
  path: /actuator/prometheus      # Actuator 경로
1
2
3
4
5
6
7
8
# application.yml
management:
  endpoints:
    web:
      exposure:
        include: prometheus,health,info
  server:
    port: 8081                     # Actuator 전용 포트

4. 트러블슈팅 — 흔한 실수

⚠️ 7대 실수 — ① ServiceMonitor selector ↔ Service label 불일치(가장 흔함), ② 포트 이름 불일치, ③ Prometheus의 serviceMonitorSelector가 이 ServiceMonitor를 선택 안 함, ④ 다른 NS 접근 RBAC 권한 없음, ⑤ 메트릭 경로 오류(/metrics vs /actuator/prometheus), ⑥ interval 너무 짧음(과부하), ⑦ Operator 로그 미확인.

1
2
3
4
5
6
7
# 진단 순서
kubectl get svc -n <ns> --show-labels                     # ① label 확인
kubectl get servicemonitor <name> -o yaml | grep -A5 selector  # ② selector 확인
kubectl get endpoints <svc> -n <ns>                       # ③ Endpoint 생성?
kubectl exec -it <pod> -- curl localhost:8080/metrics     # ④ 메트릭 경로 확인
kubectl logs -n monitoring prometheus-operator-<pod> | grep -i error  # ⑤ Operator 에러
# Prometheus UI: http://<url>/targets 에서 up{job="<svc>"} 확인

💡 타겟이 안 보이면 Label 매칭부터 의심하자. selector: app=my-app인데 Service가 application=my-app이면 Prometheus는 영영 발견하지 못한다. --show-labels로 실제 값을 눈으로 대조하는 것이 가장 빠르다.


5. 운영 참고

Grafana 연동 흐름: ServiceMonitor → Prometheus(저장) → Grafana(Data Source) → PromQL 대시보드.

항목권장
interval중요도에 따라 15s~60s
메트릭 필터metricRelabelings로 불필요 제거
보안(금융권)민감정보 노출 금지·내부망만 접근·불필요 Label 제거
API 버전monitoring.coreos.com/v1

📝 정리

1
2
3
4
5
6
ServiceMonitor
├─ 개념   Prometheus 타겟 자동 발견 CRD(Hot Reload)
├─ 연결   selector↔label, port명 일치 필수
├─ 가공   relabelings(수집전)·metricRelabelings(수집후)
├─ 연동   Spring Actuator(/actuator/prometheus)
└─ 함정   Label/포트 불일치 → 타겟 안 보임
개념한 줄 정의
ServiceMonitor선언적 모니터링 타겟
Label 매칭selector ↔ Service label
RelabelingLabel·메트릭 가공/필터

ServiceMonitor의 핵심은 YAML 선언만으로 Prometheus 타겟을 자동 관리하는 것이다. 대부분의 문제는 Label·포트 이름 불일치에서 오므로, 타겟이 안 보이면 이 매칭부터 확인하는 것이 정석이다.


🔗 참고

This post is licensed under CC BY 4.0 by the author.

Comments powered by Disqus.