LabHub
배우기 러닝패스 코스

GPU Operator 와 타임슬라이싱 · GPU 파드가 안 뜬다 — 원인을 순서대로 좁힌다 · 실습

GPU 장애 분류 — 같은 메시지에서 다른 원인을 갈라낸다

LabHub 에서 이어서 보기

목표

GPU 파드가 막히는 일곱 가지 상태를 진짜 스케줄러 위에 만들어 놓고, 오브젝트만 보고 원인을 한 단어로 답하는 분류기를 만듭니다.

왜 중요한가

"GPU 파드가 안 뜬다" 는 신고 하나에 실제 원인은 예닐곱 가지이고, 조사해야 할 자리가 전부 다릅니다. 게다가 자원 미광고·allocatable 0·자리 소진 세 가지는 스케줄러가 완전히 같은 문장을 냅니다. 그래서 메시지를 읽는 것으로는 끝나지 않고, nodeSelector → 테인트 → capacity → allocatable → 남은 자리 순서로 오브젝트를 대조해야 원인이 하나로 좁혀집니다. 순서가 중요한 이유는 앞 단계가 참이면 뒤 단계는 검사할 대상 자체가 없기 때문입니다 — 순서를 어기면 멀쩡한 테인트를 지우는 식으로 클러스터만 망가집니다. 이 판정을 사람이 매번 하면 기준이 흔들리므로, 마지막에 도구로 굳혀 둡니다.

단계

1. 작업 디렉터리 /root/gputri/cases /root/gputri/out /root/gputri/bin 을 만들고 네임스페이스 gpu-triage 를 만드세요. lab-node-0status.capacitystatus.allocatable 양쪽에 nvidia.com/gpu"2" 로 넣고, 테인트 nvidia.com/gpu=present:NoSchedule 을 거세요. /root/gputri/cases/case-ok.yaml 에 파드 case-ok 를 쓰세요 — 네임스페이스 gpu-triage, nodeSelectorkubernetes.io/hostname: lab-node-0, 그 테인트를 견디는 톨러레이션, 컨테이너 이름 cuda, 이미지 nvcr.io/nvidia/cuda:12.4.1-base-ubuntu22.04, limitsnvidia.com/gpu: 1. 적용해 Running 이 되면 /root/gputri/out/01-ok.txt 에 두 줄을 적으세요 — NODE=PHASE=.
2. lab-node-1 은 아무것도 광고하지 않은 채로 둡니다(device plugin 이 죽은 노드입니다). /root/gputri/cases/case-nogpunode.yaml 에 파드 case-nogpunode 를 쓰세요 — nodeSelectorlab-node-1 에 못 박고, 톨러레이션은 1단계와 같게 두고, nvidia.com/gpu: 1 을 요구합니다. 적용한 뒤 Pending 인 것을 확인하고 PodScheduled 조건의 reasonmessage/root/gputri/out/02-nogpunode.txtREASON=MESSAGE= 두 줄로 저장하세요.
3. lab-node-2status.capacitynvidia.com/gpu"4" 로, status.allocatable 에는 "0" 으로 넣으세요(드라이버 검증에 실패해 노드가 GPU 를 내놓지 못하는 상태입니다). /root/gputri/cases/case-alloc0.yaml 에 파드 case-alloc0 을 쓰세요 — lab-node-2 에 못 박고 나머지는 2단계와 같습니다. 적용한 뒤 /root/gputri/out/03-alloc0.txt 에 세 줄을 적으세요 — CAPACITY=, ALLOCATABLE=, MESSAGE=. 앞 단계의 메시지와 견주어 보세요.
4. /root/gputri/cases/case-taint.yaml 에 파드 case-taint 를 쓰세요 — lab-node-0 에 못 박고 nvidia.com/gpu: 1 을 요구하되 톨러레이션은 넣지 않습니다. 나머지는 1단계 파드와 같습니다. 적용한 뒤 /root/gputri/out/04-taint.txt 에 두 줄을 적으세요 — TAINT=nvidia.com/gpu=present:NoScheduleMESSAGE=. 자원은 남아 있는데 왜 막히는지 메시지로 확인하세요.
5. /root/gputri/cases/case-label.yaml 에 파드 case-label 을 쓰세요 — nodeSelectornvidia.com/gpu.product: NVIDIA-A100-SXM4-40GB 로 두고(이 라벨을 가진 노드는 없습니다), 톨러레이션과 nvidia.com/gpu: 1 요청은 그대로 둡니다. 적용한 뒤 /root/gputri/out/05-label.txt 에 두 줄을 적으세요 — MATCHING_NODES= 에는 그 라벨을 실제로 가진 노드 수를, MESSAGE= 에는 조건 메시지를 넣습니다.
6. /root/gputri/cases/case-exhaust.yaml 에 파드 case-exhaust 를 쓰세요 — lab-node-0 에 못 박고 톨러레이션을 넣고 nvidia.com/gpu: 2 를 요구합니다. 그 노드는 2장을 광고하지만 1단계의 case-ok 가 이미 한 장을 쥐고 있습니다. 적용한 뒤 /root/gputri/out/06-exhaust.txt 에 세 줄을 적으세요 — ALLOCATABLE=(그 노드가 광고한 양), ALLOCATED=(그 노드에 배치된 파드들의 GPU 요청 합), REQUESTED=2.
7. 먼저 /root/gputri/cases/case-norequest.yaml 에 파드 case-norequest 를 쓰세요 — lab-node-0 에 못 박고 톨러레이션은 넣되 자원 요청은 아예 넣지 않습니다. 적용하면 뜹니다. 다음으로 /root/gputri/cases/case-rtc.yamlruntimeClassName: nvidia 를 단 파드 case-rtc 를 쓰고 적용해, 표준 오류까지 포함한 출력을 /root/gputri/out/07-runtimeclass.txt 에 저장하세요(RuntimeClass 는 만들지 마세요). 끝으로 네임스페이스 gpu-quota 를 만들고 /root/gputri/cases/quota.yaml 에 ResourceQuota gpu-quota 를 써서 requests.nvidia.com/gpu"1" 로 막은 뒤, /root/gputri/cases/case-quota.yaml 의 파드 case-quota(GPU 3장 요구)를 적용해 출력을 /root/gputri/out/07-quota.txt 에 저장하세요. 마지막으로 /root/gputri/out/07-symptoms.txt 에 세 줄을 적으세요 — NOREQUEST=, RUNTIMECLASS=, QUOTA=. 뒤 두 줄에는 파드 오브젝트가 생겼는지를 created 또는 absent 로 적습니다.
8. /root/gputri/bin/triage.sh 를 만드세요. bash triage.sh <네임스페이스> <파드> 로 부르면 표준 출력에 한 단어만 내고 끝납니다. 답은 일곱 가지입니다 — no-request ok label-mismatch taint no-gpu-node allocatable-zero exhausted. 파드가 없으면 표준 오류에 안내를 내고 1 로 끝냅니다. 판정은 kubectl get -o json 이 준 오브젝트만으로 하고, 순서는 요청 없음 → 이미 배치됨 → nodeSelector → 테인트 → capacity → allocatable → 남은 자리입니다. 만든 뒤 일곱 파드(case-ok case-nogpunode case-alloc0 case-taint case-label case-exhaust case-norequest)에 모두 물려 /root/gputri/out/triage.txt<파드이름> <원인> 일곱 줄을 적으세요.

참고

단계 8개

  1. 정상인 GPU 노드 한 대를 세운다
  2. 자원 이름 자체가 없는 노드
  3. capacity 는 있는데 내줄 수 없는 노드
  4. 톨러레이션만 빠진 파드
  5. 후보 노드가 아예 없는 파드
  6. 광고도 멀쩡한데 자리가 없다
  7. 파드가 아예 만들어지지 않는 두 가지
  8. 오브젝트만 보고 원인을 한 단어로 답하는 분류기