GPU Operator 와 타임슬라이싱 · GPU 는 무엇으로 보나 · 실습
GPU 지표 — 노출 형식을 만들고 파싱하고 경보로 잇는다
목표
DCGM Exporter 의 노출 형식을 직접 쓰고, 파싱해 카드별 표로 바꾸고, 할당률과 사용률을 나란히 놓고, 경보 규칙과 수집 대상 오브젝트까지 만듭니다.
왜 중요한가
GPU 는 조직에서 가장 비싼 자원인데 쿠버네티스는 그 사용률을 모릅니다. 아는 것은 '이 파드에 한 장을 배정했다' 뿐입니다. 그래서 스케줄러 눈에는 꽉 찬 클러스터가 전기 요금 관점에서는 거의 놀고 있는 상태가 몇 달씩 갑니다. 이 격차를 숫자로 만들려면 쿠버네티스 API 의 할당량과 DCGM 의 사용률을 같은 화면에 올려야 하고, 그러려면 먼저 지표의 실제 모양을 알아야 합니다. 지표에서 중요한 것은 값이 아니라 라벨입니다 — 라벨이 지표를 카드와 노드와 파드에 잇고, 그 이음이 끊긴 자리에서 '임자 없이 메모리를 쥔 카드' 같은 장애가 드러납니다.
단계
1. /root/gpumet/metrics /root/gpumet/bin /root/gpumet/out /root/gpumet/rules /root/gpumet/k8s 를 만들고 /root/gpumet/metrics/dcgm.prom 에 A100 4장이 꽂힌 노드의 /metrics 출력을 쓰세요. 지표는 다섯 가지입니다 — DCGM_FI_DEV_GPU_UTIL DCGM_FI_DEV_FB_USED DCGM_FI_DEV_FB_FREE DCGM_FI_DEV_GPU_TEMP DCGM_FI_DEV_XID_ERRORS. 지표마다 # HELP 한 줄과 # TYPE <이름> gauge 한 줄을 앞에 두고, 카드 네 장에 대한 샘플을 이어 적습니다. 샘플의 라벨은 네 가지입니다 — gpu(0부터 3), UUID(GPU-a1b2c3d4-0000-0000-0000-00000000000<번호>), device(nvidia<번호>), Hostname(lab-node-0). 값은 gpu 0 은 사용률 97 · FB_USED 38000 · FB_FREE 2760 · 온도 71 · XID 0, gpu 1 은 2 · 9000 · 31760 · 41 · 2, gpu 2 는 0 · 0 · 40760 · 33 · 0, gpu 3 은 1 · 21000 · 19760 · 40 · 0 입니다.
2. /root/gpumet/bin/parse-metrics.sh <노출파일> 을 만드세요. 카드 하나마다 한 줄씩 <gpu> <util> <fb_used> <fb_total> <mem_pct> 다섯 칸을 빈칸으로 나눠 출력합니다. fb_total 은 FB_USED 와 FB_FREE 의 합이고, mem_pct 는 fb_used * 100 / fb_total 의 버림 정수입니다. 줄은 gpu 번호 오름차순이어야 하고, 인자로 받은 파일만 읽어야 합니다(경로를 안에 박아 두지 마세요). 만든 뒤 1단계 파일에 물려 출력을 /root/gpumet/out/per-gpu.txt 에 저장하세요.
3. /root/gpumet/metrics/dcgm-k8s.prom 에 쿠버네티스 매핑을 켠 판을 쓰세요 — 1단계와 같은 다섯 지표·네 카드에 gpu 0 과 gpu 3 에만 라벨 세 개를 더합니다(namespace="gpu-metrics", gpu 0 은 pod="train-a" 와 container="trainer", gpu 3 은 pod="infer-b" 와 container="server"). gpu 1 과 gpu 2 에는 파드 라벨이 없습니다. 그리고 /root/gpumet/bin/find-orphan.sh <노출파일> 을 만드세요 — 파드 라벨이 없는데 FB_USED 가 1024 를 넘는 카드의 gpu 번호를 오름차순으로 한 줄에 하나씩 냅니다. 1단계가 아니라 이 새 파일에 물려 출력을 /root/gpumet/out/orphan.txt 에 저장하세요.
4. lab-node-0 의 status.capacity 와 status.allocatable 양쪽에 nvidia.com/gpu 를 "4" 로 넣고, 네임스페이스 gpu-metrics 를 만든 뒤 /root/gpumet/k8s/workloads.yaml 에 파드 셋(train-a infer-b idle-c)을 쓰세요 — 모두 lab-node-0 에 못 박고 각각 nvidia.com/gpu: 1 을 요구합니다. 적용해 셋 다 뜨면 /root/gpumet/out/gap.txt 에 다섯 줄을 적으세요 — PHYSICAL=(노드가 광고한 장수), ALLOCATED=(파드들이 요구해 나간 장수), ALLOC_PCT=(둘의 비율, 버림 정수), MEAN_UTIL=(3단계 노출 파일의 네 카드 평균 사용률, 버림 정수), IDLE_BUT_ALLOCATED=(파드 라벨이 붙었는데 사용률이 10 미만인 카드 수).
5. /root/gpumet/rules/gpu-alerts.yaml 에 프로메테우스 규칙 파일을 쓰세요. 최상위에 groups 가 있고 그룹 하나의 name 은 gpu, 그 안에 규칙 정확히 세 개입니다 — GpuXidError(DCGM_FI_DEV_XID_ERRORS 를 쓰는 식, for: 0m, severity: critical), GpuTempHigh(DCGM_FI_DEV_GPU_TEMP 를 쓰는 식, for: 10m, severity: warning), GpuAllocatedButIdle(DCGM_FI_DEV_GPU_UTIL 을 쓰는 식, for: 2h, severity: info). 규칙마다 alert expr for labels.severity annotations.summary 다섯 가지를 모두 갖추세요. summary 는 '무엇을 해야 하는가' 가 담긴 한 문장으로 씁니다.
6. /root/gpumet/bin/check-rules.sh <규칙파일> <노출파일> 을 만드세요. 규칙 파일의 모든 expr 에서 DCGM_FI_ 로 시작하는 지표 이름을 뽑아, 그 이름의 샘플이 노출 파일에 하나도 없으면 MISSING=<이름> 을 한 줄씩 내고 1 로 끝냅니다. 전부 있으면 OK=<노출에 있는 지표 수> 를 내고 0 으로 끝냅니다. 만든 뒤 5단계 규칙과 1단계 노출 파일에 물려 출력을 /root/gpumet/out/rulecheck.txt 에 저장하세요.
7. /root/gpumet/k8s/servicemonitor-crd.yaml 에 servicemonitors.monitoring.coreos.com CRD 를 쓰고 적용하세요 — 그룹 monitoring.coreos.com, 버전 v1, 네임스페이스 스코프, 종류 ServiceMonitor. 스키마는 spec.selector.matchLabels(문자열 맵), spec.endpoints(배열, minItems: 1, 항목마다 port 필수 문자열, path 문자열, interval 은 ^[0-9]+(ms|s|m|h)$ 패턴을 가진 문자열)이고 spec 에는 selector 와 endpoints 가 모두 필수입니다. 다음으로 /root/gpumet/k8s/servicemonitor.yaml 에 gpu-metrics 네임스페이스의 nvidia-dcgm-exporter 를 쓰고 적용하세요 (셀렉터 app: nvidia-dcgm-exporter, 엔드포인트 하나에 port: gpu-metrics, path: /metrics, interval: 15s). 끝으로 /root/gpumet/k8s/servicemonitor-bad.yaml 에 이름 dcgm-bad-interval 로 같은 것을 쓰되 interval 을 따옴표 없는 30 으로 적고 적용해, 거부 출력을 /root/gpumet/out/07-reject.txt 에 표준 오류까지 담아 저장하세요.
8. /root/gpumet/bin/gpu-report.sh <노출파일> <규칙파일> 을 만드세요. 여섯 줄을 순서대로 냅니다 — GPUS=(노출에 나오는 카드 수), MEAN_UTIL=(평균 사용률, 버림), MAX_TEMP=(최고 온도), ORPHAN_GPUS=(파드 라벨 없이 FB_USED 가 1024 를 넘는 카드 수), XID_GPUS=(XID 오류가 0보다 큰 카드 수), ALERT_RULES=(규칙 파일의 규칙 총수). 숫자는 전부 인자로 받은 두 파일에서 계산해야 합니다. 3단계의 노출 파일과 5단계의 규칙 파일에 물려 출력을 /root/gpumet/out/report.txt 에 저장하세요.
참고
- 이 파드에는 GPU 도 DCGM 도 프로메테우스도 없습니다. 그래서 노출 텍스트를 1단계에서 직접 만들고 그 뒤 단계가 그것을 재료로 씁니다. 지표 이름과 라벨 이름은 공식 문서의 실제 출력 그대로입니다.
- PromQL 은 실행하지 않습니다. 경보 규칙은 구조와 참조하는 지표 이름의 존재까지만 판정합니다.
- 노출 형식 한 줄의 모양:
이름{라벨="값",…} 숫자. 주석은# HELP와# TYPE두 가지뿐입니다. - 메모리 총량 지표는 없습니다 — FB_USED 와 FB_FREE 를 더해서 얻습니다.
- 흔한 실수: 비율을 반올림하면 채점기가 잡습니다. 이 실습의 모든 비율은 버림 정수입니다.
- 흔한 실수: 스크립트 안에 1단계 파일의 숫자나 경로를 박아 두면, 채점기가 다른 파일을 물릴 때 떨어집니다.
단계 8개
- DCGM Exporter 의 노출 형식을 직접 쓴다
- 노출 텍스트를 카드별 표로 바꾼다
- 파드 라벨을 붙이고 임자 없는 점유를 찾는다
- 할당률과 사용률을 같은 화면에 올린다
- 사람이 움직여야 하는 것만 경보로 건다
- 규칙이 부르는 지표가 실제로 나오는지 대조한다
- 수집 대상을 스키마 있는 오브젝트로 만든다
- 여섯 줄짜리 GPU 현황 보고서를 계산해 낸다