GPU 8장짜리 노드 4대에 vLLM을 올려놓고 Service 하나 붙이면 끝이라고 생각한 적 있을 것이다. 나도 그랬다. 그리고 프로덕션 트래픽이 들어오는 순간 깨달았다 — 라운드로빈은 LLM 서빙에서 최악의 선택이다.
왜 라운드로빈이 문제인가
HTTP API 서빙할 때는 라운드로빈이 괜찮다. 요청 하나에 수 밀리초, 상태 없음, 리소스 소비도 균일하다. LLM 추론은 전부 다르다.
한 요청이 수 초에서 수십 초까지 걸린다. KV 캐시가 GPU 메모리를 물고 있다. 모델 A와 모델 B가 같은 Pod에 LoRA 어댑터로 올라가 있을 수도 있다. 라운드로빈은 이 중 아무것도 모른다. 그냥 다음 Pod으로 보낸다.
결과? GPU 3번은 VRAM이 터지기 직전인데 GPU 7번은 놀고 있다. prefill 큐가 한쪽에 몰려서 TTFT(Time To First Token)가 4배 차이 난다. 사용자 경험은 p50이 아니라 p99에서 결정되는데, 로드밸런서가 GPU 상태를 보지 않으니 p99가 치솟는 건 예정된 수순이다.
InferencePool과 InferenceModel — CRD 두 개로 해결한다
Kubernetes SIG Network에서 이 문제를 정면으로 다루는 프로젝트가 나왔다. Gateway API Inference Extension. 이름이 길어서 "추론 게이트웨이"라고 부르겠다. 이미 GA 상태다.
핵심은 CRD 두 개다.
InferencePool은 같은 GPU 노드 풀에서 모델을 서빙하는 Pod 집합을 정의한다. 기존 Service와 비슷하지만 결정적 차이가 있다 — 각 Pod의 실시간 메트릭을 수집한다. LLM 큐 깊이, 가용 GPU 메모리, 어댑터 프리로드 여부까지.
InferenceModel은 사용자에게 노출되는 모델 엔드포인트다. model: "llama-3-70b-chat"이라고 정의하면 클라이언트는 OpenAI 호환 API로 그냥 요청을 보내면 된다. 어떤 Pod이 그 모델을 서빙하는지, 어떤 LoRA 어댑터가 올라가 있는지는 추론 게이트웨이가 알아서 매핑한다.
apiVersion: inference.networking.x-k8s.io/v1alpha2
kind: InferenceModel
metadata:
name: llama-chat
spec:
modelName: llama-3-70b-chat
criticality: Standard
poolRef:
name: gpu-pool
targetModels:
- name: llama-3-70b-instruct
weight: 90
- name: llama-3-70b-instruct-v2
weight: 10
이렇게 하면 canary 배포도 된다. 새 모델 버전에 10%만 흘려보면서 레이턴시 비교하고, 문제없으면 weight를 올리면 그만이다. GPU 워크로드에서 이 정도의 canary를 선언적으로 할 수 있는 방법이 이전에는 사실상 없었다.
Endpoint Picker가 진짜 두뇌다
라우팅의 핵심은 "endpoint picker"다. 요청이 들어올 때마다 InferencePool에 속한 모든 Pod의 상태를 실시간으로 보고 최적의 Pod을 고른다. 고르는 기준이 라운드로빈과는 차원이 다르다.
KV 캐시 히트율. 이전 대화의 prefix cache가 어떤 Pod에 남아있는지 안다. 같은 세션의 후속 요청은 캐시가 있는 Pod으로 보내면 prefill을 건너뛰니까 TTFT가 수백 밀리초 줄어든다. 멀티턴 챗봇이라면 이 차이가 체감된다.
큐 깊이와 GPU 메모리. 대기 중인 추론 요청이 적고 VRAM 여유가 있는 Pod을 우선 선택한다. vLLM의 continuous batching과 합쳐지면 클러스터 전체의 GPU 활용률이 훨씬 균일해진다.
어댑터 상태. 요청된 LoRA 어댑터가 이미 메모리에 올라와 있는 Pod을 고른다. 어댑터 스왑에 수 초가 걸릴 수 있는데, 이걸 피할 수 있다면 피해야 한다.
Criticality 기반 쉐딩. InferenceModel에 Critical, Standard, Sheddable 같은 우선순위를 매길 수 있다. GPU가 부족할 때 프로덕션 채팅은 유지하고 내부 배치 요약 작업을 드롭하는 식의 정책이 YAML 한 줄로 가능해진다.
프로덕션에 넣을 수 있나
지원하는 게이트웨이 구현체가 이미 꽤 된다. Envoy Gateway가 레퍼런스 구현체이고, kgateway 2.0, GKE Gateway가 네이티브 지원한다. KubeCon Europe 2026에서 Istio가 베타 지원을 발표했고, NGINX Gateway Fabric도 문서를 공개한 상태다.
GKE를 쓰고 있다면 GKE Gateway 조합이 가장 빠른 경로다. 온프레미스라면 Envoy Gateway를 기준으로 잡는 게 안전하다.
달라지는 것
이 프로젝트 전에는 K8s에서 LLM을 서빙한다는 게 좀 억지스러웠다. vLLM이나 TGI를 Deployment로 띄우고 Service를 붙이면 작동은 한다. 근데 트래픽 관리가 원시적이었다. 모델 라우팅? 수동 Ingress 규칙. Canary? 직접 트래픽 분배 로직을 짜거나 포기하거나. 결국 SageMaker나 Vertex AI로 도망가거나, 커스텀 프록시를 만들게 됐다.
추론 게이트웨이는 "K8s 네이티브로 AI 인프라를 운영한다"는 말을 허풍이 아니게 만든다. 모델 라우팅, canary, 우선순위 기반 쉐딩까지 전부 선언적으로. GPU 위에서 돌아가는 워크로드가 드디어 일급 시민 대접을 받기 시작한 셈이다.
kubectl get inferencepool — 곧 치게 될 명령어다.