서버리스 LLM의 콜드 스타트 완화(Cold Start Mitigation for Serverless LLMs)
20GB 규모 모델 이미지(model image)는 콜드(cold) 상태에서 서빙(serving) 상태로 전환되기까지 7B 모델은 510분, 70B 모델은 20분 이상 걸리기도 합니다. 진정한 서버리스(serverless) 환경에서 이 시간은 워밍업(warm-up)이 아니라 사실상 장애(outage)에 가깝습니다. 완화책은 다섯 계층에서 작동합니다. 사전 적재한 노드 이미지(pre-seeded node image; AWS의 Bottlerocket과 듀얼 볼륨 아키텍처), 모델 스트리밍(model streaming; NVIDIA Run:ai Model Streamer, vLLM 네이티브 지원), GPU 메모리 스냅샷(GPU memory snapshot; Modal 체크포인트는 재시작을 최대 10배 빠르게 만듭니다), 웜 풀(warm pool; min_workers=1), 계층형 로딩(tiered loading; ServerlessLLM의 NVMe→DRAM→HBM 파이프라인은 지연을 10200배 줄입니다), 그리고 KV 캐시(KV cache; GB 단위)가 아니라 입력 토큰(input token; KB 단위)을 옮기는 라이브 마이그레이션(live migration)이 그것입니다. Modal은 콜드 스타트 24초를 공식 하한으로 공개하며, Baseten은 기본 510초, 사전 워밍(pre-warming) 사용 시 1초 미만(sub-second)을 제시합니다. 이 강의는 콜드 스타트를 측정하고, 예산화하고, 다섯 계층을 겹쳐 쌓는 방법을 가르칩니다.
유형: Learn
언어: Python(표준 라이브러리, 학습용 콜드 스타트 경로 시뮬레이터)
선수 지식: Phase 17 · 02(추론 플랫폼 경제학; Inference Platform Economics), Phase 17 · 03(GPU 오토스케일링; GPU Autoscaling)
예상 시간: 약 60분
학습 목표
- 콜드 스타트 완화(cold-start mitigation)의 다섯 계층을 열거하고, 각 계층의 도구(tool) 또는 패턴(pattern)을 하나씩 말할 수 있습니다.
- 70B 모델의 총 콜드 스타트 시간(total cold-start time)을 (노드 프로비전) + (가중치 다운로드) + (가중치를 HBM에 적재) + (엔진 초기화)의 합으로 계산할 수 있습니다.
- 라이브 마이그레이션이 KV 캐시(GB)가 아니라 입력 토큰(KB)을 전송하는 이유와, 그에 따르는 비용이 재계산(recomputation)이라는 점을 설명할 수 있습니다.
- 웜 풀(warm pool)의 절충(trade-off), 즉 유휴(idle) GPU 비용을 부담할지 콜드 스타트 꼬리 지연(tail latency)을 받아들일지를 설명하고,
min_workers > 0이 필수가 되는 SLA 임계값(threshold)을 말할 수 있습니다.
문제
서버리스 LLM 엔드포인트(endpoint)가 밤사이 0으로 축소(scale to zero)됩니다. 오전 8시에 트래픽(traffic)이 급증합니다. 첫 요청은 다음 과정을 기다려야 합니다.
- Karpenter가 GPU 노드를 프로비전(provision)합니다: 45~60초.
- 컨테이너(container)가 가중치(weights)를 포함한 30GB 이미지를 풀(pull)해 옵니다: 120~300초.
- 엔진(engine)이 가중치를 HBM에 적재(load)합니다. 모델 크기와 스토리지 속도에 따라 45~120초.
- vLLM 또는 TRT-LLM이 CUDA 그래프(CUDA graph), KV 캐시 풀(KV cache pool), 토크나이저(tokenizer)를 초기화합니다: 10~30초.
합쳐서 첫 토큰이 돌아오기까지 220510초, 즉 대략 38분이 걸립니다. SLA는 2초입니다. 웜 풀(min_workers=1)을 배포하니 문제가 사라진 것처럼 보이지만, 이제 유휴 GPU 한 대를 하루 24시간 내내(24x7) 지불해야 합니다. 서비스가 5개 제품(product)을 갖고 있고 각각 웜 레플리카(warm replica) 하나를 둔다면, 단 한 명의 사용자도 호출하지 않더라도 매월 5 × 24 × 30 = 3,600 GPU-시간(GPU-hour)을 지출합니다.
콜드 스타트 완화는 서버리스의 경제성(economics)을 유지하면서, 항상 켜진(always-on) 서비스에 가까운 지연(latency)을 만들어 내는 방법입니다.
개념
1계층 — 사전 적재 노드 이미지(pre-seeded node image; Bottlerocket)
AWS에서 Bottlerocket의 듀얼 볼륨 아키텍처(dual-volume architecture)는 OS와 데이터(data)를 분리합니다. 컨테이너 이미지를 미리 풀(pull)해 둔 데이터 볼륨(data volume)을 스냅샷(snapshot)으로 만들고, 그 스냅샷 ID를 EC2NodeClass에서 참조합니다. 새 노드는 가중치가 이미 로컬 NVMe에 자리 잡은 상태로 부팅(boot)합니다. 즉, 위에서 본 2단계와 3단계의 일부가 사라집니다. Karpenter와 기본적으로(natively) 함께 작동합니다. 큰 모델에서는 콜드 스타트마다 보통 2~4분을 절약합니다.
GCP에서는 같은 패턴을 컨테이너 레이어(container layer)가 미리 구워진(pre-baked) 사용자 정의 VM 이미지로 구현합니다. Azure에서는 관리형 디스크 스냅샷(managed disk snapshot)으로 같은 패턴을 구성합니다.
2계층 — 모델 스트리밍(model streaming; Run:ai Model Streamer)
첫 요청에 답하기 전 가중치 파일 전체를 적재하는 대신, 가중치를 레이어 단위(layer-by-layer)로 GPU 메모리에 스트리밍하고, 첫 트랜스포머 블록(transformer block)이 메모리에 자리 잡는 즉시 처리를 시작합니다. NVIDIA Run:ai Model Streamer는 2026년 vLLM에 네이티브로 포함되었습니다. S3, GCS, 로컬 NVMe와 모두 함께 작동합니다. I/O와 컴퓨트 초기화(compute setup)를 겹쳐 큰 모델의 가중치 적재 시간을 대략 절반으로 줄입니다.
3계층 — GPU 메모리 스냅샷(GPU memory snapshot; Modal)
Modal은 첫 적재 직후 GPU 상태(GPU state), 즉 가중치, CUDA 그래프, KV 캐시 영역(KV cache region)의 체크포인트(checkpoint)를 만듭니다. 이후 재시작(restart)은 곧바로 HBM으로 역직렬화(deserialize)됩니다. 처음부터 다시 초기화하는 것보다 10배 빠릅니다. 이는 "2초 안에 웜 GPU를 부팅한다"는 표현에 가장 가깝습니다. 절충점은 스냅샷이 GPU 토폴로지(topology)별로 묶인다는 점입니다. Karpenter가 다른 SKU로 옮기면 다시 체크포인트해야 합니다.
4계층 — 웜 풀(warm pool; min_workers=1)
가장 단순한 완화책은 레플리카 하나를 항상 준비(ready) 상태로 유지하는 것입니다. 비용은 GPU 한 대의 시간당 요금(hourly rate)을 하루 24시간 내내 지불하는 것입니다. 작은 모델에서는 산수가 가혹합니다. 30초짜리 콜드 스타트를 피하려고 시간당 0.85~1.50달러를 냅니다. 큰 모델에서는 비교적 너그럽습니다. 5분짜리 콜드 스타트를 피하려고 시간당 4달러를 냅니다. 웜 풀이 필수가 되는 SLA 임계값은 보통 70B 이상 모델에서 TTFT P99 < 60초입니다.
5계층 — 계층형 로딩(tiered loading; ServerlessLLM)
ServerlessLLM은 스토리지를 계층 구조(hierarchy)로 봅니다. NVMe는 빠르면서 크고, DRAM은 중간 속도이면서 계층화되어 있으며(tiered), HBM은 작지만 즉시 사용 가능합니다. 가중치를 DRAM에 미리 적재해 두고, 필요할 때 HBM으로 적재합니다. 논문은 단순한 디스크-HBM 적재 대비 콜드 적재 지연을 10~200배 줄였다고 보고합니다. 프로덕션 도입은 아직 초기 단계지만 vLLM 통합이 존재합니다.
6계층 — 라이브 마이그레이션(live migration; 보너스 패턴)
노드가 사용할 수 없는 상태가 되었을 때, 예를 들어 스팟 제거(spot eviction)나 노드 드레인(node drain) 상황에서, 전통적인 패턴은 다른 레플리카를 콜드 스타트하고 요청 큐(request queue)를 비우는 방식입니다. 라이브 마이그레이션은 입력 토큰(KB 단위)을 모델이 이미 적재된 목적지(destination)로 옮기고, 그 목적지에서 KV 캐시를 다시 계산합니다. 네트워크로 GB 단위 KV 캐시를 전송하는 것보다 재계산이 더 저렴합니다. 분리형(disaggregated) 배포에 적용됩니다.
웜 풀 산수(warm-pool math)
P99 TTFT SLA가 2초인 서비스에서는 질문이 "웜 풀을 둘 것이냐 말 것이냐"가 아닙니다. "웜 레플리카를 몇 개 둘 것이고, 어떤 경로(path)에 둘 것이냐"입니다.
- 고가치 대화형(interactive) 경로(라이브 채팅, 음성 에이전트):
min_workers=1-2.
- 백그라운드 배치(background batch) 경로(야간 분류 작업): 0으로 축소(scale-to-zero) 허용, 5~10분짜리 콜드 스타트도 허용.
- 프리미엄 등급(premium tier): 테넌트(tenant)별
min_workers와 전용 용량(dedicated capacity).
최적화 전에 측정하기
새 노드 위 70B 모델의 콜드 스타트 해부(예시)는 다음과 같습니다.
| 단계(phase) | 시간 | 완화책 |
|---|
| 노드 프로비전(node provision) | 50초 | Bottlerocket + 사전 적재 이미지, 웜 풀 |
| 이미지 풀(image pull) | 180초 | 사전 적재 데이터 볼륨으로 제거 |
| 가중치를 HBM에 적재(weights to HBM) | 75초 | Model Streamer(절반); GPU 스냅샷(제거) |
| 엔진 초기화(engine init) | 20초 | 영속 CUDA 그래프 캐시(persistent CUDA graph cache) |
| 첫 순전파(first forward) | 3초 | 본질적인 최소 지연 |
| 콜드 합계(total cold) | 328초 | |
| **완화책 적용 시 합계 | 약 15초** | 22배 감소 |
기억해야 할 숫자
- Modal 콜드 스타트: 2~4초(GPU 스냅샷 사용 시).
- Baseten 기본 콜드 스타트: 5~10초, 사전 워밍 사용 시 1초 미만.
- 원본 70B 콜드 스타트: 3~8분.
- Run:ai Model Streamer: 가중치 적재 속도 약 2배 향상.
- ServerlessLLM 계층형 로딩: 지연 10~200배 감소(논문 수치).
사용해보기
code/main.py는 각 완화책을 적용했거나 적용하지 않은 콜드 스타트 경로를 모델링합니다. 총 콜드 스타트 시간, 웜 풀 비용, 그리고 웜 풀이 비용을 회수하기 시작하는 손익분기 요청률(break-even request rate)을 보고합니다.
산출물 만들기
이 강의는 outputs/skill-cold-start-planner.md를 만듭니다. SLA, 모델 크기, 트래픽 형태(traffic shape)가 주어지면 어떤 완화책을 겹쳐 쌓을지 선택합니다.
연습문제
- 쉬움:
code/main.py를 실행합니다. SLO에서 추가 요청 드롭(request drop)으로 콜드 스타트 비용을 치르는 것보다 웜 레플리카가 더 저렴해지는 손익분기 요청률을 계산하세요.
- 중간: P99 TTFT SLA가 3초인 13B 모델을 배포한다고 가정합니다. 이를 달성하는 최소 완화 조합(가장 적은 계층 조합)을 고르세요.
- 중간: Bottlerocket 사전 적재는 이미지 풀은 제거하지만 가중치는 여전히 스냅샷에서 HBM으로 적재해야 합니다. 스냅샷 기반 NVMe가 7GB/s로 읽는다고 할 때 70B 모델의 실제 소요 시간(wall-clock)을 계산하세요.
- 어려움: 서버리스 제공자가 GPU 스냅샷(Modal)을 제공하지만 팀은 "스냅샷이 개인정보(PII)를 누출한다"는 이유로 반대합니다. 양쪽 입장을 모두 논해 보세요. 현실적인 위험(risk)은 무엇이고 완화책은 무엇입니까? 예를 들어 일시 스냅샷(ephemeral snapshot), 암호화(encryption), 네임스페이스 격리(namespace isolation) 같은 방안이 있습니다.
- 어려움: 유료 사용자, 체험 사용자, 배치 워크로드(batch workload)에 대한 계층형 웜 풀 정책을 설계하세요. 웜 레플리카 수와 비용을 산수로 보여주세요.
핵심 용어
| 용어 | 흔한 설명 | 실제 의미 |
|---|
| 콜드 스타트(Cold start) | "큰 멈춤(big pause)" | 새 레플리카에서 요청부터 첫 토큰까지 걸리는 시간 |
| 웜 풀(Warm pool) | "항상 켜진 최소값" | 최소 한 개의 레플리카를 준비 상태로 유지하기 위한 min_workers >= 1 |
| 사전 적재 이미지(Pre-seeded image) | "구운 AMI(baked AMI)" | 컨테이너와 가중치가 미리 상주(resident)한 노드 이미지 |
| Bottlerocket | "AWS 노드 OS" | 듀얼 볼륨 스냅샷을 지원하는 AWS 컨테이너 전용 OS |
| 모델 스트리머(Model streamer) | "스트리밍 적재" | 가중치 I/O와 컴퓨트 초기화를 겹치는 방식 |
| GPU 스냅샷(GPU snapshot) | "HBM 체크포인트" | 적재 이후 GPU 상태를 직렬화하고 재시작 시 역직렬화하는 방식 |
| 계층형 로딩(Tiered loading) | "NVMe + DRAM + HBM" | 스토리지 계층 구조. 필요할 때 적재 |
| 라이브 마이그레이션(Live migration) | "토큰 이동" | 입력(KB)을 전송하고 목적지에서 KV를 재계산하는 방식 |
min_workers | "웜 레플리카" | 서버리스 최소 유지(keep-alive) 개수 |
| 0으로 축소(Scale-to-zero) | "완전 서버리스" | 유휴 비용은 0이지만 콜드 스타트 비용 전체를 감수하는 방식 |
더 읽을거리