Prometheus + Grafana로 서버 모니터링 구축하기
Prometheus와 Grafana는 이 과정을 구현하는 대표 조합입니다. 다만 도구를 띄우는 것과 관측 가능성을 설계하는 것은 다릅니다. 메트릭 이름, 라벨, 수집 주기, 쿼리, 알림 기준이 잘못되면 데이터는 많아도 운영에는 별 도움이 안 될 수 있습니다.
먼저 정리해야 할 것: 무엇을 관측할 것인가
모니터링은 무작정 메트릭을 많이 쌓는다고 좋아지지 않습니다. 보통 아래 층위로 생각하면 정리가 쉽습니다.
- 인프라: CPU, 메모리, 디스크, 네트워크
- 애플리케이션: 요청 수, 에러율, 지연 시간, 큐 적체
- 런타임: JVM heap, GC, thread pool, DB pool
- 비즈니스: 주문 수, 결제 성공률, 가입 전환율
즉, 좋은 모니터링은 시스템이 살아 있는지뿐 아니라 서비스가 제대로 가치 전달을 하고 있는지까지 볼 수 있어야 합니다.
가장 작은 시작점
services:
prometheus:
image: prom/prometheus:latest
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
grafana:
image: grafana/grafana:latest
ports:
- "3000:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin
volumes:
- grafana_data:/var/lib/grafana
depends_on: [prometheus]
volumes:
grafana_data:
이 구성은 시작점으로 충분합니다. 하지만 실무에서는 설치보다 더 중요한 질문이 이어집니다.
- 어떤 타깃을 얼마 주기로 수집할 것인가
- 라벨 카디널리티를 어떻게 제어할 것인가
- 알림 기준은 무엇인가
- 대시보드는 누가 어떤 용도로 볼 것인가
scrape 설정은 비용과 해상도의 균형이다
global:
scrape_interval: 15s
scrape_configs:
- job_name: 'spring-app'
static_configs:
- targets: ['host.docker.internal:8080']
metrics_path: '/actuator/prometheus'
수집 주기는 짧을수록 자세하지만 저장 비용이 커지고, 길수록 비용은 줄지만 스파이크를 놓칠 수 있습니다. 즉, scrape interval은 기술 설정이 아니라 운영 비용과 관측 해상도의 균형점입니다.
Spring Boot Actuator는 좋은 시작점이지만 충분하지 않을 수 있다
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
management:
endpoints:
web:
exposure:
include: health,info,prometheus,metrics
metrics:
tags:
application: ${spring.application.name}
Micrometer + Actuator만 붙여도 꽤 많은 기본 메트릭이 나옵니다. 하지만 운영에 정말 중요한 메트릭은 대개 애플리케이션 고유의 흐름에서 나옵니다.
- 주문 생성 수
- 결제 실패 이유별 카운트
- Kafka lag
- 외부 API fallback 횟수
- 배치 처리 건수와 실패율
즉, 기본 메트릭은 기반이고, 실제 운영 품질은 도메인 메트릭을 얼마나 잘 정의했는가에서 차이가 납니다.
커스텀 메트릭은 이름보다 의미가 중요하다
@Component
@RequiredArgsConstructor
public class OrderMetrics {
private final MeterRegistry registry;
public void recordOrder(String status) {
registry.counter("orders.created", "status", status).increment();
}
}
커스텀 메트릭을 만들 때는 아래를 먼저 생각하는 편이 좋습니다.
- 이 숫자가 운영 의사결정에 실제로 쓰일까
- 라벨 값이 폭증하지 않을까
- 누적 카운터가 맞을까, 게이지가 맞을까, 히스토그램이 맞을까
특히 라벨에 사용자 ID, 주문 ID 같은 고카디널리티 값을 넣는 실수는 매우 위험합니다. Prometheus는 이런 라벨 폭증에 취약할 수 있습니다.
PromQL은 숫자 조회가 아니라 질문을 만드는 도구다
rate(http_server_requests_seconds_count[1m])
rate(http_server_requests_seconds_sum[5m])
/
rate(http_server_requests_seconds_count[5m])
jvm_memory_used_bytes{area="heap"}
/
jvm_memory_max_bytes{area="heap"}
PromQL의 핵심은 쿼리를 외우는 데 있지 않습니다. 더 중요한 건 운영 질문을 메트릭으로 번역하는 능력입니다.
- 최근 5분 동안 요청률이 얼마나 늘었는가
- 평균보다 tail latency가 나빠지고 있는가
- 특정 상태코드가 평소보다 급증했는가
- JVM heap pressure가 GC와 함께 악화되고 있는가
즉, 모니터링은 그래프 보는 기술이 아니라 좋은 질문을 시스템 데이터로 바꾸는 기술입니다.
대시보드는 사람마다 목적이 다르다
Grafana 대시보드를 하나만 만들고 모두가 그것만 보게 하면 금방 복잡해집니다. 보통은 층위를 나누는 편이 좋습니다.
- 경영/서비스 상태 대시보드: 핵심 KPI, 가용성, 에러율
- 운영 대시보드: 요청률, 지연, 인프라 상태
- 서비스별 대시보드: DB pool, JVM, 큐, 외부 API
- 장애 분석 대시보드: 상세 라벨, pod별 비교, 최근 배포 영향
즉, 좋은 대시보드는 모든 걸 다 보여주는 화면이 아니라, 특정 역할의 사람이 빨리 판단하게 해주는 화면입니다.
알림은 민감도보다 신뢰도가 중요하다
많은 팀이 초기에 알림을 너무 많이 켭니다. 그러면 곧 알림 피로도가 생기고 아무도 믿지 않게 됩니다.
좋은 알림 기준은 대체로 아래와 같습니다.
- 실제 행동이 필요한 상황만 울린다
- 일시적인 스파이크보다 지속 패턴을 본다
- 단일 지표보다 여러 지표 조합을 고려한다
- 서비스 영향과 연결된다
예를 들어 CPU 90% 단일 기준보다, p95 latency 증가 + 에러율 상승 + HPA 포화 조합이 훨씬 운영 가치가 높을 수 있습니다.
흔한 안티패턴
- 메트릭은 많지만 서비스 KPI가 없다
- 라벨 카디널리티가 너무 높다
- 대시보드는 화려하지만 알림 기준이 모호하다
- 평균 응답시간만 보고 tail latency를 놓친다
- 대시보드를 임포트만 하고 팀 상황에 맞게 커스터마이즈하지 않는다
특히 Grafana dashboard ID를 가져다 쓰는 것만으로는 충분하지 않습니다. 팀 서비스 구조에 맞게 질문을 다시 설계해야 합니다.
Prometheus + Grafana가 특히 잘 맞는 경우
- 시계열 메트릭 기반 운영 모니터링
- Kubernetes/VM 환경 혼합 모니터링
- 애플리케이션과 인프라 메트릭을 함께 보고 싶을 때
- 팀별/서비스별 대시보드와 알림 체계를 만들고 싶을 때
반대로 로그 검색, 트레이싱, 이벤트 분석까지 모두 Prometheus만으로 해결하려 하면 한계가 있습니다. 메트릭은 observability의 한 축일 뿐입니다.
마무리
Prometheus와 Grafana의 가치는 도구 자체보다, 어떤 상태를 관측하고 어떤 질문에 답하려 하는지 체계적으로 설계할 수 있게 해준다는 점에 있습니다.
좋은 모니터링은 그래프를 많이 띄우는 것이 아니라, 장애를 더 빨리 감지하고 원인을 더 빨리 좁히고 서비스 상태를 더 명확히 이해하게 만드는 것입니다. 결국 핵심은 설치보다도, 메트릭과 대시보드를 운영 언어로 바꾸는 데 있습니다.
운영 환경에서 어려워지는 지점
- Prometheus와 Grafana는 메트릭 설계가 대시보드 장식이 아니라 서비스 건강 질문에 연결될 때 효과적이다.
- cardinality 증가, scrape 비용, 알림 소음이 반복되는 운영 함정이다.
- 핵심은 모든 것을 수집하는 것이 아니라 맞는 것을 경제적으로 수집하는 것이다.
중요한 아키텍처 결정
- 메트릭은 사용자 영향, 포화도, 오류, 처리량 기준으로 설계한다.
- label은 비용과 질의 사용성을 위해 제한되고 의미 있게 유지한다.
- 대시보드는 시각적 밀도가 아니라 진단 경로를 지원해야 한다.
실무 예시
탄탄한 서비스 메트릭 셋은 보통 작은 핵심 패턴을 따른다.
http_requests_total
http_request_duration_seconds
background_jobs_inflight
queue_lag_seconds
피해야 할 안티패턴
- user ID, raw path, request ID로 고카디널리티 label을 만드는 것.
- 대응 흐름 없는 수십 개 차트 대시보드를 만드는 것.
- 알림 임계값을 영구 고정값처럼 다루는 것.
운영 체크리스트
- cardinality hotspot과 질의 성능을 검토한다.
- 사고 근거로 알림 임계값을 조정한다.
- 대시보드 변경과 소유권을 버전 관리한다.
- scrape 실패와 모니터링 blind spot 시나리오를 테스트한다.
최종 판단
Prometheus와 Grafana는 빠른 운영 추론을 지원할 때 강하다. 메트릭 매립지가 되면 도구는 화려하지만 시스템은 여전히 운영하기 어렵다.
Continue Reading
다음으로 읽기 좋은 글
Kubernetes 심화 — HPA, Resource 관리, Pod Scheduling
Kubernetes 운영을 설정 모음이 아니라 자원 배치와 장애 복원력의 관점에서 정리합니다. requests/limits, HPA, affinity, taint, PDB, probe를 언제 어떻게 써야 하는지 실무적으로 설명합니다.
🚀 DevOpsKubernetes 클러스터 유형 완전 가이드
단일 노드부터 고가용성, 관리형, 멀티 클러스터까지 Kubernetes 클러스터 유형별 구조, 선택 기준, 구성 방법, 운영 트레이드오프를 실무 관점으로 정리합니다.
📚 IT 이야기컨테이너와 쿠버네티스는 어떻게 배포의 감각을 바꿨나
한때 배포는 늘 불안한 행사처럼 느껴졌지만, 컨테이너와 쿠버네티스는 그것을 더 반복 가능하고 더 자동화된 일상으로 바꾸려 했습니다.
🔧 ToolsDocker Desktop 실전 가이드: 개발 환경 운영 기준
Docker Desktop을 단순 실행 도구가 아니라 개발 환경 표준화 수단으로 쓰기 위해 Compose 설계, 볼륨 전략, 리소스 튜닝, Dev Container 활용 기준을 정리합니다.
다음 탐색