TT Lab
블로그 시작하기
배우기 러닝패스 코스

쿠버네티스 GPU 스케줄링과 AI 배치

거절 대신 줄을 세운다

TT Lab 에서 이어서 보기

한 줄 요약

Kueue 는 파드를 배치하지 않습니다. Job 을 「멈춘(suspend) 채로 붙잡아 두었다가」, 큐의 쿼터가 허락하는 순간 풀어 줍니다. 이 「풀어 줌」 을 입장(admission)이라 부르고, 입장한 뒤의 배치는 여전히 기본 kube-scheduler 가 합니다. 입장과 배치를 나눈 것이 Kueue 설계의 전부라고 해도 과장이 아닙니다.

왜 이게 필요했나

쿠버네티스에도 쿼터가 있습니다. ResourceQuota 는 네임스페이스가 쓸 수 있는 양을 넘는 「생성을 거절」합니다. 웹 서비스에는 이것이 맞습니다. 한도를 넘는 배포는 실수일 가능성이 크고, 바로 실패해야 고칩니다.

배치 작업은 다릅니다. GPU 4장짜리 학습을 밤 열한 시에 제출했는데 팀 쿼터가 지금 꽉 찼다고 거절당하면, 사람은 다음 날 아침에야 알게 됩니다. 원하는 것은 거절이 아니라 「줄 서기」입니다. 지금은 못 들어가도 앞 작업이 끝나면 자동으로 들어가야 합니다. 여기에 팀끼리 남는 쿼터를 빌려 주기, 우선순위, 여러 파드를 한꺼번에 입장시키기가 더해지면 ResourceQuota 로는 표현할 수 없습니다. HPC 의 Slurm 이 오래 해 온 일이고, 이 플랫폼의 HPC 와 Slurm 코스에서 본 그 큐를 쿠버네티스 방식으로 다시 만든 것이 Kueue 입니다.

어떻게 동작하나

객체 다섯 개를 기억하면 됩니다.

ResourceFlavor  자원의 「맛」. 노드 라벨·테인트·톨러레이션을 담아, 입장할 때 파드에 붙여 준다
ClusterQueue    쿼터의 주인. 플레이버마다 자원별 nominalQuota, 같은 cohort 끼리 빌려 쓰기 규칙
LocalQueue      네임스페이스 안의 창구. 어느 ClusterQueue 로 갈지만 적는다
Workload        Kueue 가 Job 마다 만드는 내부 객체. 파드 묶음(podSets)과 필요한 자원의 합
WorkloadPriorityClass  입장 순서와 선점에 쓰는 우선순위(파드의 PriorityClass 와 따로)

흐름은 이렇습니다.

Job 생성(라벨 kueue.x-k8s.io/queue-name: lq)
  → 웹훅이 spec.suspend=true 로 바꾼다       파드가 하나도 생기지 않는다
  → Workload 생성, LocalQueue → ClusterQueue 의 줄에 선다
  → 쿼터가 되면 입장: 플레이버의 노드 라벨을 파드 템플릿에 넣고 suspend=false
  → 이제 Job 컨트롤러가 파드를 만들고 kube-scheduler 가 노드를 고른다

실험 VM 에서 잰 값입니다(Kueue v0.20.3, 컨트롤러 메모리 60Mi, 설치부터 준비까지 16초). 그리고 API 판이 바뀌었다는 것을 꼭 기억해 두세요. 이 판의 CRD 는 kueue.x-k8s.io/v1beta2 만 내주고 v1beta1 은 더 이상 받지 않습니다. 인터넷의 예제 다수가 아직 v1beta1 이라 그대로 붙이면 no matches for kind 로 실패합니다.

현장에서 만나는 모습

English corner

Kueue decides when a job may start; the scheduler decides where its pods run.

admission(입장), suspend(일시 정지), nominal quota(명목 쿼터)는 Kueue 문서의 기본 어휘입니다.

다음 실습에서 할 것

ResourceFlavor·ClusterQueue·LocalQueue 를 직접 세우고, GPU 1장짜리 Job 셋을 넣어 둘은 입장하고 하나는 줄 서는 것을 봅니다. 라벨 없는 Job 이 쿼터를 우회하는 것을 확인하고, ClusterQueue 의 장부를 읽은 뒤, 앞 작업을 지워 줄이 저절로 줄어드는 것을 봅니다.