Prometheus는 서버와 애플리케이션의 상태를 수치 데이터로 수집하고 저장하는 모니터링 시스템이다. CPU 사용률, 메모리 사용량, HTTP 요청 수, 응답 시간, 에러 발생 횟수 같은 데이터를 지속적으로 수집해서 현재 시스템이 어떤 상태인지 확인할 수 있게 해준다.
특히 Kubernetes 같은 분산 환경에서는 서비스가 많아지면서 로그만 보고 시스템 상태를 파악하기 어려워진다. 이때 Prometheus가 각 서버와 애플리케이션에서 메트릭을 수집하고, Grafana 같은 도구를 연결해 시각화하거나 Alertmanager를 통해 장애 알림을 보내는 형태로 많이 사용한다.
Prometheus를 이해할 때는 Metric -> Exporter -> Scrape -> TSDB -> Query -> Alert 흐름을 잡는 게 편하다.
Metric
Prometheus가 다루는 기본 데이터는 Metric이다.
예를 들어 다음과 같은 값들이 있다.
http_requests_total
process_cpu_seconds_total
node_memory_MemAvailable_bytes
단순히 123이라는 숫자를 저장하는 것이 아니라, 해당 숫자가 무엇을 의미하는지 식별할 수 있는 이름과 label을 함께 사용한다.
예를 들어 HTTP 요청 수를 다음처럼 표현할 수 있다.
http_requests_total{method="GET", endpoint="/users", status="200"} 15231
여기서 http_requests_total이 Metric 이름이고 method, endpoint, status가 label이다.
같은 Metric이라도 label 값에 따라 서로 다른 시계열(Time Series)이 만들어진다.
http_requests_total{status="200"} 15231
http_requests_total{status="404"} 231
http_requests_total{status="500"} 12
이 구조 덕분에 특정 조건의 데이터만 조회할 수 있다.
다만 label을 무작정 많이 붙이면 문제가 생긴다. label 조합이 많아질수록 시계열 개수가 급격하게 증가하기 때문이다. 특히 사용자 ID, 요청 ID처럼 값의 종류가 계속 늘어나는 데이터를 label로 사용하는 것은 일반적으로 피해야 한다.
Prometheus의 데이터 모델
Prometheus는 기본적으로 시계열 데이터베이스(Time Series Database)다.
각 시계열은 Metric 이름과 label 집합으로 식별되고 시간에 따라 값이 기록된다.
개념적으로 보면 다음과 같다.
Metric + Labels -> Time Series -> (timestamp, value) -> (timestamp, value) -> (timestamp, value) -> ...
예를 들어 CPU 사용률을 수집한다면 시간이 지나면서 다음과 같은 데이터가 쌓인다.
timestamp value
10:00:00 31
10:00:15 34
10:00:30 42
10:00:45 39
이 데이터를 기반으로 현재 상태뿐 아니라 시간에 따른 변화도 분석할 수 있다.
Pull 방식의 메트릭 수집
Prometheus에서 가장 특징적인 부분 중 하나가 Pull 방식의 메트릭 수집이다.
일반적인 애플리케이션이 데이터를 Prometheus로 보내는 것이 아니라 Prometheus가 주기적으로 대상 서버에 접근해서 메트릭을 가져온다.
Application -> /metrics -> Prometheus -> TSDB
예를 들어 애플리케이션이 다음과 같은 endpoint를 제공한다고 하자.
GET /metrics
응답은 대략 다음과 같은 형태다.
http_requests_total{method="GET",status="200"} 15231
http_requests_total{method="GET",status="500"} 12
process_resident_memory_bytes 52428800
Prometheus는 일정한 주기로 이 endpoint를 호출해서 데이터를 가져온다.
이 과정을 Scrape라고 한다.
Prometheus 설정에서는 어떤 대상을 수집할지 지정한다.
scrape_configs:
- job_name: "game-server"
static_configs:
- targets:
- "localhost:8080"
이렇게 설정하면 Prometheus가 해당 대상의 메트릭 endpoint를 주기적으로 조회한다.
Exporter
모든 시스템이 처음부터 Prometheus 형식의 Metric을 제공하는 것은 아니다.
이때 사용하는 것이 Exporter다.
Exporter는 특정 시스템의 상태를 Prometheus가 읽을 수 있는 Metric 형태로 변환해서 제공하는 역할을 한다.
대표적인 것이 node_exporter다.
Linux Server -> node_exporter -> /metrics -> Prometheus
Linux의 CPU, 메모리, 디스크, 네트워크 등의 정보를 node_exporter가 수집하고 Prometheus 형식으로 노출한다.
데이터베이스나 기타 인프라에서도 각각의 Exporter를 사용할 수 있다.
애플리케이션 자체에서 Metric을 직접 생성할 수도 있다.
Application -> Application Metrics / Exporter -> Prometheus
그래서 Exporter는 Prometheus 자체가 데이터를 수집하는 모듈이라기보다는, Prometheus가 읽을 수 있는 Metric endpoint를 제공하는 어댑터에 가깝다고 이해하면 된다.
Instrumentation
애플리케이션에서 직접 Metric을 기록하는 방식도 있다.
예를 들어 HTTP 서버라면 다음과 같은 Metric을 만들 수 있다.
http_requests_total
http_request_duration_seconds
active_connections
게임 서버라면 조금 다른 Metric이 필요할 수 있다.
connected_players
matchmaking_queue_size
game_tick_duration_seconds
packet_loss_total
이런 식으로 애플리케이션 내부의 상태를 Metric으로 노출하면 인프라 상태뿐 아니라 실제 서비스의 상태도 관찰할 수 있다.
Prometheus는 결국 서버의 CPU만 보는 시스템이 아니다.
개발자가 서비스에 어떤 Metric을 정의하느냐에 따라 모니터링할 수 있는 대상이 달라진다.
Metric의 종류
Prometheus에서는 대표적으로 Counter, Gauge, Histogram, Summary를 사용한다.
Counter
계속 증가하는 값을 기록한다.
http_requests_total
errors_total
packets_sent_total
일반적으로 요청 횟수나 에러 횟수처럼 누적되는 데이터를 표현한다.
프로세스가 재시작되면 Counter 값이 다시 올라갈 수 있지만, Prometheus에서는 시간에 따른 증가량을 계산해서 의미 있는 값을 얻을 수 있다.
예를 들어 초당 요청 수를 계산할 때 rate()를 사용할 수 있다.
rate(http_requests_total[5m])
최근 5분 동안의 증가 추세를 이용해서 초당 요청률을 계산한다.
Gauge
현재 값을 나타낸다.
active_connections
memory_usage
queue_size
temperature
증가하거나 감소할 수 있다.
active_connections = 153
현재 연결된 클라이언트가 153개라는 의미다.
Histogram
값의 분포를 측정할 때 사용한다.
대표적으로 HTTP 응답 시간을 측정할 수 있다.
http_request_duration_seconds
단순히 평균 응답 시간이 얼마인지 보는 것보다,
50% 요청이 몇 ms 이하인가
95% 요청이 몇 ms 이하인가
99% 요청이 몇 ms 이하인가
같은 정보를 확인할 때 유용하다.
특히 실제 서비스에서 응답 시간이나 처리 시간의 Tail Latency를 확인할 때 중요하다.
Summary
Summary 역시 관측값의 분포나 분위수를 다루기 위한 Metric 타입이다.
다만 분산 환경에서 서버별 데이터를 합쳐 분석하는 방식에는 Histogram이 더 적합한 경우가 많기 때문에 실무에서는 Histogram을 자주 사용한다.
PromQL
Prometheus에서 데이터를 조회할 때 사용하는 언어가 PromQL(Prometheus Query Language)이다.
예를 들어 특정 Metric을 조회할 수 있다.
http_requests_total
label 조건을 걸 수도 있다.
http_requests_total{status="500"}
특정 시간 범위의 요청 증가율을 보고 싶다면 다음처럼 작성한다.
rate(http_requests_total[5m])
CPU 사용률 같은 데이터도 계산해서 사용할 수 있다.
PromQL의 중요한 부분은 단순히 데이터를 검색하는 것보다 수집한 Metric을 조합하고 계산해서 운영에 필요한 정보를 만드는 것이다.
예를 들어 서버가 100대라면 각각의 CPU 사용률을 보는 것보다 전체 서버의 평균이나 특정 조건을 만족하는 서버를 찾는 것이 더 유용하다.
Alerting
Prometheus는 Metric을 수집하는 것에서 끝나지 않는다.
특정 조건이 일정 시간 동안 유지되면 Alert를 발생시킬 수 있다.
예를 들어 CPU 사용률이 80% 이상인 상태가 5분 이상 지속되는 경우를 생각할 수 있다.
groups:
- name: server
rules:
- alert: HighCPUUsage
expr: cpu_usage > 80
for: 5m
이런 Rule을 기반으로 Prometheus가 알림 조건을 평가한다.
다만 실제 알림 전달은 일반적으로 Alertmanager와 함께 구성한다.
Prometheus -> Alert -> Alertmanager -> Slack / Email / PagerDuty / 기타 알림 시스템
Alertmanager는 여러 Alert를 그룹화하거나 중복 알림을 억제하고, 특정 조건에 따라 알림을 라우팅하는 역할을 한다.
따라서 Prometheus와 Alertmanager는 역할이 다르다.
Prometheus가 Metric 수집과 Alert Rule 평가를 담당한다면 Alertmanager는 Alert의 전달과 관리를 담당한다.
Grafana와의 관계
Prometheus 자체에도 PromQL을 실행하고 데이터를 확인할 수 있는 기능은 있다.
하지만 실제 운영 환경에서는 Grafana와 같이 사용하는 경우가 많다.
Server / Application -> Prometheus -> Grafana
Grafana가 Prometheus를 데이터 소스로 사용하면 CPU, 메모리, 요청량, 에러율, 응답 시간 등을 Dashboard로 구성할 수 있다.
예를 들어 하나의 서버를 다음과 같이 볼 수 있다.
CPU Usage 72%
Memory Usage 81%
HTTP RPS 1,240
HTTP 5xx 3
P99 Latency 420ms
여기서 Grafana는 데이터를 저장하는 시스템이 아니다.
Prometheus가 데이터를 저장하고 Grafana가 그것을 조회해서 시각화하는 구조다.
Kubernetes에서의 Prometheus
Prometheus가 많이 사용되는 환경 중 하나가 Kubernetes다.
Kubernetes에서는 서버와 Pod가 동적으로 생성되고 사라질 수 있다.
Pod A / Pod B / Pod C / Pod D / ...
고정된 서버 목록만 관리하는 방식으로는 이런 환경을 효율적으로 모니터링하기 어렵다.
Kubernetes의 Service Discovery 기능과 Prometheus를 연동하면 현재 존재하는 대상들을 발견하고 Metric을 수집할 수 있다.
Kubernetes -> Service Discovery -> Prometheus -> Pod Metrics / Node Metrics / Application Metrics
실제 Kubernetes 환경에서는 Prometheus Operator나 kube-prometheus-stack 같은 구성도 많이 사용한다.
이런 도구들을 사용하면 Prometheus 자체뿐 아니라 Alertmanager, Grafana, 여러 기본 모니터링 Rule 등을 함께 구성할 수 있다.
Prometheus의 전체 구조
전체적인 관계를 한 번 묶어보면 다음과 같다.
Application / Exporter -> /metrics -> Prometheus -> TSDB / PromQL -> Grafana / Alert Rule -> Alertmanager -> Slack / Email 등
각 구성요소의 역할을 분리해서 이해하면 어렵지 않다.
Exporter / Application
Metric을 제공한다.
Prometheus
Metric을 주기적으로 수집하고 저장한다.
PromQL
저장된 Metric을 조회하고 계산한다.
Grafana
Metric을 Dashboard로 시각화한다.
Alertmanager
Prometheus에서 발생한 Alert를 실제 알림 시스템으로 전달하고 관리한다.
실무에서 어떤 Metric을 수집해야 하는가
Prometheus를 처음 도입하면 Metric을 많이 수집하고 싶어진다.
하지만 Metric이 많다고 모니터링이 잘 되는 것은 아니다.
보통 서버와 서비스 상태를 판단하는 데 필요한 데이터를 먼저 잡는다.
서버
CPU / Memory / Disk / Network / Load / Filesystem
애플리케이션
Request Count / Request Rate / Error Rate / Response Time / Active Connections
게임 서버
Connected Players / Matchmaking Queue / Game Tick Time / Packet Rate / Packet Loss / Session Count
여기에 장애를 판단할 수 있는 Metric을 추가한다.
예를 들어 단순히 CPU 사용률을 보는 것보다,
CPU Usage / HTTP Error Rate / P99 Latency / Active Connections
를 함께 보는 것이 실제 서비스 상태를 판단하는 데 더 도움이 된다.
Metric을 설계할 때도 결국 운영자가 이 값을 보고 어떤 판단을 내릴 것인가를 기준으로 잡는 게 좋다.
Prometheus를 로그 시스템으로 생각하면 안 되는 이유
Prometheus는 Metric 시스템이고 로그 시스템이 아니다.
예를 들어 다음 데이터는 Metric으로 적합하다.
초당 요청 수 / 현재 접속자 수 / 초당 에러 수 / 평균 응답 시간 / P99 응답 시간 / CPU 사용률
반면 이런 데이터는 로그에 더 적합하다.
2026-08-26 01:30:12
User 1234 login failed
reason=invalid_password
로그에는 개별 이벤트의 상세 정보가 필요하다.
Metric에는 시스템 전체의 상태와 추세를 빠르게 파악할 수 있는 수치가 필요하다.
그래서 실제 시스템에서는 보통 역할을 나눈다.
Metrics -> Prometheus
Logs -> Loki / Elasticsearch 등
Traces -> Tempo / Jaeger 등
이런 세 가지 관측 데이터를 묶어서 보는 것을 Observability 관점에서 접근할 수 있다.
Prometheus를 이해하면서 정리한 핵심
Prometheus를 단순히 “모니터링 툴”이라고 외우면 구조가 잘 잡히지 않는다.
내가 이해한 기준으로 보면 Prometheus의 중심은 시계열 Metric을 수집하고 질의하는 시스템이다.
애플리케이션이나 Exporter가 Metric을 노출하고, Prometheus가 이를 Scrape해서 TSDB에 저장한다. 이후 PromQL로 데이터를 조회하거나 계산하고, Grafana에서 시각화한다. 장애 조건은 Alert Rule로 정의하고 실제 알림 전달과 관리는 Alertmanager가 담당한다.
전체 흐름은 이 정도로 잡아두면 된다.
Application / Exporter -> Metric -> Scrape -> Prometheus -> TSDB / PromQL -> Grafana / Alert Rule -> Alertmanager
결국 모니터링에서 중요한 것은 도구 자체보다 무엇을 측정할 것인가다.
Prometheus는 그 측정값을 시간에 따라 저장하고, 필요한 형태로 조회하고, 시스템 상태를 판단할 수 있도록 만들어주는 역할을 한다.