2. Prometheus 아키텍처: Pull vs Push, 데이터 모델, PromQL 기초

프로메테우스는 클라우드 네이티브 환경의 모니터링을 위해 태어난 오픈소스 프로젝트입니다. 이제는 사실상 업계 표준으로 자리 잡았죠. 프로메테우스를 제대로 이해하려면 그 아키텍처와 핵심적인 데이터 수집 방식인 'Pull' 모델을 알아야 합니다.

프로메테우스 아키텍처 한눈에 보기

프로메테우스는 단일 프로그램이 아니라, 여러 컴포넌트가 유기적으로 동작하는 하나의 생태계입니다.

Prometheus Ecosystem

Prometheus Server
Scraper
TSDB
HTTP API
Grafana
Alertmanager
Targets
Exporter
Instrumented App
Pushgateway

핵심 메커니즘: Pull vs. Push

프로메테우스의 가장 큰 특징 중 하나는 Pull(풀) 기반의 데이터 수집 방식입니다. 이는 프로메테우스 서버가 주기적으로 각 타겟의 HTTP 엔드포인트(보통 /metrics)를 '당겨와서(scrape)' 메트릭을 수집하는 것을 의미합니다.

비유: 건강검진 vs. 자가진단 보고

Pull 방식 (프로메테우스): 의사(프로메테우스)가 정기적으로 환자들(타겟)에게 직접 찾아가 혈압, 체온 등 건강 상태(메트릭)를 측정하고 기록하는 '정기 건강검진'과 같습니다. 의사가 주도권을 가지며, 환자가 연락이 안 되면(다운) 바로 알 수 있습니다.

Push 방식 (전통적인 방식): 환자들(타겟)이 스스로 건강 상태를 측정하여 주기적으로 의사(모니터링 서버)에게 '보고'하는 방식입니다. 환자가 보고를 잊거나 못하게 되면(장애), 의사는 환자의 상태를 알 수 없습니다.

항목 Pull 방식 (기본) Push 방식 (Pushgateway 사용)
주도권 프로메테우스 서버 모니터링 대상 (클라이언트)
장점 - 중앙에서 수집 대상 및 주기 관리 용이
- 타겟의 장애를 즉시 감지 가능 (Scrape 실패)
- 개발/테스트 환경에서 타겟을 직접 호출해 디버깅 용이
- 방화벽 내부나 NAT 뒤에 있는 타겟 모니터링 가능
- 수명이 매우 짧은 배치 잡(Job) 모니터링 가능
단점 - 방화벽 설정이 복잡해질 수 있음
- 수명이 매우 짧은 타겟은 수집 전에 사라질 수 있음
- Pushgateway가 SPOF(단일 장애점) 및 병목 지점이 됨
- 타겟의 장애를 직접 감지하기 어려움
- 타겟이 종료되어도 오래된(stale) 메트릭이 남을 수 있음

결론: 언제 Pushgateway를 사용해야 할까?

프로메테우스 공식 문서에서도 Pushgateway는 매우 제한적인 경우에만 사용하도록 권고합니다. 바로 수명이 매우 짧아서 프로메테우스가 Pull 하러 오기 전에 사라지는 서비스, 예를 들어 Cron으로 실행되는 배치 잡의 결과를 모니터링할 때입니다. 그 외의 일반적인 애플리케이션이나 서버 모니터링에는 반드시 Pull 방식을 사용해야 합니다.

프로메테우스 데이터 모델과 4가지 메트릭 타입

프로메테우스는 수집한 모든 데이터를 시계열(Time-series) 데이터로 저장합니다. 시계열 데이터는 메트릭 이름레이블(Label)의 조합, 그리고 시간과 값으로 구성됩니다.

# 문법: metric_name{label1="value1", label2="value2"} value

# 실제 예시
http_requests_total{method="POST", handler="/api/v1/users"} 26

이러한 유연한 레이블 구조 덕분에, 우리는 다차원적인 데이터 분석을 할 수 있습니다. 예를 들어, 위 메트릭을 이용해 "POST 요청 전체 수", "`/api/v1/users` 핸들러로 들어온 요청 수" 등을 자유롭게 집계할 수 있습니다.

프로메테우스는 목적에 따라 4가지 메트릭 타입을 제공합니다.

타입 설명 사용 예시
Counter 오직 증가만 하는 누적 값. (e.g., 요청 수, 에러 수) 초기화는 서버가 재시작될 때만 가능합니다. http_requests_total, user_logins_total
Gauge 증가하거나 감소할 수 있는 현재 상태 값. (e.g., 온도, 메모리 사용량) memory_usage_bytes, cpu_temperature, queue_length
Histogram 관측 값을 사전에 정의된 버킷(bucket)에 누적하여 분포를 기록. (e.g., 요청 지연 시간, 응답 크기) 백분위수(Percentile) 계산이 가능합니다. http_request_duration_seconds, rpc_durations_seconds
Summary (Histogram과 유사) 관측 값의 분포를 기록하지만, 서버가 아닌 클라이언트에서 직접 백분위수를 계산하여 수집합니다. (특별한 경우 외에는 Histogram 사용이 권장됨)

PromQL (Prometheus Query Language) 기초

PromQL은 프로메테우스에 저장된 시계열 데이터를 조회하고 분석하기 위한 강력한 함수형 쿼리 언어입니다. Grafana에서 차트를 그릴 때 사용하는 것이 바로 이 PromQL입니다.

# 1. 특정 메트릭의 모든 시계열 데이터 조회
http_requests_total

# 2. 특정 레이블을 가진 시계열 데이터 필터링
http_requests_total{job="api-server", method="POST"}

# 3. 5분 동안의 http_requests_total의 초당 평균 증가율 계산
rate(http_requests_total{job="api-server"}[5m])

# 4. 핸들러별 초당 평균 요청 수 합계
sum by (handler) (rate(http_requests_total[5m]))

처음에는 복잡해 보일 수 있지만, 몇 가지 핵심 함수(rate, increase, sum, avg)와 개념(범위 벡터 [5m])만 익히면 강력한 분석이 가능해집니다. 이는 다음 장에서 더 자세히 다루겠습니다.

면접관의 시선 💡

Q: "Prometheus의 Pull 방식과 Push 방식의 장단점을 설명해주세요. 그리고 어떤 경우에 Push 방식을 사용해야 할까요?"

A: "프로메테우스의 기본 방식인 Pull은 프로메테우스 서버가 주기적으로 타겟의 메트릭 엔드포인트를 호출하여 데이터를 가져오는 방식입니다. 중앙에서 수집 대상을 관리하기 쉽고, 타겟의 장애를 즉시 감지할 수 있는 장점이 있습니다. 반면 Push 방식은 타겟이 Pushgateway라는 중간 지점에 메트릭을 보내고, 프로메테우스는 이 Pushgateway를 Pull 하는 방식입니다. 이는 방화벽 뒤에 있거나 수명이 매우 짧은 타겟을 모니터링할 때 유용합니다. 하지만 Pushgateway는 단일 장애점이 될 수 있고, 타겟이 종료되어도 오래된 메트릭이 남는 문제가 있습니다. 따라서 Push 방식은 Cron으로 실행되는 배치 잡처럼 수명이 매우 짧아 Pull이 불가능한 예외적인 경우에만 제한적으로 사용해야 합니다."


Q: "Prometheus의 4가지 메트릭 타입(Counter, Gauge, Histogram, Summary)에 대해 설명하고, 각각 어떤 경우에 사용해야 하는지 예를 들어주세요."

A: "네, 4가지 타입이 있습니다. 첫째, Counter는 '총 요청 수'나 '총 에러 수'처럼 오직 증가만 하는 누적 값을 기록할 때 사용합니다. 둘째, Gauge는 '현재 메모리 사용량'이나 '큐에 쌓인 메시지 수'처럼 값이 오르내릴 수 있는 현재 상태를 나타낼 때 사용합니다. 셋째, Histogram은 'API 응답 시간'처럼 값의 분포를 알고 싶을 때 사용합니다. 사전에 정의된 버킷에 관측 값을 누적하여, 나중에 p99, p95 같은 백분위수를 계산할 수 있습니다. 마지막으로 Summary도 분포를 기록하지만, 클라이언트에서 직접 백분위수를 계산한다는 차이가 있습니다. 일반적으로는 서버에서 유연하게 집계할 수 있는 Histogram 사용이 권장됩니다."


Q: "PromQL에서 `rate(http_requests_total[5m])`는 무엇을 의미하나요?"

A: "`rate()` 함수는 Counter 타입의 메트릭이 시간 경과에 따라 얼마나 빠르게 증가했는지, 즉 '초당 평균 증가율'을 계산하는 함수입니다. `http_requests_total`은 누적 요청 수를 나타내는 Counter이므로, `rate(http_requests_total[5m])`는 쿼리가 실행되는 시점을 기준으로 지난 5분 동안의 `http_requests_total` 데이터를 보고, 이를 기반으로 초당 평균 요청 수(RPS)가 얼마인지를 계산한 결과를 의미합니다. 시스템의 처리량을 파악하는 데 매우 중요한 쿼리입니다."