- Published on
KServe+Knative로 GPU 모델 무중단 롤아웃
- Authors
- Name
- 스타차일드
- https://x.com/ETFBITX
서빙 중인 GPU 모델을 교체할 때 가장 무서운 순간은 두 가지입니다. 첫째, 새 모델 파드가 뜨기 전까지 트래픽이 끊기는 순간(다운타임). 둘째, 새 모델이 뜨긴 떴는데 예측 품질이나 레이턴시가 망가져서 장애로 번지는 순간입니다.
KServe는 모델 서빙을 InferenceService로 추상화하고, Knative는 리비전 기반 배포와 트래픽 분할(카나리)을 제공합니다. 둘을 조합하면 GPU 모델도 애플리케이션처럼 무중단 롤아웃을 설계할 수 있습니다. 이 글은 “GPU라는 비싼 자원”과 “모델 로딩/워밍업이 느리다”는 현실을 전제로, 운영에서 실제로 필요한 설정 포인트를 중심으로 정리합니다.
아키텍처 개요: KServe와 Knative의 역할 분담
KServe가 해주는 것
- 모델 서버(예: TorchServe, Triton, vLLM 등) 배포를
InferenceService로 관리 - 스토리지(예: S3, GCS, PVC)에서 모델 아티팩트 로딩
- 요청 라우팅, 스케일링, 관측(메트릭/로그) 연계
Knative가 해주는 것
- 리비전(Revision) 단위로 “새 버전”을 안전하게 띄움
- 트래픽을 리비전 간에 비율로 분할(예: 90% 기존, 10% 신규)
- 점진적 전환, 즉시 롤백(트래픽을 다시 기존으로 100%)
핵심은 “새 모델 = 새 리비전”으로 만들고, 트래픽만 천천히 옮기는 것입니다.
무중단 롤아웃의 전제 조건: GPU/스케줄링 이슈부터 잡기
GPU 모델은 일반 웹 서비스보다 배포 실패의 원인이 더 다양합니다. 특히 새 리비전을 띄우는 순간 클러스터 자원이 부족하면 카나리 자체가 시작되지 않습니다.
- GPU 노드에 여유가 없으면 새 리비전이
Pending에 머무름 - 모델 로딩이 길면 준비(Ready)까지 시간이 오래 걸림
- 오토스케일이 0으로 떨어지면 콜드스타트가 발생
리비전이 뜨지 않는 문제는 “배포 전략” 이전에 “스케줄링/리소스” 문제인 경우가 많습니다. EKS에서 파드가 Pending으로 멈출 때의 점검 포인트는 아래 글도 같이 참고하면 좋습니다.
기본 예제: GPU InferenceService 정의
아래 예시는 KServe InferenceService에 GPU 리소스를 요청하고, Knative 기반으로 리비전이 생성되도록 하는 전형적인 형태입니다. (클러스터에 설치된 KServe 버전/ServingRuntime에 따라 필드가 조금 다를 수 있습니다.)
apiVersion: serving.kserve.io/v1beta1
kind: InferenceService
metadata:
name: gpu-model
namespace: ml-serving
spec:
predictor:
containers:
- name: predictor
image: ghcr.io/acme/ml/gpu-model-server:1.0.0
ports:
- containerPort: 8080
resources:
requests:
cpu: "2"
memory: "8Gi"
nvidia.com/gpu: "1"
limits:
cpu: "4"
memory: "16Gi"
nvidia.com/gpu: "1"
env:
- name: MODEL_PATH
value: "/models/model"
여기서 “무중단”의 출발점은 새 이미지를 올려도 기존 리비전이 살아있어야 한다는 점입니다. KServe는 내부적으로 Knative Service를 만들고, 이미지 변경은 새 리비전을 생성합니다.
카나리 롤아웃: 트래픽을 리비전 간 분할하기
전략 1) 트래픽 비율로 점진 전환
운영에서 가장 많이 쓰는 방식은 1% 또는 5%로 시작해 관측 지표가 안정적이면 25% → 50% → 100%로 올리는 방식입니다.
Knative 트래픽 분할은 KServe가 생성한 Knative Service(또는 KServe가 제공하는 트래픽 라우팅 인터페이스)를 통해 제어합니다. 환경에 따라 접근 방식이 다르므로, “원리”를 이해하는 게 중요합니다.
- 새 리비전이
Ready상태가 될 때까지 트래픽을 보내지 않는다 Ready이후에도 초기에는 소량만 보내서 안전성을 확인한다- 이상 징후가 있으면 트래픽을 즉시 0으로 내려 롤백한다
전략 2) 블루그린(즉시 전환) + 빠른 롤백
모델 교체가 자주 없고, 테스트가 충분히 되었으며, 전환 시점만 무중단이면 되는 경우 블루그린이 단순합니다.
- Blue(기존) 100% 유지
- Green(신규)
Ready될 때까지 대기 - 전환 시점에 Green 100%
- 문제 생기면 즉시 Blue 100%로 복귀
CI/CD로 블루그린을 운영하는 관점은 아래 글의 접근이 그대로 참고됩니다. 모델 배포도 결국 “리비전 두 개를 띄우고 트래픽만 바꾸는 문제”로 귀결됩니다.
GPU 모델에서 카나리가 특히 중요한 이유
GPU 모델은 카나리에서 잡아야 하는 리스크가 CPU 서비스보다 훨씬 큽니다.
- 레이턴시 급증: 커널/텐서RT/드라이버 조합, 배치 크기, 동시성 설정에 따라 p95가 급격히 튈 수 있음
- 메모리 누수/프래그먼테이션: 장시간 서빙 시 GPU 메모리가 점점 잠식될 수 있음
- 품질 회귀: 모델 파일 교체, 토크나이저 버전 차이, 전처리 변경 등
따라서 카나리 단계에서는 최소한 아래를 봐야 합니다.
- p50/p95/p99 레이턴시
- 오류율(HTTP 5xx, 타임아웃)
- GPU 메모리 사용량, GPU util
- 모델 품질 지표(가능하면 온라인 샘플링 검증)
콜드스타트와 워밍업: “무중단인데 느려짐”을 막기
무중단은 “연결이 끊기지 않음”만 의미하지 않습니다. 새 리비전이 트래픽을 받기 시작했는데 모델 로딩 때문에 응답이 느려지면 사용자 입장에서는 장애처럼 느껴집니다.
1) 최소 스케일 설정으로 0 스케일 방지
Knative는 기본적으로 트래픽이 없으면 0으로 스케일 다운할 수 있습니다. GPU 모델은 콜드스타트 비용이 크므로, 최소 1개는 유지하는 편이 운영 안정성에 유리합니다.
KServe/Knative 설정 방식은 설치 형태에 따라 다르지만, 일반적으로는 리비전의 최소 스케일을 1 이상으로 유지하는 방향으로 잡습니다.
- 운영 트래픽이 있는 엔드포인트:
minScale을 1 또는 그 이상 - 야간에 트래픽이 거의 없는 엔드포인트: 비용과 콜드스타트 사이에서 타협
2) readinessProbe를 “모델 로딩 완료” 기준으로
컨테이너가 떴다고 바로 트래픽을 받으면 안 됩니다. 모델 로딩과 엔진 초기화까지 끝난 뒤에만 Ready가 되도록 readinessProbe를 구성해야 카나리/블루그린이 의미가 있습니다.
readinessProbe:
httpGet:
path: /health/ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 2
timeoutSeconds: 1
failureThreshold: 30
/health/ready는 “프로세스 살아있음”이 아니라 “모델이 GPU에 올라가 있고 첫 추론이 가능한 상태”를 반환하도록 구현하는 게 핵심입니다.
3) 워밍업 요청(프리히트) 넣기
새 리비전이 Ready가 된 직후에도 첫 요청이 느릴 수 있습니다. 커널 캐시, 그래프 컴파일, 메모리 할당이 첫 추론에서 발생하기 때문입니다.
배포 파이프라인에서 카나리 트래픽을 올리기 전에 워밍업 요청을 몇 번 보내는 것을 권장합니다.
# 워밍업: 대표 입력으로 10회 호출
for i in $(seq 1 10); do
curl -sS -X POST "$PREDICT_URL" \
-H 'Content-Type: application/json' \
-d '{"instances":[{"text":"warmup"}]}' > /dev/null
done
트래픽 전환 자동화: 안전장치가 있는 단계적 승격
사람이 수동으로 10% → 50% → 100%를 올려도 되지만, GPU 모델은 배포 빈도가 높아질수록 자동화가 필요합니다.
권장 패턴은 아래와 같습니다.
- 새 리비전 배포
- 새 리비전
Ready확인 - 워밍업 호출
- 트래픽 1%로 5~10분
- SLO 통과 시 10% → 25% → 50% → 100%
- 어느 단계에서든 실패하면 즉시 0%로 내리고 종료
이때 “SLO 판정”은 최소한 다음을 포함하세요.
- 오류율 임계치(예: 5xx 비율)
- 레이턴시 임계치(예: p95)
- GPU 메모리 임계치(예: OOM 위험)
롤백 설계: 모델은 되돌리기 쉬워야 한다
무중단의 완성은 “전환”이 아니라 “즉시 복귀”입니다.
- 트래픽을 신규에서 기존으로 즉시 100% 되돌릴 수 있어야 함
- 신규 리비전은 바로 삭제하지 말고 일정 시간 보관(관측/포렌식)
- 모델 아티팩트/이미지 태그는 불변(immutable)하게 관리
특히 이미지 태그를 latest 같은 가변 태그로 운영하면, “롤백했는데도 같은 태그가 다른 바이너리를 가리켜서” 되돌아가지 않는 사고가 납니다. 모델 서빙은 재현 가능성이 생명이라, 태그를 빌드 해시나 버전으로 고정하세요.
운영에서 자주 터지는 이슈와 처방
1) 새 리비전이 Pending에 오래 머문다
- GPU 노드 부족
- 노드 셀렉터/테인트-톨러레이션 불일치
- 요청 리소스 과다(특히 메모리)
이 경우는 트래픽 분할 이전에 스케줄링부터 해결해야 합니다. 앞서 소개한 Pending 점검 글의 체크리스트가 그대로 적용됩니다.
2) Ready는 되는데 카나리 트래픽에서 타임아웃이 난다
- readinessProbe가 “모델 로딩 완료”를 보장하지 못함
- 워밍업 부재
- 동시성/배치 설정이 실제 트래픽에 맞지 않음
해결은 readinessProbe 기준 강화 + 워밍업 + 부하 테스트(카나리 전 단계)입니다.
3) GPU 비용이 감당이 안 된다
- minScale을 너무 높게 잡음
- 카나리 기간이 과도하게 길어짐
비용과 안정성의 균형을 위해 “업무 시간 minScale 1, 야간 0” 같은 정책도 고려할 수 있습니다. 다만 야간 콜드스타트는 장애로 오인될 수 있으니, 호출 패턴과 SLA를 먼저 합의하세요.
간단한 배포 파이프라인 예시(개념)
아래는 “새 이미지 적용 → 준비 확인 → 워밍업 → 카나리 시작”의 최소 흐름을 보여주는 예시입니다. 실제로는 관측/판정 로직이 더 들어갑니다.
# 1) 새 이미지로 InferenceService 업데이트
kubectl -n ml-serving set image inferenceservice/gpu-model \
predictor=ghcr.io/acme/ml/gpu-model-server:1.1.0
# 2) Ready 대기
kubectl -n ml-serving wait --for=condition=Ready inferenceservice/gpu-model --timeout=600s
# 3) 워밍업
PREDICT_URL=$(kubectl -n ml-serving get inferenceservice gpu-model -o jsonpath='{.status.url}')
for i in $(seq 1 10); do
curl -sS -X POST "$PREDICT_URL/v1/models/model:predict" \
-H 'Content-Type: application/json' \
-d '{"instances":[{"text":"warmup"}]}' > /dev/null
done
# 4) 이후 단계: Knative 트래픽을 1%로 시작(환경별로 적용 방식 상이)
# 여기서는 개념만: "new=1%, old=99%"
중요한 점은 “KServe 리소스가 Ready라고 해서, 사용자 체감까지 안전하다고 단정하면 안 된다”는 것입니다. 워밍업과 카나리 관측이 그 간극을 메웁니다.
체크리스트: GPU 모델 무중단 롤아웃을 위한 필수 항목
- 모델 버전은 불변 태그로 관리(이미지/아티팩트)
- readinessProbe는 모델 로딩 완료 기준
- 워밍업 요청을 배포 파이프라인에 포함
- 카나리 트래픽 분할로 지표 확인 후 승격
- 즉시 롤백 가능한 트래픽 스위치 경로 확보
- GPU 스케줄링(노드/테인트/리소스) 사전 검증
- 콜드스타트가 문제면
minScale로 0 스케일 방지
마무리
KServe와 Knative를 조합하면 “GPU 모델도 애플리케이션처럼” 리비전 단위로 안전하게 교체할 수 있습니다. 무중단 롤아웃의 본질은 새 모델을 먼저 안전하게 띄우고(Ready와 워밍업), 트래픽을 통제된 방식으로 옮기며(카나리/블루그린), 언제든 되돌릴 수 있게 만드는 것입니다.
다음 단계로는 관측(프로메테우스/그라파나) 기반의 자동 승격, 모델 품질 회귀 탐지(온라인 샘플링), 그리고 배포 파이프라인에 SLO 게이트를 넣는 쪽으로 확장하면 운영 난이도가 크게 내려갑니다.