생산 환경에서 LLM 추론 모니터링(2026): vLLM, TGI, llama.cpp용 Prometheus 및 Grafana
프로메테우스와 그라파나를 사용하여 LLM 모니터링하기
LLM 추론은 “단순한 API처럼” 보일 수 있지만, 지연 시간이 급격히 증가하고 대기열이 다시 쌓이기 시작하며, GPU가 95% 메모리 사용률에 도달하면서도 명확한 설명이 없을 때 문제가 발생합니다.
단일 노드 설정을 벗어나거나 처리량 최적화를 시작하는 순간 모니터링은 미션 크리티컬이 됩니다. 그 시점에서 전통적인 API 메트릭만으로는 충분하지 않습니다. 토큰, 배치 행동, 대기 시간, KV 캐시 압력과 같은 현대 LLM 시스템의 실제 병목 현상에 대한 가시성이 필요합니다.
이 기사는 제가 작성한 **관측 가능성 및 모니터링 가이드**의 일부입니다. 여기서는 모니터링 대 관측 가능성의 기초, Prometheus 아키텍처, 그리고 생산성 최고 실천 방법을 다룹니다. 여기서는 특히 LLM 추론 작업량 모니터링에 초점을 맞춥니다.
(인프라 선택을 고려 중이라면, 제 2026년 LLM 호스팅 가이드를 참조하세요. 배치 메커니즘, VRAM 제한, 처리량 대 지연 시간의 트레이드오프에 대한 심층 분석이 필요하다면, LLM 성능 공학 가이드를 참조하세요.)
일반적인 REST 서비스와 달리 LLM 서빙은 토큰, 지속적인 배치, KV 캐시 활용, GPU/CPU 포화, 대기열 동역학에 의해 형성됩니다. 동일한 페이로드 크기의 두 요청은 max_new_tokens, 병렬 처리, 캐시 재사용에 따라 지연 시간이 크게 달라질 수 있습니다.
이 가이드는 Prometheus와 Grafana를 활용한 LLM 추론 모니터링을 위한 실용적이고 생산성 중심의 단계별 가이드입니다:
- 측정해야 할 항목 (p95/p99 지연 시간, 토큰/초, 대기 시간, 캐시 활용, 오류율)
- 일반적인 서버에서
/metrics를 스크래핑하는 방법 (vLLM, Hugging Face TGI, llama.cpp) - 백분위, 포화, 처리량에 대한 PromQL 예시
- Docker Compose 및 Kubernetes와 함께 사용되는 배포 패턴
- 실제 부하 하에서만 나타나는 문제를 해결하는 방법
예제는 제조사 중립적입니다. 나중에 OpenTelemetry 추적, 자동 확장, 서비스 메시지가 추가되더라도 동일한 메트릭 모델이 적용됩니다.

왜 LLM 추론을 다르게 모니터링해야 하는가
전통적인 API 모니터링(RPS, p95 지연 시간, 오류율)은 필수적이지만 충분하지 않습니다. LLM 서빙은 추가적인 축을 더합니다:
1) 지연 시간에는 두 가지 의미가 있습니다
- E2E 지연 시간: 요청이 수신된 시간부터 최종 토큰이 반환된 시간까지.
- 토큰 간 지연 시간: 디코딩 중 토큰당 시간 (스트리밍 UX에 중요).
일부 서버는 두 가지 모두를 노출합니다. 예를 들어, TGI는 요청 지속 시간과 토큰당 평균 시간을 히스토그램으로 노출합니다.
2) 처리량은 토큰 수, 요청 수가 아닙니다
5개의 토큰을 반환하는 “빠른” 서비스는 500개의 토큰을 반환하는 서비스와 비교할 수 없습니다. 대부분의 경우, “RPS"는 “토큰/초“가 되어야 합니다.
3) 대기열은 제품입니다
지속적인 배치를 실행할 경우, 대기열 깊이는 판매하는 것입니다. 대기열 지속 시간 및 대기열 크기를 감시하면 사용자 기대치를 충족하는지 알 수 있습니다.
4) 캐시 압력은 장애 사전 지표입니다
KV 캐시 고갈 (또는 분할)은 일반적으로 갑작스러운 지연 시간 증가 및 타임아웃으로 나타납니다. vLLM은 KV 캐시 사용량을 게이지로 노출합니다.
LLM 추론 모니터링을 위한 메트릭 체크리스트
이를 당신의 북마크로 사용하세요. 처음에는 모든 항목이 필요하지 않지만, 결국에는 대부분을 사용하게 될 것입니다.
골든 신호 (LLM 스타일)
- 트래픽: 요청/초, 토큰/초
- 오류: 오류율, 타임아웃, OOM, 429 (레이트 제한)
- 지연 시간: p50/p95/p99 요청 지속 시간; 사전 처리 vs 디코딩 지연 시간; 토큰 간 지연 시간
- 포화: GPU 사용률, 메모리 사용, KV 캐시 사용, 대기열 크기
Prometheus 외부에서 GPU 메모리 사용, 온도, 사용량에 대한 저수준 가시성이 필요하다면 (디버깅 또는 단일 노드 설정을 위해), 제 Linux / Ubuntu에서의 GPU 모니터링 애플리케이션 가이드를 참조하세요.
LLM 관측 가능성에 대한 보다 넓은 시야 - 추적, 구조화된 로그, 합성 테스트, GPU 프로파일링, SLO 설계를 포함하여 - 제 LLM 시스템을 위한 관측 가능성 가이드를 참조하세요.
유용한 차원 (레이블)
레이블 카디널리티를 낮추세요. 좋은 레이블:
모델,엔드포인트,메서드(사전 처리/디코딩),상태(성공/오류),인스턴스
피해야 할 레이블:
- 원시
프롬프트, 원시사용자 ID, 요청 ID - 이들은 시리즈 수를 폭증시킵니다.
메트릭 노출: 내장된 /metrics 엔드포인트 (vLLM, TGI, llama.cpp)
가장 쉬운 방법은: 서버가 이미 노출하는 메트릭을 사용하는 것입니다.
vLLM: Prometheus 호환 /metrics
vLLM은 Prometheus 호환 /metrics 엔드포인트를 노출하고 (Prometheus 메트릭 로거를 통해) vllm: 접두사로 서버/요청 메트릭을 출판합니다. 실행 중인 요청 및 KV 캐시 사용량과 같은 게이지도 포함됩니다.
보통 볼 수 있는 예시 메트릭:
vllm:num_requests_runningvllm:num_requests_waitingvllm:kv_cache_usage_perc
Hugging Face TGI: 대기열 + 요청 히스토그램을 포함한 /metrics
TGI는 /metrics에서 대기열 크기, 요청 지속 시간, 대기열 지속 시간, 토큰당 평균 시간을 포함한 많은 생산용 메트릭을 노출합니다.
주목할 만한 항목:
tgi_queue_size(게이지)tgi_request_duration(히스토그램, E2E 지연 시간)tgi_request_queue_duration(히스토그램)tgi_request_mean_time_per_token_duration(히스토그램)
llama.cpp 서버: 메트릭 엔드포인트 활성화
llama.cpp 서버는 Prometheus 호환 메트릭 엔드포인트를 지원하지만, 이는 플래그로 활성화되어야 합니다 (예: --metrics).
llama.cpp가 프록시 뒤에 실행 중이라면, 가능한 한 서버를 직접 스크래핑하세요 (프록시 수준의 지연 시간이 실제 추론 행동을 숨기는 것을 피하기 위해).
Prometheus 구성: 추론 서버 스크래핑
이 예제는 다음과 가정합니다:
- vLLM:
http://vllm:8000/metrics - TGI:
http://tgi:8080/metrics - llama.cpp:
http://llama:8080/metrics - 빠른 피드백을 위해 스크래핑 간격이 조정됨
prometheus.yml
global:
scrape_interval: 5s
evaluation_interval: 15s
scrape_configs:
- job_name: "vllm"
metrics_path: /metrics
static_configs:
- targets: ["vllm:8000"]
- job_name: "tgi"
metrics_path: /metrics
static_configs:
- targets: ["tgi:8080"]
- job_name: "llama_cpp"
metrics_path: /metrics
static_configs:
- targets: ["llama:8080"]
Prometheus가 새로운 사람이라면, 스크래핑 구성, 엑спор터, 레이블 재설정, 경고 규칙에 대한 보다 깊은 설명이 필요하다면, 제 Prometheus 모니터링 설정 가이드를 참조하세요.
프로 팁: “서비스 레이블” 추가
여러 모델/리플리카를 실행 중이라면, 대시보드에 안정적인 service 레이블을 추가하기 위해 레이블 재설정을 포함하세요.
relabel_configs:
- target_label: service
replacement: "llm-inference"
복사/붙여넣기 가능한 PromQL 예시
요청률 (RPS)
sum(rate(tgi_request_count[5m]))
vLLM의 경우, 요청 카운터를 사용하세요 (버전에 따라 이름이 다를 수 있음), 하지만 패턴은 동일합니다: sum(rate(<counter>[5m])).
오류율 (%)
*_success 카운터가 있다면, 실패 비율을 계산하세요:
1 - (
sum(rate(tgi_request_success[5m]))
/
sum(rate(tgi_request_count[5m]))
)
히스토그램 메트릭의 p95 지연 시간 (Prometheus)
Prometheus 히스토그램은 버킷 수를 기반으로 합니다. histogram_quantile()를 사용하여 rate()의 버킷에 대해 계산하세요. Prometheus는 이 모델과 히스토그램 대 요약의 차이점을 문서화합니다.
histogram_quantile(
0.95,
sum by (le) (rate(tgi_request_duration_bucket[5m]))
)
p99 대기 시간
histogram_quantile(
0.99,
sum by (le) (rate(tgi_request_queue_duration_bucket[5m]))
)
토큰당 평균 시간 (토큰 간 지연 시간)
histogram_quantile(
0.95,
sum by (le) (rate(tgi_request_mean_time_per_token_duration_bucket[5m]))
)
토큰 간 지연 시간은 종종 디코딩 병목 현상과 메모리 대역폭에 의해 제한됩니다. 이는 LLM 성능 최적화 가이드에서 상세히 다룹니다.
대기열 깊이 (즉시)
max(tgi_queue_size)
vLLM KV 캐시 사용률 (즉시)
max(vllm:kv_cache_usage_perc)
Grafana 대시보드: 실시간 알림에 도움이 되는 패널
Grafana는 히스토그램을 여러 가지 방식으로 시각화할 수 있습니다 (백분위, 히트맵, 버킷 분포). Grafana Labs는 Prometheus 히스토그램 시각화에 대한 상세한 가이드를 제공합니다.
최소한의, 고신호 대시보드 레이아웃:
행 1 — 사용자 경험
- p95 요청 지연 시간 (시간 시리즈)
- p95 토큰 간 지연 시간 (시간 시리즈)
- 오류율 (시간 시리즈 + 통계)
행 2 — 용량 및 포화
- 대기열 크기 (시간 시리즈)
- 실행 중 vs 대기 중 요청 (스택)
- KV 캐시 사용 % (게이지)
행 3 — 처리량
- 요청/초
- 생성된 토큰/요청 (p50/p95)
스트리밍이 있다면, “첫 번째 토큰 지연 시간” (TTFT) 패널을 추가하세요.
예시 Grafana 쿼리
- p95 지연 시간 패널: 위에서 언급한
histogram_quantile(0.95, …)쿼리 - 히트맵 패널: 버킷 레이트 (
*_bucket)를 히트맵으로 그래프 (Grafana는 이 접근법을 지원합니다)
배포 옵션 1: Docker Compose (빠른 로컬 + 단일 노드)
로컬, 자가 호스팅, 클라우드 기반 추론 아키텍처 사이의 선택을 고려 중이라면, 제 LLM 호스팅 비교 가이드에서 전체 분석을 참조하세요.
다음과 같은 폴더를 생성하세요:
monitoring/
docker-compose.yml
prometheus/
prometheus.yml
grafana/
provisioning/
datasources/datasource.yml
dashboards/dashboards.yml
dashboards/
llm-inference.json
docker-compose.yml
services:
prometheus:
image: prom/prometheus:latest
volumes:
- ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro
ports:
- "9090:9090"
grafana:
image: grafana/grafana:latest
environment:
- GF_SECURITY_ADMIN_USER=admin
- GF_SECURITY_ADMIN_PASSWORD=admin
volumes:
- ./grafana/provisioning:/etc/grafana/provisioning
- ./grafana/dashboards:/var/lib/grafana/dashboards
ports:
- "3000:3000"
depends_on:
- prometheus
Docker 대신 수동 Grafana 설치를 선호한다면, 제 Ubuntu에서 Grafana 설치 및 사용 가이드의 단계별 가이드를 참조하세요.
Grafana 데이터소스 제공 (grafana/provisioning/datasources/datasource.yml)
apiVersion: 1
datasources:
- name: Prometheus
type: prometheus
access: proxy
url: http://prometheus:9090
isDefault: true
대시보드 제공 (grafana/provisioning/dashboards/dashboards.yml)
apiVersion: 1
providers:
- name: "LLM"
folder: "LLM"
type: file
disableDeletion: true
options:
path: /var/lib/grafana/dashboards
배포 옵션 2: Kubernetes (Prometheus Operator + ServiceMonitor)
kube-prometheus-stack (Prometheus Operator)를 사용하는 경우, ServiceMonitor를 통해 스크래핑 대상으로 지정하세요.
Kubernetes, 단일 노드 Docker, 관리형 추론 제공업체 간의 인프라 트레이드오프에 대해, 제 2026년 LLM 호스팅 가이드를 참조하세요.
1) 인프라 배포를 Service로 노출
apiVersion: v1
kind: Service
metadata:
name: tgi
labels:
app: tgi
spec:
selector:
app: tgi
ports:
- name: http
port: 8080
targetPort: 8080
2) ServiceMonitor 생성
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: tgi
labels:
release: kube-prometheus-stack
spec:
selector:
matchLabels:
app: tgi
endpoints:
- port: http
path: /metrics
interval: 5s
vLLM 및 llama.cpp 서비스에 대해 반복하세요. 리플리카를 추가할 때 깔끔하게 확장됩니다.
3) 경고: SLO 스타일 규칙 (예시)
다음은 좋은 시작 경고입니다:
- 높은 p95 지연 시간 (연소율)
- 대기 시간 p99 너무 높음 (사용자가 대기 중)
- 오류율 > 1%
- KV 캐시 사용률 > 90% 지속 (용량 경계)
예시 규칙 (p95 요청 지속 시간):
- alert: LLMHighP95Latency
expr: histogram_quantile(0.95, sum by (le) (rate(tgi_request_duration_bucket[5m]))) > 3
for: 10m
labels:
severity: page
annotations:
summary: "TGI p95 latency > 3s (10m)"
디버깅: LLM 스택에서 일반적인 Prometheus + Grafana 실패 사례
1) Prometheus 대상이 “DOWN”
증상
- Prometheus UI → 대상이
DOWN표시 - “context deadline exceeded” 또는 연결 거부
체크리스트
- 서버가 실제로
/metrics를 노출하고 있습니까? - 잘못된 포트? 잘못된 스키마 (http 대 https)?
- Kubernetes: Service가 pod를 선택하고 있습니까? ServiceMonitor의
release라벨이 올바른가요?
빠른 테스트
curl -sS http://tgi:8080/metrics | head
2) 메트릭을 스크래핑할 수 있지만 패널이 비어 있음
가장 흔한 원인
- 잘못된 메트릭 이름 (서버 버전 변경)
- 대시보드가
_bucket을 기대하지만 게이지/카운터만 가지고 있음 - Prometheus 스크래핑 간격이 짧은 윈도우에 너무 길음 (예:
[1m]에 30초 스크래핑은 노이즈가 많음)
해결 방법
- Grafana Explore에서 메트릭 접두사를 검색하세요 (예:
tgi_/vllm:) - 범위 윈도우를
[1m]→[5m]으로 증가하세요
3) 히스토그램 백분위가 “평평"하거나 잘못됨
Prometheus 히스토그램은 올바른 집계가 필요합니다:
rate(metric_bucket[5m])사용sum by (le)(및 선택적으로 다른 안정적인 레이블)histogram_quantile()사용
Prometheus는 버킷 모델과 서버 측 백분위 계산을 문서화합니다.
Grafana의 히스토그램 시각화 가이드는 실용적인 패널 패턴을 포함합니다.
4) 카디널리티 폭증 (Prometheus 메모리 증가)
증상
- Prometheus RAM 사용량 증가
- “too many series” 오류
일반적인 근본 원인
- 사용자 정의 엑спор터에서
프롬프트,사용자 ID, 요청 ID를 레이블로 추가했습니다.
해결 방법
- 고카디널리티 레이블 제거
- 낮은 카디널리티 레이블로 사전 집계 (모델, 엔드포인트, 상태)
- 요청별 디버깅을 위해 레이블 대신 로그/트레이스 사용 고려
5) “메트릭은 있으나 왜 느린지 알 수 없음”
메트릭은 필수적이지만, 때로는 상관 관계가 필요합니다:
- 요청 메타데이터 (모델, 토큰 수, TTFT)와 함께 구조화된 로그 추가
- 게이트웨이 및 추론 서버 주변의 트레이싱 (OpenTelemetry) 추가
- 지원되는 경우, 예제를 사용하여 지연 시간 급증에서 트레이스로 이동
좋은 워크플로우: Grafana 대시보드 급증 → Explore 클릭 → 인스턴스/모델로 좁히기 → 해당 기간의 로그/트레이스 확인
이것은 관측 가능성 및 모니터링 아키텍처 가이드에서 설명한 고전적인 메트릭 → 로그 → 트레이스 모델을 따릅니다.
6) vLLM / 다프로세스 메트릭 특이점
서빙 스택이 여러 프로세스에서 실행 중이라면, Prometheus 다프로세스 구성이 필요할 수 있습니다 (프로세스가 메트릭을 노출하는 방식에 따라 다름). vLLM 문서는 Prometheus polling을 위해 /metrics를 노출하는 것을 강조하며, 배포 시 서버의 메트릭 모드를 확인하세요.
실용적인 “Day-1” 대시보드 및 경고 설정
생산성에 적합한 가벼운 설정을 원한다면, 다음과 같이 시작하세요:
대시보드 패널
- p95 요청 지연 시간
- p95 토큰당 평균 시간
- 대기열 크기
- p95 대기열 지속 시간
- 오류율
- KV 캐시 사용 %
경고
- p95 요청 지연 시간 > X 10분 동안
- p99 대기열 지속 시간 > Y 10분 동안
- 오류율 > 1% 5분 동안
- KV 캐시 사용률 > 90% 15분 동안
- Prometheus 대상이 다운 (항상)
관련 관측 가능성 가이드
- 관측 가능성 가이드: Prometheus, Grafana 및 생산성 모니터링
- Prometheus 모니터링: 설정 및 최고 실천 방법
- Ubuntu에서 Grafana 설치 및 사용: 완전한 가이드
관련 LLM 인프라스트럭처 가이드
마무리 메모
Prometheus + Grafana는 추론 건강에 대한 “상시 활동” 뷰를 제공합니다. 기본 사항을 갖춘 후, 일반적으로 다음 큰 성공은 다음과 같은 것에서 옵니다:
- 모델/테넌트별 SLO
- 요청 형성 (최대 토큰, 병렬 처리 제한)
- 대기열 시간 및 KV 캐시 여유 공간에 따라 자동 확장
모니터링 대 관측 가능성, Prometheus 기초, 생산성 패턴에 대한 보다 넓은 설명이 필요하다면, 제 관측 가능성 가이드를 참조하세요.