--- title: K8s GPU 스케줄링 완전판 — 하드웨어부터 스케줄러까지 date: 2026-07-15 type: note domain: k8s tags: [kubernetes, gpu, scheduling, device-plugin, dra, gang-scheduling, nvlink, pcie, nccl] --- > [!note] 원본은 인터랙티브 HTML > 이 글의 본체는 인터랙티브 문서다. 스테퍼·시뮬레이터 7종(DMA 전송, island 쌍 선택, device plugin 흐름, DRA 할당, gang 데드락 시뮬레이터 등)이 포함되어 있다. > > **[→ 전문 보기 (interactive.html)](files/interactive.html)** > > 2026-06 학습 세션 종합. 원 대화 대비 정밀화·정정 5건 반영(원문 부록 A). 이 페이지는 핵심 요약본. ## 한 문단 요약 K8s의 모든 협업은 API server 오브젝트를 경유한다. GPU는 커널 표준 인터페이스가 없어 device plugin이 벤더 대리인으로 정수 카운터(`nvidia.com/gpu: 8`)를 채우는데, 카운터에는 속성이 없고 디바이스 선택이 kubelet 단계로 밀린다. 한편 GPU 간 통신 속도는 "쌍 사이에 어떤 회선이 물리적으로 존재하는가"로 결정되고(같은 island = NVLink, 밖 = PCIe, 노드 밖 = 네트워크), 집합 통신은 가장 느린 쌍에 묶이므로 성능 요구사항은 "GPU N장"이 아니라 "같은 island의 N장"이 된다. DRA가 속성 게시(ResourceSlice) + CEL 필터 + `matchAttribute`로 이것을 선언 가능하게 만들고, 노드·디바이스 결정을 스케줄러 한 곳으로 합친다. 분산 학습은 여기에 Pod N개의 원자성을 추가한다 — all-reduce barrier 때문에 부분 배치는 점유 100%·진행 0이고, gang scheduling(Kueue의 all-or-nothing admission)이 그 교착을 원천 차단한다. ## 구성 | 장 | 주제 | 핵심 | |---|---|---| | 1 | K8s 상태 흐름 | 허브-스포크, capacity/allocatable, 장부 계산(실측 아님) | | 2 | 컴퓨터 구조 | CPU 패키지 = 코어+메모리 컨트롤러+root complex, PCIe 점대점 트리, DMA | | 3 | NVLink | 브리지 vs SXM+NVSwitch, 대역폭 절벽, island | | 4 | Device plugin | 정수 카운터 모델과 구조적 한계 3가지 | | 5 | DRA | ResourceSlice·ResourceClaim·CEL·matchAttribute, 결정권의 스케줄러 이동 | | 6 | Gang scheduling | all-reduce barrier, Coffman 데드락 동형, Kueue suspend/resume | | 7 | 2×3090 실습 | 호환성 체크 → topo -m → P2P 검증 → NCCL 대조 실험 → DDP 벤치마크 | ## 장별 핵심 압축 ### 1. K8s 상태 흐름 - K8s 협업 = API server 오브젝트의 읽기/쓰기/watch. 직접 통신은 노드 로컬(kubelet↔plugin·런타임)뿐. - kubelet은 실물 발견(capacity/allocatable), 스케줄러는 장부 계산(allocatable − Σrequests) — 실측 아님. - GPU는 커널 표준 인터페이스가 없어 kubelet이 스스로 발견 불가 → 벤더 위임 확장점(device plugin)이 필요. ### 2. 컴퓨터 구조 (PCIe · DMA) - CPU 패키지 = 코어 + 메모리 컨트롤러 + root complex. PCIe는 root complex를 뿌리로 한 점대점 트리(공유 버스 아님). - RAM→VRAM 전송은 CPU 실리콘을 *지나가지만*, 복사 노동은 GPU의 DMA 엔진(copy engine)이 한다 — 코어는 지시서 작성과 완료 통보에만 등장. - pinned memory(`pin_memory=True`) = 스테이징 복사 제거. DMA의 본질 = MMIO 공유 주소 공간 위의 load/store. 확장하면 GPUDirect Storage/RDMA. ### 3. NVLink와 island - GPU 다이는 PCIe PHY와 NVLink PHY를 모두 내장 — NVLink는 메인보드 미경유 별도 회선(브리지 = 끼움 PCB, SXM = 보드 인쇄 배선 + NVSwitch). - 대역폭은 **쌍의 속성**: 같은 island = NVLink 회선 존재, 밖 = PCIe가 유일한 길, 노드 밖 = 네트워크가 유일한 길. - 집합 통신은 가장 느린 쌍에 묶인다 → "같은 island의 N장"이 성능 요구사항이 되는 물리적 근거. - 기준 통일 시 A100 NVLink(양방향 ~600GB/s)는 PCIe Gen4 x16(양방향 ~64GB/s)의 약 9–10배. ### 4. Device plugin의 한계 - Extended resource = 속성 없는 정수 카운터. 스케줄러에게 GPU는 의미를 모르는 숫자. - 결정이 두 단계로 분리: 노드(스케줄러) → 디바이스(kubelet, Pod 도착 후). 전체를 보는 주체 없음. - 한계 셋 — ① 속성 표현 불가(자원 이름 폭발) ② 토폴로지 무지(같은 매니페스트가 실행마다 다른 성능) ③ 정수 전부-아니면-전무(MIG·time-slicing은 땜질). ### 5. DRA (K8s 1.34 GA) - DRA = PV/PVC 패턴의 디바이스 적용: ResourceSlice(인벤토리+속성) / ResourceClaim(조건 요청) / 선택 결정의 스케줄러 이동. - CEL은 속성 정의가 아니라 디바이스별 boolean 필터(SQL의 WHERE 절). 디바이스 *간* 관계(같은 NVLink 도메인)는 CEL 밖 — `constraints.matchAttribute`의 영역. - 노드+디바이스 동시 결정이 토폴로지 인지 스케줄링의 구조적 전제. 남은 숙제 = 노드 간 정렬(rail-optimized 배치, 멀티-드라이버 교차 제약). ### 6. Gang scheduling - all-reduce는 전원 barrier — 부분 배치는 "점유 100% · 진행 0"의 무의미 상태. N개 Pod 배치에 트랜잭션급 원자성 필요. - 기본 스케줄러는 Pod 단위 greedy(Job 경계 무지) → 두 Job 인터리브 → Coffman 4조건 충족 = 데드락 동형. - gang = all-or-nothing admission. Kueue는 suspend/resume 게이트로 kube-scheduler와 협업 — 교착만 막고, 순서 결정(우선순위·quota·선점)은 다음 층. ### 7. 2×RTX 3090 실습 방법론 - 구매 게이트는 슬롯 간격: CPU 직결 x8/x8 두 슬롯 + 브리지 pitch 일치. 보드 확인이 카드 구매보다 먼저. - 검증 사다리: `nvidia-smi topo -m`의 NV4 → p2pBandwidthLatencyTest ~50GB/s → nccl-tests "via NVL". - 진짜 실험은 `NCCL_P2P_DISABLE=1` 대조 — island 절벽을 자기 하드웨어에서 수치로 재현. 브리지가 사주는 것은 속도가 아니라 **대조군**이다. - 전체 절차(호환성 체크리스트·DDP 벤치마크 스크립트·문제 해결 표·실험 기록 템플릿)는 [인터랙티브 전문](files/interactive.html#ch7) 7장. ## 검토 노트 (원 대화 대비 정정 5건) | # | 내용 | 위치 | |---|---|---| | ① | 대역폭 비교 기준 통일: NVLink 수치는 양방향 합산, PCIe는 단방향 — 같은 기준으로 약 9–10배 | 3.4 | | ② | NVSwitch 기반 현대 8-GPU 서버는 노드 전체가 단일 island. "노드 안 복수 island"는 브리지 페어·구형 토폴로지의 경우 | 3.5 | | ③ | "3090이 마지막 NVLink"는 GeForce 라인 기준 — 워크스테이션은 Ampere 세대까지 유지 | 3.6 | | ④ | device plugin의 디바이스 선택 주체는 kubelet device manager(plugin은 GetPreferredAllocation 힌트) | 4장 | | ⑤ | 실습 수치는 전형값(환경 의존). 목표 측정치는 절대값이 아니라 NVLink/차단 비율 | 7.7 | ## 다음 학습 — Kueue admission - ClusterQueue · LocalQueue · cohort는 quota를 어떤 구조로 나누는가? - preemption은 "비선점" 조건을 의도적으로 깨는 행위 — 언제, 무엇을 근거로 정당화되는가? - suspend/resume 게이트가 kube-scheduler를 대체하지 않는 이유 — 입장 결정과 배치 결정의 분리. - borrowing/reclaim은 gang의 원자성과 어떻게 공존하는가?