Kubernetes GPU 자동 확장 — Karpenter, KAI Scheduler, Gang Scheduling

하나의 계층이 아니라 세 개의 계층입니다. Karpenter는 노드(node)를 동적으로 프로비저닝(provisioning)합니다. 보통 1분 안에 끝나며, Cluster Autoscaler보다 약 40% 빠릅니다. KAI Scheduler는 갱 스케줄링(gang scheduling), 토폴로지 인식(topology awareness), 계층형 큐(hierarchical queues)를 처리합니다. 8개 GPU 중 7개만 할당되어 마지막 GPU 하나를 기다리는 동안 일곱 노드가 돈을 태우는 부분 할당(partial allocation) 함정을 막아줍니다. 애플리케이션 수준 자동 확장기(application-level autoscaler), 예를 들어 NVIDIA Dynamo Planner와 llm-d Workload Variant Autoscaler는 CPU나 DCGM 듀티 사이클(duty cycle)이 아니라 추론 특화 신호, 즉 큐 깊이(queue depth), KV 캐시 사용률(KV cache utilization)을 기준으로 확장합니다. 고전적인 HPA 함정은 DCGM_FI_DEV_GPU_UTIL이 듀티 사이클 측정값이라는 점입니다. 100%는 요청 10개일 수도 있고 100개일 수도 있습니다. vLLM은 KV 캐시 메모리를 미리 할당하므로 메모리도 축소(scale-down) 신호가 되지 않습니다. 이 lesson에서는 세 계층을 조합하는 법과, 실행 중인 GPU 작업을 추론 도중 종료할 수 있는 Karpenter 기본 WhenEmptyOrUnderutilized 정책을 피하는 법을 배웁니다.

유형: Learn 언어: Python(표준 라이브러리, 큐 깊이 기반 자동 확장 장난감 시뮬레이터) 선수 지식: Phase 17 · 02(Inference Platform Economics), Phase 17 · 04(vLLM Serving Internals) 예상 시간: 약 75분

학습 목표

  • 세 가지 자동 확장 계층, 즉 노드 프로비저닝(node provisioning), 갱 스케줄링(gang scheduling), 애플리케이션 수준(application-level)을 도식화하고 각 계층에서 쓰는 도구를 말할 수 있습니다.
  • DCGM_FI_DEV_GPU_UTIL이 왜 vLLM의 HPA 신호로 잘못된지 설명하고, 대체 신호 두 가지인 큐 깊이와 KV 캐시 사용률을 말할 수 있습니다.
  • 갱 스케줄링과 KAI Scheduler가 막아주는 부분 할당 실패 모드, 즉 GPU 8개 중 7개가 유휴로 묶이는 상황을 설명할 수 있습니다.
  • 실행 중인 GPU 작업을 종료할 수 있는 Karpenter 통합(consolidation) 정책인 WhenEmptyOrUnderutilized를 이름 붙이고, 2026년 기준 안전한 대안을 말할 수 있습니다.

문제

팀이 Kubernetes 위에 LLM 서빙 서비스를 배포했습니다. HPA 신호로 DCGM_FI_DEV_GPU_UTIL을 설정했습니다. 업무 시간 동안 서비스는 100% 사용률에 고정됩니다. 그런데 HPA는 확장하지 않습니다. 이미 가득 찼다고 판단하기 때문입니다. 수동으로 복제본(replica)을 하나 더 추가하니 TTFT가 떨어집니다. 그래도 HPA는 확장하지 않습니다. 신호가 거짓말을 하고 있습니다.

별도로, 노드에는 Cluster Autoscaler를 사용하고 있습니다. 새벽 2시에 100만 토큰 프롬프트가 들어옵니다. 클러스터는 노드를 프로비저닝하는 데 3분을 쓰고, 요청은 타임아웃됩니다.

또 별도로, 2개 노드에 걸쳐 8개 GPU가 필요한 70B 모델을 배포합니다. 클러스터에는 7개의 GPU가 비어 있고, 나머지 1개는 3개 노드에 흩어져 있습니다. Cluster Autoscaler는 부족한 GPU 1개를 위해 노드를 프로비저닝합니다. 마지막 GPU가 올라올 때까지 7개 노드는 4분 동안 기다리며 비용을 태웁니다.

세 계층, 세 가지 다른 실패 모드입니다. 2026년의 GPU 인식 자동 확장(GPU-aware autoscaling)은 "HPA를 켠다"가 아닙니다. 노드 프로비저닝, 갱 스케줄링, 애플리케이션 신호 기반 자동 확장을 조합하는 일입니다.

사전 테스트

2문제 · 이 강의를 시작하기 전에 얼마나 알고 있는지 확인해보세요

1.vLLM 기반 LLM 서빙에서 DCGM_FI_DEV_GPU_UTIL이 왜 잘못된 HPA 신호인가요?

2.갱 스케줄링(gang scheduling)이 멀티 GPU LLM 배포에서 해결하는 문제는 무엇인가요?

0/2 답변 완료

개념

Layer 1 — 노드 프로비저닝(Karpenter)

Karpenter는 대기 중인 파드(pending pod)를 감시하고 약 45-60초 안에 노드를 프로비저닝합니다. Cluster Autoscaler는 GPU 노드 기준 보통 90-120초가 걸립니다. Karpenter는 NodePool 제약에 따라 인스턴스 타입(instance type)을 동적으로 고릅니다. 파드가 H100 8개를 필요로 하는데 클러스터에 맞는 노드가 없다면, 기존 그룹을 늘리는 대신 필요한 노드를 직접 프로비저닝합니다.

통합 함정(consolidation trap): Karpenter의 기본 consolidationPolicy: WhenEmptyOrUnderutilized는 GPU 풀에 위험합니다. 실행 중인 GPU 노드를 종료해 파드를 더 저렴하고 크기가 맞는 인스턴스로 옮기려 할 수 있습니다. 추론 워크로드에서는 실행 중인 요청을 축출(evict)하고, 새 노드에서 70B 모델을 다시 로드한다는 뜻입니다. 손실은 몇 분의 용량과 요청 실패입니다.

GPU 풀의 안전한 설정은 다음과 같습니다.

disruption:
  consolidationPolicy: WhenEmpty
  consolidateAfter: 1h

이 설정은 Karpenter가 한 시간 뒤 정말 빈 노드만 통합하도록 허용하고, 실행 중인 작업은 축출하지 않습니다.

Layer 2 — 갱 스케줄링(KAI Scheduler)

KAI Scheduler는 기본 kube-scheduler가 처리하지 못하는 일을 맡습니다. 초기 프로젝트명은 "Karp"였고 이후 이름이 바뀌었습니다.

갱 스케줄링(Gang scheduling)은 전부 아니면 전무(all-or-nothing) 방식으로 스케줄링합니다. 8개 GPU가 필요한 분산 추론 파드는 8개가 모두 함께 시작하거나, 아무것도 시작하지 않습니다. 이 기능이 없으면 부분 할당 함정에 빠집니다. 8개 중 7개 파드가 시작한 뒤 무기한 기다리며 돈을 태우는 상황입니다.

토폴로지 인식(Topology awareness)은 어떤 GPU들이 NVLink를 공유하는지, 어느 GPU들이 같은 랙(rack)에 있는지, 어디 사이에 InfiniBand가 있는지 아는 것입니다. 스케줄러는 이 정보를 바탕으로 파드를 배치합니다. DeepSeek-V3 67B 텐서 병렬(tensor-parallel) 워크로드는 하나의 NVLink 도메인(domain) 안에 있어야 하며, KAI Scheduler는 이를 존중합니다.

계층형 큐(Hierarchical queues)는 여러 팀이 우선순위와 할당량(quota)을 두고 같은 GPU 풀을 두고 경쟁하게 합니다. Team A의 프로덕션 피크가 Team B의 학습 작업에 의해 선점(preempt)되는 일은 우선순위 규칙이 허용할 때만 일어납니다.

KAI는 kube-scheduler 옆에 보조 스케줄러(secondary scheduler)로 배포됩니다. 워크로드(workload)에 어노테이션(annotation)을 붙여 KAI를 사용하게 합니다. Ray와 vLLM production-stack 모두 통합됩니다.

Layer 3 — 애플리케이션 수준 신호

HPA 함정: DCGM_FI_DEV_GPU_UTIL은 듀티 사이클(duty-cycle) 지표입니다. 각 샘플링 구간에서 GPU가 일을 하고 있었는지만 측정합니다. 100% 사용률은 동시 요청 10개일 수도 있고 100개일 수도 있습니다. GPU는 어느 쪽이든 바빴습니다. 듀티 사이클로 확장하는 것은 눈을 감고 확장하는 것입니다.

더 나쁜 점은 vLLM과 비슷한 엔진들이 --gpu-memory-utilization까지 KV 캐시 메모리를 미리 할당한다는 것입니다. 요청이 하나뿐이어도 메모리 사용량은 90% 근처에 머뭅니다. 메모리 기반 HPA는 축소(scale-down)를 절대 제대로 하지 못합니다.

2026년의 대체 신호는 다음과 같습니다.

  • 큐 깊이(queue depth): 프리필(prefill)을 기다리는 요청 수.
  • KV 캐시 사용률(KV cache utilization): 활성 시퀀스(active sequence)에 할당된 블록 비율.
  • 복제본(replica)별 P99 TTFT: 실제 SLA 신호.
  • 굿풋(Goodput): 모든 SLO를 만족하는 초당 요청 수.

NVIDIA Dynamo Planner와 llm-d Workload Variant Autoscaler는 이런 신호를 소비해 복제본을 확장합니다. LLM 서빙에서는 HPA를 완전히 대체합니다.

무엇을 언제 사용하는가

확장 결정도구
노드 추가/제거Karpenter
멀티 GPU 작업 스케줄링KAI Scheduler
복제본 추가/제거Dynamo Planner / llm-d WVA 또는 큐 깊이 기반 사용자 정의 HPA
GPU 타입 선택Karpenter NodePool
낮은 우선순위 선점KAI Scheduler 큐

분리형 prefill/decode는 모든 것을 더 복잡하게 만듭니다

분리형 프리필/디코드(disaggregated prefill/decode)를 운영한다면(Phase 17 · 17), 확장 트리거가 서로 다른 두 종류의 파드가 생깁니다. 프리필 파드는 큐 깊이를 기준으로 확장하고, 디코드(decode) 파드는 KV 캐시 압박을 기준으로 확장합니다. llm-d는 이들을 역할별 HPA가 붙은 별도 Services로 노출합니다. 둘 앞에 하나의 HPA를 두려고 하면 안 됩니다.

여기서도 콜드 스타트가 중요합니다

콜드 스타트(cold start) 완화(Phase 17 · 10)는 노드 프로비저닝 시간이 사용자에게 보이기 시작하는 지점입니다. Karpenter의 45-60초 워밍업, 20GB 모델 로드, 엔진 초기화를 합치면 0에서 시작한 요청은 2-5분이 걸립니다. SLO가 중요한 경로에는 웜 풀(warm pool), 예를 들어 min_workers=1을 유지하거나, 애플리케이션 계층에서 Modal 방식의 체크포인팅(checkpointing)을 사용하세요.

기억해야 할 숫자

  • Karpenter 노드 프로비저닝: GPU 노드 기준 약 45-60초. Cluster Autoscaler는 약 90-120초.
  • KAI Scheduler는 부분 할당 낭비, 즉 8개 중 7개만 잡히는 함정을 막아 줍니다.
  • DCGM_FI_DEV_GPU_UTIL을 HPA 신호로 쓰는 방식은 이미 깨져 있습니다. 큐 깊이나 KV 캐시 사용률을 사용하세요.
  • Karpenter WhenEmptyOrUnderutilized는 실행 중인 GPU 작업을 종료할 수 있습니다. 추론에는 WhenEmpty + consolidateAfter: 1h를 사용하세요.

사용해보기

code/main.py는 버스트성 GPU 워크로드에서 세 계층 자동 확장기를 시뮬레이션합니다. 순진한 HPA(듀티 사이클), 큐 깊이 HPA, KAI 갱 스케줄링 기반 확장을 비교합니다. 충족하지 못한 요청 수, 유휴 GPU 분(idle GPU-minutes), 복합 점수를 보고합니다.

산출물 만들기

이 lesson은 outputs/skill-gpu-autoscaler-plan.md를 만듭니다. 클러스터 토폴로지(cluster topology), 워크로드 형태(workload shape), SLO를 입력하면 세 계층 자동 확장 계획을 설계합니다.

연습문제

  1. 쉬움: code/main.py를 실행하세요. 버스트성 워크로드에서 순진한 듀티 사이클 HPA가 큐 깊이 HPA에 비해 얼마나 많은 요청을 놓칩니까? 차이는 어디에서 생깁니까?
  2. 중간: H100 SXM5에서 Llama 3.3 70B FP8을 서빙하는 클러스터의 Karpenter NodePool을 설계하세요. capacity-type, disruption.consolidationPolicy, consolidateAfter, 그리고 GPU가 아닌 워크로드가 이 노드에 올라오지 못하게 하는 테인트(taint)를 지정하세요.
  3. 중간: 팀이 "GPU는 사용 가능한데 파드가 스케줄되지 않아 Pending에 멈춰 있다"고 보고합니다. 진단해 보세요. 이것은 Karpenter 문제입니까, kube-scheduler 문제입니까, KAI Scheduler 문제입니까? 어떤 지표로 확인할 수 있습니까?
  4. 어려움: 분리형 프리필 파드를 자동 확장할 신호 하나와 디코드 파드를 자동 확장할 다른 신호 하나를 고르세요. 둘 다 정당화하세요.
  5. 어려움: 평균적으로 하루 60회 요청 드롭 이벤트가 발생하고 P99 TTFT가 10초를 넘는 24x7 프로덕션 서비스에서 WhenEmptyOrUnderutilized 통합 함정의 비용을 계산하세요.

핵심 용어

용어흔한 설명실제 의미
Karpenter"노드 프로비저너"1분 미만 프로비저닝을 목표로 하는 Kubernetes 노드 자동 확장기
Cluster Autoscaler"예전 스케일러"더 느리고 그룹 기반인 Kubernetes 노드 자동 확장기 선행 도구
KAI Scheduler"GPU 스케줄러"갱 스케줄링, 토폴로지, 큐를 위한 보조 스케줄러
Gang scheduling"전부 아니면 전무"N개 파드를 원자적으로 스케줄하거나 모두 미루는 방식
Topology awareness"랙 인식"NVLink, InfiniBand, 랙 배치를 기준으로 파드를 배치하는 능력
DCGM_FI_DEV_GPU_UTIL"GPU 사용률"듀티 사이클 지표. LLM 확장 신호로는 부적합함
Queue depth"대기 요청"프리필 병목 확장을 위한 올바른 HPA 신호
KV cache utilization"메모리 압박"디코드 병목 확장을 위한 올바른 HPA 신호
Consolidation"Karpenter 통합"더 저렴한 인스턴스 타입으로 옮기기 위한 노드 종료
WhenEmpty + 1h"안전한 통합"실행 중인 GPU 작업을 축출하지 않는 정책

더 읽을거리

실습 코드

이 강의의 실습 코드 1개

main
Code

산출물

이 강의에서 생성된 프롬프트, 스킬, 코드 산출물 1개

gpu-autoscaler-plan

Design a three-layer GPU autoscaling plan (Karpenter + KAI Scheduler + application signals) for a Kubernetes-based LLM serving cluster. Diagnose DCGM_FI_DEV_GPU_UTIL traps and partial-allocation failures.

Skill

확인 문제

3문제 · 모두 맞추면 완료 표시가 가능합니다

1.Karpenter의 기본 consolidationPolicy: WhenEmptyOrUnderutilized가 GPU 추론 워크로드에 위험한 이유는 무엇인가요?

2.DCGM_FI_DEV_GPU_UTIL을 대체해야 하는 LLM 서빙의 올바른 HPA 신호 두 가지는 무엇인가요?

3.분리형 프리필/디코드(disaggregated prefill/decode) 아키텍처에서 프리필 파드와 디코드 파드에 하나의 HPA를 사용할 수 없는 이유는 무엇인가요?

0/3 답변 완료

추가 문제 풀기

AI가 강의 내용을 바탕으로 새로운 문제를 생성합니다