kubeflow_trainer_with_volcano/README.md

361 lines
13 KiB
Markdown

# Volcano + Kubeflow Trainer 설치 매뉴얼
멀티노드 GPU 분산 학습을 위한 Volcano Scheduler와 Kubeflow Trainer v2 설치 가이드.
## 환경 정보
| 항목 | 값 |
|------|-----|
| Kubernetes | v1.34.3 |
| Helm | v4.0.4 |
| GPU 노드 | InfiniBand 연결 GPU 노드 3대 (노드당 GPU 8장, IB NIC 2개) |
| GPU 이미지 | nvcr.io/nvidia/pytorch:24.10-py3 |
| Volcano | v1.14.0 |
| Kubeflow Trainer | sha-48e7a93 |
| JobSet (의존성) | v0.10.1 |
## 디렉토리 구조
```
kubeflow_trainer_with_volcano/
├── .env # 환경변수 (git 제외)
├── .gitignore
├── README.md # 이 문서
├── charts/
│ ├── volcano/
│ │ └── volcano-1.14.0.tgz # Volcano Helm chart
│ └── kubeflow-trainer-0.0.0-sha-48e7a93.tgz # Kubeflow Trainer Helm chart
├── manifests/
│ └── kubeflow-trainer/
│ └── runtimes/
│ └── runtimes.yaml # ClusterTrainingRuntime manifests
└── configs/
├── volcano-values.yaml # Volcano 커스텀 values
├── kubeflow-trainer-values.yaml # Kubeflow Trainer 커스텀 values
└── volcano-trainjob-integration.yaml # Volcano-Trainer 연동 설정 샘플
```
## 사전 요구사항
- Kubernetes 클러스터 (v1.26+)
- Helm v3 이상
- `kubectl` 클러스터 접근 설정 완료
- GPU 노드에 NVIDIA device plugin 설치 완료
- InfiniBand 네트워크 구성 완료
- 클러스터에 기존 Volcano/Kubeflow CRD가 없는 상태
- 컨트롤 플레인 컴포넌트 배치용 노드에 `nodegroup: nd` 라벨 설정 완료
- 테스트용 CIFAR-10 데이터셋을 **모든 GPU 노드**의 `/home/ubuntu/cifar-10-batches-py`에 사전 배치 (hostPath로 마운트)
```bash
# 사전 확인
kubectl version
helm version
kubectl get nodes
kubectl get nodes -l nodegroup=nd # 컨트롤 컴포넌트 배치 노드 확인
nvidia-smi # GPU 노드에서 확인
ibstat # InfiniBand 상태 확인
```
---
## Task 2: Volcano 설치
Volcano는 Kubernetes를 위한 배치 스케줄링 시스템으로, gang scheduling을 통해 분산 학습 Pod들이 동시에 스케줄링되도록 보장합니다.
### 2.1 네임스페이스 생성
```bash
kubectl create namespace volcano-system
```
### 2.2 Helm으로 Volcano 설치 (로컬 chart 사용)
```bash
helm install volcano charts/volcano/volcano-1.14.0.tgz \
-n volcano-system \
-f configs/volcano-values.yaml \
--wait --timeout 5m
```
주요 커스텀 설정 (`configs/volcano-values.yaml`):
- **scheduler_config_override**: gang scheduling + binpack (GPU 노드 집약 배치) 활성화
- **default_ns**: `nodegroup: nd` — Volcano 컴포넌트를 non-GPU 노드에 배치
- **API rate limits**: 대규모 클러스터용 QPS/Burst 설정
### 2.3 설치 확인
```bash
# Pod 상태 확인 (모두 nodegroup=nd 노드에 배치되어야 함)
kubectl get pods -n volcano-system -o wide
# CRD 확인
kubectl get crd | grep volcano
```
### 2.4 Volcano 삭제 (필요시)
```bash
helm uninstall volcano -n volcano-system
kubectl delete namespace volcano-system
```
---
## Task 3: Kubeflow Trainer 설치
Kubeflow Trainer v2는 TrainJob CRD를 통해 분산 학습 워크로드를 관리합니다.
### 3.1 네임스페이스 생성
```bash
kubectl create namespace kubeflow-trainer
```
### 3.2 Helm으로 Kubeflow Trainer 설치 (로컬 chart 사용)
```bash
helm install kubeflow-trainer charts/kubeflow-trainer-0.0.0-sha-48e7a93.tgz \
-n kubeflow-trainer \
-f configs/kubeflow-trainer-values.yaml \
--wait --timeout 5m
```
주요 커스텀 설정 (`configs/kubeflow-trainer-values.yaml`):
- **manager.nodeSelector**: `nodegroup: nd` — Trainer controller를 non-GPU 노드에 배치
- **jobset.controller.nodeSelector**: `nodegroup: nd` — JobSet controller를 non-GPU 노드에 배치
- **jobset.install**: `true` — JobSet을 함께 설치 (이미 설치되어 있으면 `false`로 변경)
### 3.3 ClusterTrainingRuntime 설치
```bash
kubectl apply -f manifests/kubeflow-trainer/runtimes/runtimes.yaml
```
> **참고**: JAX runtime은 현재 CRD에서 `spec.mlPolicy.jax` 필드를 지원하지 않아 주석 처리되어 있음.
> 설치되는 Runtime: deepspeed-distributed, mlx-distributed, torch-distributed, torchtune-llama3.2-1b/3b, torchtune-qwen2.5-1.5b
### 3.4 설치 확인
```bash
# Trainer, JobSet controller 확인 (nodegroup=nd 노드에 배치되어야 함)
kubectl get pods -n kubeflow-trainer -o wide
# CRD 확인
kubectl get crd | grep trainer
# ClusterTrainingRuntime 확인
kubectl get clustertrainingruntimes
```
### 3.5 Kubeflow Trainer 삭제 (필요시)
```bash
kubectl delete -f manifests/kubeflow-trainer/runtimes/runtimes.yaml
helm uninstall kubeflow-trainer -n kubeflow-trainer
kubectl delete namespace kubeflow-trainer
```
---
## Task 4: Volcano ↔ Kubeflow Trainer 연동 설정
Volcano 스케줄러를 Kubeflow TrainJob과 연동하여 gang scheduling, queue 기반 리소스 관리, topology-aware scheduling을 활성화합니다.
> Reference: https://www.kubeflow.org/docs/components/trainer/gang-scheduling/volcano/
### 4.1 연동 리소스 개요
`configs/volcano-trainjob-integration.yaml`에 아래 3개 리소스가 정의되어 있습니다.
#### Queue — 리소스 풀
학습 워크로드가 사용할 수 있는 총 리소스 상한을 정의합니다. 한 번 생성하면 모든 TrainJob이 공유합니다.
| 옵션 | 설명 |
|------|------|
| `weight` | 여러 Queue 간 리소스 배분 비율 (Queue 1개면 무의미) |
| `reclaimable` | 유휴 리소스를 다른 Queue에 빌려줄 수 있는지 |
| `capability` | 이 Queue의 최대 리소스 (클러스터 실제 용량에 맞게 조정) |
#### ClusterTrainingRuntime — 학습 환경 템플릿
학습 Pod의 기본 설정을 정의합니다. 한 번 생성하면 여러 TrainJob이 재사용합니다.
| 옵션 | 설명 |
|------|------|
| `mlPolicy.torch.numProcPerNode` | 노드당 프로세스 수 (기본값, TrainJob에서 override 가능) |
| `mlPolicy.numNodes` | 노드 수 (기본값, TrainJob에서 override 가능) |
| `podGroupPolicy.volcano` | Volcano gang scheduling 활성화. PodGroup 자동 생성 |
| `podGroupPolicy.volcano.networkTopology` | topology-aware scheduling (InfiniBand 통신 최적화) |
| `template.metadata.annotations` | Queue 지정 등. TrainJob level에서 override 가능 |
| `resources.requests/limits` | 노드당 GPU 기본 할당량 (TrainJob에서 override 가능) |
현재 Runtime에 포함된 InfiniBand/NCCL 설정:
| 설정 | 값 | 설명 |
|------|-----|------|
| `k8s.v1.cni.cncf.io/networks` | `hostdevice-net` | InfiniBand CNI 네트워크 연결 |
| `nvidia.com/gpu` | `8` | 노드당 GPU 8장 |
| `nvidia.com/hostdev` | `2` | 노드당 IB NIC 2개 |
| `privileged` + `IPC_LOCK` | - | NCCL IB 통신에 필요한 권한 |
| `NCCL_IB_DISABLE` | `0` | InfiniBand 사용 |
| `NCCL_DEBUG_SUBSYS` | `INIT,NET,IB` | NCCL 디버그 서브시스템 |
| `NCCL_SOCKET_IFNAME` | `net` | NCCL 소켓 인터페이스 |
| `/dev/shm` | `128Gi` | NCCL 공유 메모리 (GPU 8장 기준) |
| `cifar-data` | hostPath | `/home/ubuntu/cifar-10-batches-py` 데이터셋 마운트 |
> MASTER_ADDR / MASTER_PORT는 Kubeflow Trainer torch runtime이 torchrun rdzv로 자동 설정하므로 별도 지정 불필요.
#### TrainJob — 학습 작업 제출
실제 학습을 실행할 때마다 생성합니다. Runtime의 기본값을 상속받고, 필요한 부분만 override합니다.
| 옵션 | 설명 |
|------|------|
| `runtimeRef.name` | 사용할 ClusterTrainingRuntime 이름 |
| `trainer.image` | 학습 컨테이너 이미지 |
| `trainer.command` | 학습 스크립트 실행 명령 (torchrun 사용 — 아래 주의사항 참고) |
| `trainer.numNodes` | 학습에 사용할 노드 수 (Runtime 기본값 override) |
| `trainer.numProcPerNode` | 노드당 프로세스 수 (`"auto"`면 GPU 수만큼 자동) |
| `trainer.resourcesPerNode` | 노드당 리소스 (Runtime 기본값 override) |
> 현재 기본 설정은 `numNodes: 2` (2노드 멀티노드 분산학습). 단일노드 테스트 시 TrainJob에서 `numNodes: 1`로 override 가능.
### 4.2 연동 설정 적용
```bash
kubectl apply -f configs/volcano-trainjob-integration.yaml
```
### 4.3 연동 확인
```bash
# Queue 확인
kubectl get queue training-queue
# ClusterTrainingRuntime 확인
kubectl get clustertrainingruntimes torch-distributed-volcano
# 테스트 TrainJob 상태 확인
kubectl get trainjob
# PodGroup 자동 생성 확인
kubectl get podgroup
# Pod 스케줄러 확인 (schedulerName이 volcano인지)
kubectl get pods -l trainer.kubeflow.org/trainjob-name=<trainjob-name> \
-o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.schedulerName}{"\n"}{end}'
```
---
## 컴포넌트 배치 요약
모든 컨트롤 플레인 컴포넌트는 `nodegroup: nd` 노드에 배치됩니다. GPU 노드에는 학습 Pod만 배치됩니다.
| 컴포넌트 | 네임스페이스 | 배치 노드 | GPU 필요 |
|----------|-------------|-----------|----------|
| Volcano admission | volcano-system | nodegroup: nd | X |
| Volcano controller | volcano-system | nodegroup: nd | X |
| Volcano scheduler | volcano-system | nodegroup: nd | X |
| Trainer controller | kubeflow-trainer | nodegroup: nd | X |
| JobSet controller | kubeflow-trainer | nodegroup: nd | X |
| TrainJob 학습 Pod | default (사용자 지정) | GPU 노드 (InfiniBand) | O |
---
## 검증 체크리스트
- [x] Volcano Pod 3개 Running (`nodegroup=nd` 노드에 배치 확인)
- [x] Volcano CRD 생성됨 (jobs, podgroups, queues 등)
- [x] Kubeflow Trainer controller Running (`nodegroup=nd` 노드에 배치 확인)
- [x] JobSet controller Running (`nodegroup=nd` 노드에 배치 확인)
- [x] Kubeflow Trainer CRD 생성됨 (trainjobs, trainingruntimes 등)
- [x] ClusterTrainingRuntime 목록 확인 (deepspeed-distributed, torch-distributed 등 6개)
- [x] Training Queue 생성됨
- [x] 테스트 TrainJob 제출 시 PodGroup 자동 생성 확인 (minMember=2, Running)
- [x] 테스트 TrainJob Pod가 서로 다른 GPU 노드에 배치됨
- [x] 2노드 16GPU 분산학습 정상 동작 확인 (VGG11 + CIFAR10 + NCCL)
---
## 주의사항
### torchrun 사용 및 Runtime/TrainJob command 분리
Kubeflow Trainer torch runtime은 Runtime에 `command`가 없을 때 `PET_*` 환경변수(NNODES, NPROC_PER_NODE, MASTER_ADDR, MASTER_PORT, NODE_RANK)를 자동 주입합니다. 이를 위해 replicatedJob에 `trainer.kubeflow.org/trainjob-ancestor-step: trainer` 라벨이 필수입니다.
학습 스크립트 실행 구조:
- **Runtime**: `command` 없음 — Trainer controller가 `PET_*` 환경변수를 주입
- **TrainJob**: `trainer.command``torchrun`으로 스크립트 지정 — torchrun이 `PET_*` 환경변수를 읽어 분산 학습 설정
```yaml
# TrainJob 예시
spec:
trainer:
command:
- torchrun
- /workspace/scripts/train_nccl.py
```
> `python`으로 직접 실행하면 `PET_*` 환경변수가 무시되어 `RANK`, `WORLD_SIZE` 등이 설정되지 않습니다.
### JAX ClusterTrainingRuntime 미지원
현재 CRD 버전에서 `spec.mlPolicy.jax` 필드를 지원하지 않아 JAX runtime은 주석 처리되어 있음.
---
## 트러블슈팅
### Volcano 관련
**Volcano admission webhook 타임아웃**
```bash
kubectl get secret volcano-admission-secret -n volcano-system
kubectl logs -n volcano-system -l app=volcano-admission
```
**Pod가 Pending 상태로 유지**
```bash
# PodGroup 상태 확인 - minMember 충족 여부
kubectl describe podgroup <podgroup-name>
# Queue 리소스 capacity 확인
kubectl get queue training-queue -o yaml
# Volcano scheduler 로그 확인
kubectl logs -n volcano-system -l app=volcano-scheduler
```
### Kubeflow Trainer 관련
**TrainJob이 생성되지 않음**
```bash
kubectl logs -n kubeflow-trainer -l app.kubernetes.io/name=kubeflow-trainer
kubectl describe trainjob <trainjob-name>
```
**ClusterTrainingRuntime을 찾을 수 없음**
```bash
kubectl get clustertrainingruntimes
kubectl apply -f manifests/kubeflow-trainer/runtimes/runtimes.yaml # 재설치
```
### 연동 관련
**PodGroup이 자동 생성되지 않음**
- ClusterTrainingRuntime에 `podGroupPolicy.volcano: {}` 가 설정되어 있는지 확인
- TrainJob이 올바른 runtimeRef(`torch-distributed-volcano`)를 참조하는지 확인
**TrainJob Pod가 default-scheduler로 스케줄링됨**
- `podGroupPolicy.volcano`가 runtime에 설정되어 있는지 확인
- Volcano가 정상 동작 중인지 확인: `kubectl get pods -n volcano-system`
### 로그 수집
```bash
kubectl logs -n volcano-system -l app=volcano-scheduler --tail=100
kubectl logs -n volcano-system -l app=volcano-controller --tail=100
kubectl logs -n volcano-system -l app=volcano-admission --tail=100
kubectl logs -n kubeflow-trainer -l app.kubernetes.io/name=kubeflow-trainer --tail=100
```