글 목록

KServe + llm-d + vLLM로 만드는 클라우드 네이티브 LLM 추론 (2026)

KServe가 CNCF 프로젝트가 되고 v0.16에서 LLMInferenceService를 내놓았습니다. vLLM·llm-d와 엮어 KV-cache 인지 라우팅으로 처리량 3배·TTFT 2배를 만드는 프로덕션 추론 아키텍처를 정리합니다.

IntentCode··6 min read

LLM을 데모로 띄우는 것과 프로덕션에서 비용·지연을 통제하며 운영하는 것은 전혀 다른 문제입니다. GPU는 비싸고, 트래픽은 들쭉날쭉하며, 같은 프롬프트가 반복돼도 매번 처음부터 계산하면 돈이 샙니다.

2026년 들어 이 문제의 표준 답이 빠르게 수렴하고 있습니다. KServe가 CNCF에 기증되고 v0.16에서 LLMInferenceService를 정식화했으며, vLLM이 실행 엔진, llm-d가 KV-cache 인지 라우팅을 담당하는 조합입니다. 한 배포 사례에서는 prefix-cache 라우팅만으로 출력 토큰/초 3배, TTFT(첫 토큰 지연) 2배 감소가 보고됐습니다.

왜 지금 이 스택인가

직접 vLLM 한 대를 띄우면 데모는 됩니다. 하지만 트래픽이 늘면 다음이 무너집니다.

  • 오토스케일: 요청이 몰리면 GPU 파드를 늘려야 하는데, 콜드 스타트가 길다
  • 라우팅: 같은 사용자의 후속 질문이 다른 파드로 가면 KV-cache를 못 쓴다
  • 거버넌스: 모델 버전·롤아웃·카나리를 표준화해야 한다

KServe + llm-d + vLLM은 이 세 가지를 쿠버네티스 네이티브로 풀어줍니다.

접근오토스케일KV-cache 재사용거버넌스적합도
vLLM 단독수동단일 파드 내만없음데모·소규모
매니지드 API(폐쇄형)자동불투명벤더 종속빠른 시작
KServe + llm-d + vLLMscale-to-zero~N클러스터 전역표준 CRD프로덕션

핵심 구성요소 분해

역할이 깔끔하게 나뉘는 게 이 스택의 장점입니다.

  • KServe — 모델 수명주기·거버넌스. LLMInferenceService CRD로 OpenAI 호환 API·토큰 스트리밍 제공
  • vLLM — 실제 추론 엔진. PagedAttention으로 KV-cache를 효율적으로 관리
  • llm-d — 런타임 간 라우팅 + prefix-cache 인지 라우팅. 같은 프리픽스(시스템 프롬프트·대화 맥락)를 가진 요청을 같은 vLLM 인스턴스로 보냄

prefix-cache 인지 라우팅이 핵심인 이유

LLM 비용의 상당 부분은 프롬프트(입력) 재계산에서 나옵니다. RAG처럼 시스템 프롬프트 + 긴 컨텍스트가 매 요청 반복되면, 매번 KV-cache를 처음부터 채우는 건 낭비입니다. llm-d는 요청의 프리픽스를 보고 이미 그 캐시를 가진 파드로 라우팅합니다.

# LLMInferenceService — OpenAI 호환 엔드포인트 (KServe v0.16)
apiVersion: serving.kserve.io/v1alpha1
kind: LLMInferenceService
metadata:
  name: qwen-chat
spec:
  model:
    uri: hf://Qwen/Qwen2.5-7B-Instruct
  runtime:
    name: vllm
    args:
      - --max-model-len=8192
      - --enable-prefix-caching      # vLLM 내부 prefix cache
  router:
    cacheAware: true                 # llm-d KV-cache 인지 라우팅
  replicas:
    min: 0                           # scale-to-zero
    max: 8

실전 적용 가이드

1. 사전 조건

# GPU 노드풀 + KServe(서버리스 모드) 설치
kubectl get nodes -L nvidia.com/gpu.product
helm install kserve oci://ghcr.io/kserve/charts/kserve --version v0.16.0 \
  --namespace kserve --create-namespace

2. 모델 배포

LLMInferenceService 매니페스트를 적용하면 KServe가 vLLM 런타임 파드 + 라우터를 생성합니다.

kubectl apply -f qwen-chat.yaml
kubectl get llminferenceservice qwen-chat -w
# READY=True 가 되면 OpenAI 호환 엔드포인트 노출

3. 호출 (OpenAI 호환)

curl -s http://qwen-chat.default.svc/v1/chat/completions \
  -H 'Content-Type: application/json' \
  -d '{
    "model": "qwen-chat",
    "messages": [{"role": "user", "content": "RAG가 뭐야?"}],
    "stream": true
  }'

기존 OpenAI SDK 코드를 base_url만 바꿔 그대로 쓸 수 있다는 게 운영 전환 비용을 크게 낮춥니다.

const client = new OpenAI({
  baseURL: 'http://qwen-chat.default.svc/v1',
  apiKey: 'unused', // 클러스터 내부 호출
});

4. 부하 기반 오토스케일

KServe는 동시성(concurrency) 기반으로 0→N 스케일합니다. 트래픽이 없으면 GPU 비용 0, 몰리면 자동 확장 — 이게 매니지드 API 대비 비용을 통제하는 핵심입니다.

트러블슈팅: 자주 만나는 3가지

1. 콜드 스타트가 너무 길다 모델 가중치 로딩이 병목입니다. min: 0 대신 min: 1로 워밍 파드 1개를 유지하거나, 가중치를 노드 로컬 캐시(emptyDir/PVC)에 미리 내려둡니다.

2. KV-cache 적중률이 낮다 라우터가 cache-aware인지(router.cacheAware: true), vLLM에 --enable-prefix-caching이 켜졌는지 확인합니다. 둘 다 켜야 클러스터 전역 재사용이 됩니다.

3. GPU OOM --max-model-len을 낮추거나 양자화(AWQ/GPTQ) 모델을 사용해 KV-cache 메모리를 줄입니다.

IntentCode 관점

우리는 RAG·에이전트 워크로드에서 시스템 프롬프트 + 검색 컨텍스트가 반복되는 패턴이 많기 때문에, prefix-cache 인지 라우팅의 이득이 특히 큽니다. "모델을 클라우드에 올린다"가 아니라, 추론을 일급 서비스로 다루고 비용·지연을 쿠버네티스 레벨에서 통제하는 것 — 이것이 클라우드 네이티브 AI의 핵심입니다.

정리: 데모는 vLLM 한 대로 충분하지만, 프로덕션은 KServe(거버넌스) + vLLM(실행) + llm-d(캐시 인지 라우팅) 의 합으로 완성됩니다.


참고: KServe는 KubeCon 2025에서 CNCF에 기증되었고, v0.16에서 LLMInferenceService가 도입되었습니다. 버전·기능은 공식 문서(kserve.io, llm-d.ai)에서 최신 상태를 확인하세요.