오픈소스 모델 서빙: KServe·NVIDIA Triton·vLLM 비교와 선택
개요
학습이 끝난 모델을 실제 트래픽에 붙이는 것이 **서빙(serving)**이다. 매니지드 서비스(SageMaker 등) 대신 **자체 인프라(Kubernetes)**에서 서빙할 때 자주 쓰이는 세 스택이 KServe, NVIDIA Triton, vLLM이다. 셋은 경쟁 관계라기보다 다른 계층을 담당한다. KServe는 K8s 위의 서빙 오케스트레이션(배포·오토스케일·카나리)을, Triton은 다중 프레임워크를 아우르는 고성능 추론 서버 엔진을, vLLM은 LLM에 특화된 처리량 최적화 엔진을 맡는다. 실무에서는 이들을 조합한다. 예를 들어 KServe가 InferenceService로 오토스케일·라우팅을 관리하고, 그 서빙 런타임으로 vLLM이나 Triton을 감싸는 식이다.
원리와 핵심 개념
KServe — K8s 표준 추론 서비스
KServe는 InferenceService라는 **CRD(Custom Resource Definition)**로 모델 배포를 선언형으로 표준화한다. 핵심 기능은 다음과 같다.
- 런타임 추상화: sklearn/XGBoost/PyTorch/TensorFlow/ONNX부터 vLLM·Triton까지
ServingRuntime으로 감싸, 배포 인터페이스를 통일한다. - Scale-to-zero 오토스케일: Knative 기반으로 트래픽이 없으면 파드를 0까지 줄여 GPU 비용을 아끼고, 요청이 오면 콜드스타트로 다시 띄운다.
- 카나리 롤아웃:
canaryTrafficPercent로 신규 모델에 소수 트래픽만 흘려 관측 후 확대한다(배포 전략 - Rolling·Blue-Green·Canary). - Transformer/Predictor 분리: 전처리(Transformer)와 추론(Predictor)을 별도 컴포넌트로 나눠 독립 스케일한다.
NVIDIA Triton — 다중 프레임워크 추론 서버
Triton Inference Server는 프레임워크에 무관한 고성능 추론 서버다.
- 다중 프레임워크 백엔드: TensorRT, ONNX Runtime, PyTorch(LibTorch), TensorFlow, Python, 그리고 LLM용 TensorRT-LLM 백엔드를 한 서버에서 지원.
- 동적 배칭(dynamic batching): 개별로 도착한 요청을 서버가 짧은 시간 모아 하나의 배치로 묶어 GPU 활용률과 처리량을 높인다.
- 멀티모델·동시 실행: 한 GPU에서 여러 모델을 동시에 로드하고 인스턴스 그룹으로 병렬 실행한다.
- 모델 앙상블: 전처리→모델→후처리를 서버 내 파이프라인으로 연결한다.
vLLM — LLM 특화 처리량 엔진
vLLM은 LLM 추론의 처리량을 끌어올린 엔진으로, 핵심은 PagedAttention이다.
- PagedAttention: 트랜스포머의 KV 캐시를 OS 가상 메모리처럼 페이지 단위로 관리한다. 기존 서빙은 시퀀스마다 최대 길이만큼 KV 캐시를 연속 예약해 심한 내부 단편화가 발생했는데, PagedAttention은 캐시를 고정 크기 블록으로 쪼개 필요할 때만 할당한다. 낭비가 거의 사라져 동일 GPU로 훨씬 많은 동시 요청과 긴 컨텍스트를 처리한다.
- Continuous batching: 배치 내 시퀀스가 끝나면 즉시 새 요청을 채워 GPU를 놀리지 않는다.
- OpenAI 호환 API:
/v1/chat/completions등 OpenAI 스키마를 그대로 제공해 클라이언트 교체 없이 붙는다. - prefix caching, speculative decoding, 텐서·파이프라인 병렬 등 LLM 최적화를 폭넓게 지원한다.
선택 기준
| 요구사항 | 우선 후보 | 이유 |
|---|---|---|
| LLM을 높은 처리량으로 대량 서빙 | vLLM | PagedAttention·continuous batching·OpenAI API |
| 다양한 프레임워크·비-LLM 모델 혼재 | Triton | 다중 백엔드·동적 배칭·멀티모델 |
| K8s에서 오토스케일·카나리 표준화 | KServe | InferenceService·scale-to-zero·트래픽 분할 |
| 위 전부(운영 + 성능) | KServe + (vLLM | Triton) | 오케스트레이션은 KServe, 엔진은 vLLM/Triton |
실전: KServe로 vLLM 런타임 배포
# vLLM을 서빙 런타임으로 감싼 KServe InferenceService
apiVersion: serving.kserve.io/v1beta1
kind: InferenceService
metadata:
name: llm-chat
spec:
predictor:
minReplicas: 0 # scale-to-zero (유휴 시 GPU 반납)
maxReplicas: 4
model:
modelFormat: { name: vLLM }
args:
- --max-model-len=8192
- --gpu-memory-utilization=0.9
resources:
limits: { nvidia.com/gpu: "1" }
# 신규 버전에 10%만 흘리는 카나리
# canaryTrafficPercent: 10# OpenAI 호환 엔드포인트로 호출 (vLLM)
curl http://llm-chat.default/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{"model":"chat","messages":[{"role":"user","content":"안녕"}]}'Triton 단독 배포 시에는 모델 리포지토리 규약(model_repository/<name>/config.pbtxt + 버전 디렉터리)에 dynamic_batching { max_queue_delay_microseconds: 100 } 같은 배칭 정책을 선언한다.
함정과 베스트프랙티스
| 함정 | 문제 | 대응 |
|---|---|---|
| scale-to-zero 콜드스타트 | LLM 가중치 로드로 수십 초 지연 | 최소 레플리카 1, 또는 예열/모델 캐시 |
gpu-memory-utilization 과대 | KV 캐시 부족으로 OOM/처리량 저하 | 여유를 두고 컨텍스트 길이와 균형 |
| 배칭 지연 오해 | 동적 배칭이 tail latency를 키움 | 배치 지연·최대 배치 크기 튜닝 |
| 처리량 vs 지연 혼동 | 벤치를 잘못 해석 | 목표에 맞춰 throughput/latency 분리 측정 |
| 관측 부재 | 병목·포화를 못 봄 | GPU 사용률·큐·TTFT/TPOT 모니터 |
- 핵심 LLM 지표를 관측한다: TTFT(첫 토큰까지 시간), TPOT(토큰당 시간), 처리량, GPU 사용률, KV 캐시 점유. Prometheus와 Grafana로 대시보드화, 호출 체인은 OpenTelemetry - 분산 추적으로.
- 엔진은 KServe로 감싸 오토스케일·카나리·롤백을 표준화한다. K8s 위에서 운영한다.
- 추론 최적화 기법(PagedAttention·speculative decoding·quantization)은 개념 레벨을 27.Technique에서 교차 참고한다.
정리
KServe·Triton·vLLM은 서로 다른 계층을 담당한다. KServe는 K8s 위 InferenceService로 오토스케일(scale-to-zero)·카나리·런타임 추상화를 제공하고, Triton은 다중 프레임워크·동적 배칭·멀티모델을 아우르는 범용 추론 서버이며, vLLM은 PagedAttention으로 KV 캐시 낭비를 없애 LLM을 높은 처리량으로 서빙하고 OpenAI 호환 API를 노출한다. LLM 대량 서빙은 vLLM, 이종 모델 혼재는 Triton, K8s 표준화는 KServe로 감싸는 조합이 실전 정석이다. LLM 앱 파이프라인 맥락은 RAG 파이프라인 - 청킹부터 생성까지, 확산형 LLM 서빙 동향은 Diffusion-LM - 개요와 최근 동향과 이어진다.
키워드: #model-serving #mlops KServe Triton vLLM PagedAttention KV-cache