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

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

하나가 죽으면 모두 다시

TT Lab 에서 이어서 보기

한 줄 요약

분산 학습 하나는 파드 여러 개가 「한 몸」처럼 움직여야 하는 일입니다. 서로의 주소를 알아야 하고, 하나가 죽으면 모두 다시 시작해야 하고, 누가 끝나면 전체가 끝난 것인지 정해야 합니다. Job 은 이 셋을 모릅니다. JobSet 은 역할이 다른 Job 여러 개를 하나의 객체로 묶고, 그 셋을 선언으로 적게 해 줍니다.

왜 이게 필요했나

PyTorch 분산 학습을 Job 하나로 띄우려 해 보면 바로 막힙니다. 랭크 0 이 마스터 주소를 열고 나머지가 거기 붙어야 하는데, Job 의 파드 이름은 무작위 접미사가 붙어 미리 알 수 없습니다. 인덱스 Job(completionMode: Indexed)이 이름 문제를 풀어 주었지만, 「매개 서버 둘과 워커 여덟」 처럼 역할이 다른 파드 묶음은 여전히 Job 여러 개로 나눠 띄우고 손으로 엮어야 했습니다. 워커 하나가 GPU 오류로 죽으면 나머지 일곱은 멈춘 랭크를 기다리며 GPU 를 붙잡고 있습니다. 누군가 전체를 내렸다 다시 올려야 합니다.

Kubeflow 의 PyTorchJob·MPIJob 이 각자 이 문제를 풀어 왔고, 프레임워크마다 비슷한 코드가 반복됐습니다. JobSet 은 그 공통 부분을 쿠버네티스 SIG 의 API 하나로 뽑아낸 것입니다. Kubeflow Trainer v2 의 TrainJob 이 내부에서 JobSet 을 만들어 쓰는 이유가 그것입니다.

어떻게 동작하나

replicatedJobs        역할마다 Job 템플릿과 그 Job 을 몇 벌 만들지(replicas)
network               기본으로 JobSet 이름의 헤드리스 서비스를 만들고 파드에 hostname·subdomain 을 준다
                      → <jobset>-<역할>-<job번호>-<파드번호>.<jobset> 으로 서로를 찾는다
failurePolicy         maxRestarts 만큼, Job 하나가 실패하면 JobSet 전체를 다시 만든다(restart-attempt 라벨이 오른다)
successPolicy         operator All|Any 와 targetReplicatedJobs: 누가 끝나면 전체가 끝난 것인지
startupPolicy         InOrder 면 앞 역할이 Ready 가 된 뒤에 다음 역할을 띄운다

실험 VM(JobSet v0.13.0, 컨트롤러 이미지 36MB, 준비 17초)에서 확인한 것입니다.

현장에서 만나는 모습

English corner

A JobSet restarts as a whole; that is the point.

replicated job, failure policy, success policy 는 JobSet 문서의 목차 그대로입니다.

다음 실습에서 할 것

리더 하나와 워커 둘로 된 JobSet 을 띄워 서로의 이름을 확인하고, 워커를 일부러 실패시켜 전체 재시작을 보고, 리더만 끝나면 끝나는 평가 JobSet 을 만듭니다. 그다음 Kueue 큐에 넣어 한 덩어리로 입장하는 것과, 쿼터를 넘으면 한 파드도 뜨지 않는 것을 봅니다.