- Published on
Kubernetes GPU 워크로드 관리: NVIDIA GPU Operator 완전 가이드
- Authors
- Name
- 1. Kubernetes에서 GPU를 사용해야 하는 이유
- 2. NVIDIA GPU Operator 아키텍처
- 3. GPU Operator 설치
- 4. NVIDIA Device Plugin 상세 분석
- 5. GPU 리소스 요청/제한 상세
- 6. GPU 공유 전략: MIG (Multi-Instance GPU)
- 7. GPU Time-Slicing 설정
- 8. MPS (Multi-Process Service) 설정
- 9. Node Affinity, Taint/Toleration으로 GPU 노드 분리
- 10. DCGM Exporter + Prometheus + Grafana 모니터링
- 11. GPU Feature Discovery 활용
- 12. 실전 YAML 예제와 트러블슈팅
- References
1. Kubernetes에서 GPU를 사용해야 하는 이유
AI/ML 워크로드의 폭발적인 증가로 인해 GPU는 더 이상 선택이 아닌 필수 인프라가 되었다. LLM 학습, 추론 서빙, 컴퓨터 비전, 과학 시뮬레이션 등 다양한 분야에서 GPU 가속 컴퓨팅이 요구되고 있으며, 이러한 워크로드를 대규모로 운영하려면 Kubernetes 기반의 오케스트레이션이 필연적이다.
Kubernetes에서 GPU를 사용하면 다음과 같은 이점을 얻을 수 있다.
- 리소스 스케줄링 자동화:
nvidia.com/gpu리소스 타입을 통해 Pod 단위로 GPU를 선언적으로 요청하고 할당받을 수 있다. - 멀티 테넌시: Namespace, ResourceQuota, LimitRange를 활용하여 팀별 GPU 리소스를 격리하고 공정하게 분배할 수 있다.
- GPU 공유: MIG, Time-Slicing, MPS 등의 기술을 통해 단일 GPU를 여러 워크로드가 공유함으로써 비용 효율성을 극대화할 수 있다.
- 자동 스케일링: HPA(Horizontal Pod Autoscaler)나 Karpenter 같은 도구와 결합하여 GPU 워크로드의 수요에 따라 자동으로 스케일링할 수 있다.
- 운영 표준화: GPU 드라이버 설치, 모니터링, 장애 대응 등의 운영 작업을 Operator 패턴으로 자동화할 수 있다.
그러나 Kubernetes에서 GPU를 제대로 활용하려면 GPU 드라이버, Container Toolkit, Device Plugin, 모니터링 등 여러 소프트웨어 컴포넌트를 정확하게 설치하고 관리해야 한다. 이 복잡성을 해결하기 위해 NVIDIA가 제공하는 것이 바로 GPU Operator이다.
2. NVIDIA GPU Operator 아키텍처
NVIDIA GPU Operator는 Kubernetes의 Operator Framework를 활용하여 GPU 노드에 필요한 모든 NVIDIA 소프트웨어 컴포넌트를 자동으로 프로비저닝하고 관리한다. 공식 문서에 따르면 GPU Operator는 다음 컴포넌트들을 포함한다.
2.1 핵심 컴포넌트
| 컴포넌트 | 역할 |
|---|---|
| NVIDIA GPU Driver | GPU와 운영체제 간의 인터페이스를 제공하며 CUDA를 활성화한다. |
| NVIDIA Container Toolkit | 컨테이너 런타임(containerd, CRI-O)이 GPU에 접근할 수 있도록 한다. |
| NVIDIA Device Plugin | kubelet API를 통해 GPU를 Kubernetes 리소스로 노출한다. |
| GPU Feature Discovery (GFD) | 노드에 장착된 GPU의 속성(모델, 메모리, CUDA 버전 등)을 감지하여 자동으로 Node Label을 생성한다. |
| DCGM Exporter | NVIDIA DCGM(Data Center GPU Manager)을 기반으로 GPU 메트릭을 Prometheus 형식으로 노출한다. |
| MIG Manager | Multi-Instance GPU 구성을 Kubernetes 컨트롤러 패턴으로 관리한다. |
| GPU Direct Storage (GDS) | 스토리지 디바이스와 GPU 메모리 간 직접 데이터 전송을 활성화한다. |
2.2 동작 원리
GPU Operator가 배포되면 다음 순서로 초기화가 진행된다.
- gpu-operator Pod 기동: 전체 컴포넌트의 상태를 감시하고 조정(reconciliation)하는 컨트롤러 역할을 수행한다.
- Node Feature Discovery (NFD) 배포: 클러스터의 각 노드에 Pod를 배포하여 GPU 유무를 감지하고 관련 Label을 추가한다.
- 드라이버 및 Toolkit 설치: GPU가 감지된 노드에 NVIDIA 드라이버와 Container Toolkit을 DaemonSet으로 배포한다.
- Device Plugin 배포: GPU를
nvidia.com/gpu리소스로 kubelet에 등록한다. - 부가 컴포넌트 배포: GFD, DCGM Exporter, MIG Manager 등을 배포한다.
모든 컴포넌트는 ClusterPolicy라는 Custom Resource에 의해 선언적으로 관리된다. Operator는 ClusterPolicy의 desired state와 actual state를 지속적으로 비교하며 차이가 발생하면 자동으로 보정한다.
3. GPU Operator 설치
GPU Operator는 Helm Chart를 통해 설치한다. 공식 문서의 설치 가이드를 기반으로 단계별로 살펴본다.
3.1 사전 요구사항
kubectl과helmCLI가 설치되어 있어야 한다.- 컨테이너 런타임으로 containerd 또는 CRI-O가 사용되어야 한다.
- GPU 워크로드를 실행할 모든 Worker Node는 동일한 OS 버전이어야 한다(드라이버를 별도 사전 설치하지 않는 경우).
- Pod Security Admission(PSA)을 사용하는 경우 Namespace에 privileged 레벨을 설정해야 한다.
3.2 설치 절차
# 1. Namespace 생성 및 PSA 설정
kubectl create ns gpu-operator
kubectl label --overwrite ns gpu-operator \
pod-security.kubernetes.io/enforce=privileged
# 2. NVIDIA Helm 리포지토리 추가
helm repo add nvidia https://helm.ngc.nvidia.com/nvidia
helm repo update
# 3. GPU Operator 설치 (기본 구성)
helm install --wait --generate-name \
-n gpu-operator --create-namespace \
nvidia/gpu-operator \
--version=v25.10.1
3.3 주요 설치 옵션
| 파라미터 | 용도 | 기본값 |
|---|---|---|
driver.enabled | NVIDIA 드라이버 배포 여부 | true |
toolkit.enabled | Container Toolkit 배포 여부 | true |
nfd.enabled | Node Feature Discovery 배포 여부 | true |
dcgmExporter.enabled | GPU 텔레메트리 활성화 여부 | true |
cdi.enabled | Container Device Interface 사용 여부 | true |
driver.version | 특정 드라이버 버전 지정 | 릴리스별 상이 |
mig.strategy | MIG 전략 설정 (none, single, mixed) | none |
호스트에 이미 NVIDIA 드라이버가 설치된 경우:
helm install --wait --generate-name \
-n gpu-operator --create-namespace \
nvidia/gpu-operator \
--version=v25.10.1 \
--set driver.enabled=false
드라이버와 Toolkit 모두 사전 설치된 경우:
helm install --wait --generate-name \
-n gpu-operator --create-namespace \
nvidia/gpu-operator \
--version=v25.10.1 \
--set driver.enabled=false \
--set toolkit.enabled=false
3.4 설치 검증
설치가 완료되면 간단한 CUDA 샘플로 GPU 동작을 확인할 수 있다.
apiVersion: v1
kind: Pod
metadata:
name: cuda-vectoradd
spec:
restartPolicy: OnFailure
containers:
- name: cuda-vectoradd
image: 'nvcr.io/nvidia/k8s/cuda-sample:vectoradd-cuda11.7.1-ubuntu20.04'
resources:
limits:
nvidia.com/gpu: 1
kubectl apply -f cuda-vectoradd.yaml
kubectl logs pod/cuda-vectoradd
# [Vector addition of 50000 elements]
# Test PASSED
4. NVIDIA Device Plugin 상세 분석
NVIDIA Device Plugin은 Kubernetes의 Device Plugin Framework를 구현한 컴포넌트로, GPU Operator의 핵심 구성 요소이다.
4.1 주요 기능
- GPU 열거(Enumeration): 노드에 장착된 모든 GPU를 탐지하고 수량을 kubelet에 보고한다.
- GPU 건강 모니터링: GPU의 상태를 지속적으로 확인하여 unhealthy 상태의 GPU를 스케줄링에서 제외한다.
- GPU 할당: Pod가
nvidia.com/gpu리소스를 요청하면 사용 가능한 GPU를 할당한다. - 리소스 공유: Time-Slicing, MIG 등의 GPU 공유 전략을 지원한다.
4.2 동작 방식
Device Plugin은 DaemonSet으로 배포되어 각 GPU 노드에서 실행된다. 동작 과정은 다음과 같다.
- Plugin이 gRPC 서버를 시작하고 kubelet의 Device Plugin 소켓에 등록한다.
- kubelet은
nvidia.com/gpu리소스의 용량(capacity)을 Node 객체에 반영한다. - Pod가 해당 리소스를 요청하면 kube-scheduler가 적절한 노드에 스케줄링한다.
- kubelet은 Device Plugin에게 GPU 할당을 요청하고, Plugin은 컨테이너에 필요한 디바이스 파일과 환경 변수를 설정한다.
4.3 리소스 요청/제한 설정
GPU 리소스는 resources.limits를 통해서만 요청할 수 있다. CPU나 메모리와 달리 requests를 별도로 설정할 수 없으며, limits를 설정하면 자동으로 동일한 값이 requests로 적용된다.
apiVersion: v1
kind: Pod
metadata:
name: gpu-pod
spec:
containers:
- name: gpu-container
image: nvcr.io/nvidia/pytorch:24.01-py3
resources:
limits:
nvidia.com/gpu: 2 # 2개의 GPU 요청
중요 제약사항:
- GPU는 정수 단위로만 요청할 수 있다 (
nvidia.com/gpu: 0.5는 불가). - GPU는 노드 간에 공유되지 않는다 (하나의 Pod가 여러 노드의 GPU를 동시에 사용할 수 없다).
limits를 지정하지 않으면 GPU가 할당되지 않는다.
5. GPU 리소스 요청/제한 상세
5.1 기본 리소스 모델
Kubernetes에서 GPU는 Extended Resource로 취급된다. nvidia.com/gpu라는 리소스 이름으로 요청하며, 이는 NVIDIA Device Plugin이 kubelet에 등록한 것이다.
resources:
limits:
nvidia.com/gpu: 1 # 1개 GPU 전용 할당
memory: '16Gi' # GPU와 별도로 시스템 메모리도 설정
cpu: '4'
5.2 ResourceQuota를 통한 GPU 제한
멀티 테넌트 환경에서 Namespace별 GPU 사용량을 제한할 수 있다.
apiVersion: v1
kind: ResourceQuota
metadata:
name: gpu-quota
namespace: team-ml
spec:
hard:
requests.nvidia.com/gpu: '4' # 최대 4개 GPU
limits.nvidia.com/gpu: '4'
5.3 LimitRange를 통한 기본값 설정
apiVersion: v1
kind: LimitRange
metadata:
name: gpu-limit-range
namespace: team-ml
spec:
limits:
- type: Container
default:
nvidia.com/gpu: '1'
defaultRequest:
nvidia.com/gpu: '1'
max:
nvidia.com/gpu: '2'
6. GPU 공유 전략: MIG (Multi-Instance GPU)
6.1 MIG 개요
Multi-Instance GPU(MIG)는 NVIDIA Ampere 아키텍처 이상의 GPU(A100, A30, H100 등)에서 지원되는 하드웨어 수준의 GPU 파티셔닝 기술이다. 단일 GPU를 최대 7개의 독립된 GPU 인스턴스로 분할할 수 있으며, 각 인스턴스는 전용 컴퓨팅 리소스, 메모리, 캐시를 가진다.
MIG의 핵심 장점은 하드웨어 수준의 격리이다. 각 MIG 인스턴스는 독립된 메모리 공간과 오류 격리를 제공하므로, 한 인스턴스의 장애가 다른 인스턴스에 영향을 미치지 않는다.
6.2 MIG 전략
GPU Operator는 두 가지 MIG 전략을 지원한다.
- Single Strategy: 노드의 모든 GPU가 동일한 MIG 구성을 갖는다. 리소스 이름은
nvidia.com/gpu로 유지된다. - Mixed Strategy: 일부 GPU는 MIG 모드로, 나머지는 Full GPU 모드로 운영할 수 있다. MIG 인스턴스는
nvidia.com/mig-<slice>형태의 별도 리소스로 노출된다.
6.3 MIG 설치 및 구성
MIG를 활성화하여 GPU Operator를 설치한다.
helm install --wait --generate-name \
-n gpu-operator --create-namespace \
nvidia/gpu-operator \
--version=v25.10.1 \
--set mig.strategy=single
사전 정의된 MIG 프로파일을 노드에 적용한다.
# 노드에 MIG 구성 Label 적용
kubectl label nodes gpu-node-01 \
nvidia.com/mig.config=all-1g.10gb --overwrite
주요 사전 정의 프로파일:
| 프로파일 | 설명 |
|---|---|
all-1g.10gb | 모든 GPU를 1g.10gb 인스턴스로 분할 |
all-3g.40gb | 모든 GPU를 3g.40gb 인스턴스로 분할 |
all-balanced | 다양한 크기의 인스턴스를 혼합 배치 |
all-disabled | MIG 모드 비활성화 |
6.4 커스텀 MIG 구성
기본 프로파일 외에 사용자 정의 구성도 가능하다.
apiVersion: v1
kind: ConfigMap
metadata:
name: custom-mig-config
namespace: gpu-operator
data:
config.yaml: |
version: v1
mig-configs:
custom-profile:
- devices: all
mig-enabled: true
mig-devices:
"1g.10gb": 5
"2g.20gb": 1
ClusterPolicy에 커스텀 ConfigMap을 연결한다.
kubectl patch clusterpolicies.nvidia.com/cluster-policy \
--type='json' \
-p='[{"op":"replace","path":"/spec/migManager/config/name","value":"custom-mig-config"}]'
구성 상태를 확인한다.
kubectl get node gpu-node-01 -o=jsonpath='{.metadata.labels}' | jq .
# "nvidia.com/mig.config.state": "success" 확인
6.5 MIG 리소스 사용
MIG 인스턴스를 사용하는 Pod는 다음과 같이 리소스를 요청한다.
apiVersion: v1
kind: Pod
metadata:
name: mig-workload
spec:
containers:
- name: cuda-app
image: nvcr.io/nvidia/pytorch:24.01-py3
resources:
limits:
nvidia.com/mig-1g.10gb: 1 # 1g.10gb MIG 인스턴스 1개 요청
7. GPU Time-Slicing 설정
7.1 Time-Slicing 개요
Time-Slicing은 NVIDIA GPU의 시분할 스케줄러를 활용하여 하나의 GPU를 여러 Pod가 시간적으로 공유하는 방식이다. MIG와 달리 메모리 격리나 오류 격리를 제공하지 않지만, MIG를 지원하지 않는 구형 GPU(T4, V100 등)에서도 사용할 수 있으며, GPU를 더 많은 수의 사용자/워크로드와 공유할 수 있다는 장점이 있다.
7.2 ConfigMap 구성
Time-Slicing은 ConfigMap을 통해 설정한다.
apiVersion: v1
kind: ConfigMap
metadata:
name: time-slicing-config
namespace: gpu-operator
data:
any: |-
version: v1
flags:
migStrategy: none
sharing:
timeSlicing:
renameByDefault: false
failRequestsGreaterThanOne: false
resources:
- name: nvidia.com/gpu
replicas: 4
주요 설정 필드:
| 필드 | 타입 | 설명 |
|---|---|---|
renameByDefault | boolean | true이면 리소스를 nvidia.com/gpu.shared로 광고한다. false이면 product label에 -SHARED 접미사를 추가한다. |
failRequestsGreaterThanOne | boolean | 하나의 Pod가 1개 이상의 GPU replica를 요청하는 것을 거부한다. true 설정을 권장한다. |
resources.name | string | 리소스 이름 (nvidia.com/gpu 등) |
resources.replicas | integer | GPU당 Time-Slice 복제본 수 |
7.3 클러스터 적용
클러스터 전체에 적용:
kubectl apply -f time-slicing-config.yaml
kubectl patch clusterpolicies.nvidia.com/cluster-policy \
-n gpu-operator --type merge \
-p '{"spec":{"devicePlugin":{"config":{"name":"time-slicing-config","default":"any"}}}}'
특정 노드에만 적용:
# ConfigMap에 GPU 모델별 설정을 정의한 경우
kubectl patch clusterpolicies.nvidia.com/cluster-policy \
-n gpu-operator --type merge \
-p '{"spec":{"devicePlugin":{"config":{"name":"time-slicing-config"}}}}'
# 해당 노드에 Label 적용
kubectl label node gpu-node-01 \
nvidia.com/device-plugin.config=tesla-t4
7.4 적용 결과 확인
Time-Slicing이 적용되면 노드의 Label과 allocatable 리소스가 변경된다.
kubectl get node gpu-node-01 -o jsonpath='{.status.allocatable}' | jq .
# "nvidia.com/gpu": "4" (물리 GPU 1개 * replicas 4)
kubectl get node gpu-node-01 --show-labels | grep nvidia
# nvidia.com/gpu.replicas=4
# nvidia.com/gpu.product=Tesla-T4-SHARED
7.5 주요 제약사항
- 메모리/오류 격리 없음: Time-Slice 복제본 간에 GPU 메모리가 공유되며, 한 프로세스의 장애가 다른 프로세스에 영향을 줄 수 있다.
- 비례적 컴퓨팅 보장 없음: 여러 GPU replica를 요청해도 비례적으로 더 많은 컴퓨팅 파워를 보장받지 못한다.
- DCGM Exporter 제한: GPU Time-Slicing이 활성화된 경우 메트릭을 개별 컨테이너에 연관시키는 것이 지원되지 않는다.
- ConfigMap 변경 시 수동 재시작 필요: Operator가 ConfigMap 변경을 자동 감지하지 않으므로 수동으로 DaemonSet을 재시작해야 한다.
kubectl rollout restart -n gpu-operator \
daemonset/nvidia-device-plugin-daemonset
8. MPS (Multi-Process Service) 설정
8.1 MPS 개요
NVIDIA MPS(Multi-Process Service)는 여러 CUDA 프로세스가 단일 GPU에서 동시에 실행될 수 있도록 하는 클라이언트-서버 아키텍처이다. 기존 CUDA 컨텍스트 스위칭의 오버헤드를 줄이고, 여러 프로세스의 CUDA 커널을 하나의 GPU 컨텍스트로 멀티플렉싱하여 GPU 활용률을 높인다.
8.2 MIG vs Time-Slicing vs MPS 비교
| 특성 | MIG | Time-Slicing | MPS |
|---|---|---|---|
| 메모리 격리 | O (하드웨어) | X | 부분적 (소프트웨어) |
| 오류 격리 | O | X | X |
| 지원 GPU | Ampere 이상 | 모든 NVIDIA GPU | Volta 이상 권장 |
| 최대 파티션 수 | 7 | 제한 없음 | 48 (Pre-Volta: 16) |
| 커널 동시 실행 | O | X (시분할) | O |
| 파티션 크기 유연성 | 고정 프로파일 | 균등 분할 | 임의 크기 |
8.3 MPS의 장단점
장점:
- MIG와 달리 임의 크기의 GPU 슬라이스를 생성할 수 있다.
- Time-Slicing과 달리 메모리 할당 제한을 강제할 수 있어 OOM 에러를 줄일 수 있다.
- 여러 프로세스의 CUDA 커널이 실제로 동시에 실행되므로 GPU 활용률이 높다.
단점:
- 오류 격리가 제공되지 않는다. 한 클라이언트 프로세스의 크래시가 GPU 리셋을 유발하여 다른 모든 프로세스에 영향을 줄 수 있다.
- 메모리 보호가 완전하지 않다.
8.4 Kubernetes에서 MPS 활용
현재 NVIDIA Device Plugin은 MPS를 직접 지원하지 않지만, NVIDIA의 DRA(Dynamic Resource Allocation) 드라이버를 통해 MPS를 구성할 수 있다. 또는 MPS를 지원하는 별도의 Device Plugin을 설치하여 사용할 수 있다.
GKE(Google Kubernetes Engine) 등 일부 관리형 Kubernetes 서비스에서는 MPS를 네이티브로 지원한다.
# GKE에서의 MPS 사용 예시
apiVersion: v1
kind: Pod
metadata:
name: mps-workload
spec:
containers:
- name: cuda-app
image: nvcr.io/nvidia/pytorch:24.01-py3
resources:
limits:
nvidia.com/gpu: 1
일반적인 온프레미스 Kubernetes 환경에서 MPS를 사용하려면 MPS Control Daemon을 사이드카 패턴이나 DaemonSet으로 배포하고, CUDA_MPS_PIPE_DIRECTORY와 CUDA_MPS_LOG_DIRECTORY 환경 변수를 설정해야 한다.
9. Node Affinity, Taint/Toleration으로 GPU 노드 분리
GPU 노드는 고가의 리소스이므로 GPU가 필요하지 않은 워크로드가 GPU 노드에 스케줄링되는 것을 방지해야 한다. Kubernetes의 Taint/Toleration과 Node Affinity를 조합하여 이를 구현한다.
9.1 GPU 노드에 Taint 적용
# GPU 노드에 Taint 추가
kubectl taint nodes gpu-node-01 \
nvidia.com/gpu=present:NoSchedule
kubectl taint nodes gpu-node-02 \
nvidia.com/gpu=present:NoSchedule
이 Taint가 적용되면 해당 Toleration이 없는 Pod는 GPU 노드에 스케줄링되지 않는다.
9.2 GPU 워크로드에 Toleration 추가
apiVersion: v1
kind: Pod
metadata:
name: gpu-training-job
spec:
tolerations:
- key: 'nvidia.com/gpu'
operator: 'Equal'
value: 'present'
effect: 'NoSchedule'
containers:
- name: training
image: nvcr.io/nvidia/pytorch:24.01-py3
resources:
limits:
nvidia.com/gpu: 1
9.3 Node Affinity로 특정 GPU 모델 선택
GPU Feature Discovery가 생성한 Label을 활용하여 특정 GPU 모델이 장착된 노드에만 워크로드를 스케줄링할 수 있다.
apiVersion: v1
kind: Pod
metadata:
name: a100-training
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: nvidia.com/gpu.product
operator: In
values:
- 'A100-SXM4-80GB'
- 'A100-SXM4-40GB'
- key: nvidia.com/gpu.memory
operator: Gt
values:
- '40000'
tolerations:
- key: 'nvidia.com/gpu'
operator: 'Equal'
value: 'present'
effect: 'NoSchedule'
containers:
- name: llm-training
image: nvcr.io/nvidia/pytorch:24.01-py3
command: ['python', 'train.py']
resources:
limits:
nvidia.com/gpu: 4
9.4 실전 전략: Taint + Affinity 조합
GPU 노드 관리의 Best Practice는 Taint로 비GPU 워크로드를 차단하고, Node Affinity로 GPU 워크로드를 적절한 노드로 유도하는 이중 전략이다.
- Taint: GPU 노드에 접근할 수 있는 Pod를 제한하는 "hard" 제약
- Node Affinity: Pod가 원하는 GPU 사양의 노드에 배치되도록 하는 "soft" 또는 "hard" 선호
Toleration은 Pod가 Taint된 노드에 스케줄링될 수 있게 허용할 뿐, 해당 노드를 강제하지는 않는다. 따라서 Node Affinity와 반드시 함께 사용해야 GPU 워크로드가 정확히 GPU 노드에만 배치된다.
10. DCGM Exporter + Prometheus + Grafana 모니터링
10.1 DCGM Exporter 개요
DCGM Exporter는 NVIDIA Data Center GPU Manager(DCGM)의 Go API를 사용하여 GPU 텔레메트리 데이터를 수집하고 Prometheus 형식으로 노출하는 컴포넌트이다. GPU Operator를 설치하면 기본적으로 DCGM Exporter가 DaemonSet으로 배포된다.
주요 수집 메트릭:
| 메트릭 | 설명 |
|---|---|
DCGM_FI_DEV_GPU_UTIL | GPU 사용률 (%) |
DCGM_FI_DEV_MEM_COPY_UTIL | 메모리 복사 사용률 (%) |
DCGM_FI_DEV_FB_USED | Framebuffer 사용 메모리 (MB) |
DCGM_FI_DEV_FB_FREE | Framebuffer 여유 메모리 (MB) |
DCGM_FI_DEV_GPU_TEMP | GPU 온도 (C) |
DCGM_FI_DEV_POWER_USAGE | 전력 사용량 (W) |
DCGM_FI_DEV_SM_CLOCK | SM Clock 주파수 (MHz) |
DCGM_FI_DEV_PCIE_TX_THROUGHPUT | PCIe TX 처리량 |
DCGM_FI_DEV_PCIE_RX_THROUGHPUT | PCIe RX 처리량 |
10.2 Prometheus 스택 설치
kube-prometheus-stack을 사용하여 Prometheus와 Grafana를 함께 배포한다.
# Prometheus 커뮤니티 Helm 리포지토리 추가
helm repo add prometheus-community \
https://prometheus-community.github.io/helm-charts
helm repo update
GPU 메트릭 수집을 위한 values 파일을 작성한다.
# kube-prometheus-stack-values.yaml
prometheus:
service:
type: NodePort
nodePort: 30090
prometheusSpec:
serviceMonitorSelectorNilUsesHelmValues: false
additionalScrapeConfigs:
- job_name: gpu-metrics
scrape_interval: 1s
metrics_path: /metrics
scheme: http
kubernetes_sd_configs:
- role: endpoints
namespaces:
names:
- gpu-operator
relabel_configs:
- source_labels: [__meta_kubernetes_pod_node_name]
action: replace
target_label: kubernetes_node
grafana:
service:
type: NodePort
nodePort: 32322
helm install prometheus-community/kube-prometheus-stack \
--create-namespace --namespace prometheus \
--generate-name \
--values kube-prometheus-stack-values.yaml
10.3 Grafana Dashboard 구성
NVIDIA 공식 DCGM Exporter 대시보드를 Import한다.
- Grafana에 접속한다 (
http://<node-ip>:32322). - Dashboards > Import로 이동한다.
- Dashboard ID
12239를 입력한다 (NVIDIA DCGM Exporter Dashboard). - Data Source로 Prometheus를 선택한다.
이 대시보드는 GPU 활용률, 메모리 사용량, 온도, 전력 사용량 등을 실시간으로 시각화한다. MIG와 Non-MIG GPU를 모두 지원하는 대시보드는 ID 23382를 사용한다.
10.4 Alert 설정 예시
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: gpu-alerts
namespace: prometheus
spec:
groups:
- name: gpu.rules
rules:
- alert: GPUHighTemperature
expr: DCGM_FI_DEV_GPU_TEMP > 85
for: 5m
labels:
severity: warning
annotations:
summary: 'GPU temperature is high on {{ $labels.kubernetes_node }}'
description: 'GPU {{ $labels.gpu }} temperature is {{ $value }}C'
- alert: GPUMemoryAlmostFull
expr: (DCGM_FI_DEV_FB_USED / (DCGM_FI_DEV_FB_USED + DCGM_FI_DEV_FB_FREE)) > 0.95
for: 5m
labels:
severity: critical
annotations:
summary: 'GPU memory usage above 95% on {{ $labels.kubernetes_node }}'
- alert: GPUHighUtilization
expr: DCGM_FI_DEV_GPU_UTIL > 95
for: 30m
labels:
severity: info
annotations:
summary: 'Sustained high GPU utilization on {{ $labels.kubernetes_node }}'
11. GPU Feature Discovery 활용
11.1 개요
GPU Feature Discovery(GFD)는 노드에 장착된 GPU의 속성을 자동으로 감지하여 Kubernetes Node Label을 생성하는 컴포넌트이다. Node Feature Discovery(NFD)를 기반으로 동작하며, GPU Operator에 포함되어 자동 배포된다.
11.2 생성되는 Label 목록
| Label | 설명 | 예시 값 |
|---|---|---|
nvidia.com/gpu.product | GPU 모델명 | Tesla-T4, A100-SXM4-80GB |
nvidia.com/gpu.memory | GPU 메모리 용량 (MB) | 40960 |
nvidia.com/gpu.count | GPU 수량 | 4 |
nvidia.com/gpu.family | GPU 아키텍처 패밀리 | ampere, hopper |
nvidia.com/gpu.compute.major | CUDA Compute Capability (Major) | 8 |
nvidia.com/gpu.compute.minor | CUDA Compute Capability (Minor) | 0 |
nvidia.com/cuda.driver.major | CUDA 드라이버 Major 버전 | 535 |
nvidia.com/cuda.driver.minor | CUDA 드라이버 Minor 버전 | 129 |
nvidia.com/cuda.runtime.major | CUDA Runtime Major 버전 | 12 |
nvidia.com/cuda.runtime.minor | CUDA Runtime Minor 버전 | 2 |
nvidia.com/gpu.machine | 머신 타입 (클라우드에서는 인스턴스 타입) | p4d.24xlarge |
nvidia.com/gpu.replicas | GPU replica 수 (공유 시) | 4 |
nvidia.com/mig.strategy | MIG 전략 | single, mixed |
11.3 Label 활용 예시
GFD Label을 활용하면 GPU 사양에 따른 세밀한 스케줄링이 가능하다.
# Hopper 아키텍처 GPU에서만 실행
apiVersion: batch/v1
kind: Job
metadata:
name: h100-inference
spec:
template:
spec:
nodeSelector:
nvidia.com/gpu.family: hopper
containers:
- name: inference
image: nvcr.io/nvidia/tritonserver:24.01-py3
resources:
limits:
nvidia.com/gpu: 1
restartPolicy: Never
# 80GB 이상 GPU 메모리가 필요한 대규모 모델 학습
apiVersion: batch/v1
kind: Job
metadata:
name: large-model-training
spec:
template:
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: nvidia.com/gpu.memory
operator: Gt
values:
- '79000'
- key: nvidia.com/gpu.count
operator: Gt
values:
- '7'
containers:
- name: training
image: nvcr.io/nvidia/pytorch:24.01-py3
resources:
limits:
nvidia.com/gpu: 8
restartPolicy: Never
12. 실전 YAML 예제와 트러블슈팅
12.1 PyTorch 분산 학습 Job
apiVersion: batch/v1
kind: Job
metadata:
name: distributed-training
spec:
parallelism: 2
completions: 2
template:
metadata:
labels:
app: distributed-training
spec:
tolerations:
- key: 'nvidia.com/gpu'
operator: 'Equal'
value: 'present'
effect: 'NoSchedule'
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: nvidia.com/gpu.product
operator: In
values:
- 'A100-SXM4-80GB'
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- distributed-training
topologyKey: kubernetes.io/hostname
containers:
- name: pytorch-trainer
image: nvcr.io/nvidia/pytorch:24.01-py3
command:
- torchrun
- --nproc_per_node=4
- --nnodes=2
- train.py
resources:
limits:
nvidia.com/gpu: 4
memory: '64Gi'
cpu: '16'
requests:
memory: '64Gi'
cpu: '16'
env:
- name: NCCL_DEBUG
value: 'INFO'
volumeMounts:
- name: dshm
mountPath: /dev/shm
- name: training-data
mountPath: /data
volumes:
- name: dshm
emptyDir:
medium: Memory
sizeLimit: '16Gi'
- name: training-data
persistentVolumeClaim:
claimName: training-data-pvc
restartPolicy: Never
backoffLimit: 3
주의사항: PyTorch 분산 학습에서 /dev/shm(공유 메모리)의 크기가 부족하면 DataLoader의 num_workers > 0 설정 시 크래시가 발생할 수 있다. emptyDir을 Memory medium으로 마운트하여 충분한 크기를 할당해야 한다.
12.2 Triton Inference Server 배포
apiVersion: apps/v1
kind: Deployment
metadata:
name: triton-inference
spec:
replicas: 2
selector:
matchLabels:
app: triton-inference
template:
metadata:
labels:
app: triton-inference
spec:
tolerations:
- key: 'nvidia.com/gpu'
operator: 'Equal'
value: 'present'
effect: 'NoSchedule'
nodeSelector:
nvidia.com/gpu.family: ampere
containers:
- name: triton
image: nvcr.io/nvidia/tritonserver:24.01-py3
args:
- tritonserver
- --model-repository=/models
- --strict-model-config=false
ports:
- containerPort: 8000
name: http
- containerPort: 8001
name: grpc
- containerPort: 8002
name: metrics
resources:
limits:
nvidia.com/gpu: 1
memory: '16Gi'
cpu: '4'
readinessProbe:
httpGet:
path: /v2/health/ready
port: 8000
initialDelaySeconds: 30
periodSeconds: 10
livenessProbe:
httpGet:
path: /v2/health/live
port: 8000
initialDelaySeconds: 30
periodSeconds: 15
volumeMounts:
- name: model-store
mountPath: /models
volumes:
- name: model-store
persistentVolumeClaim:
claimName: model-store-pvc
---
apiVersion: v1
kind: Service
metadata:
name: triton-inference
spec:
selector:
app: triton-inference
ports:
- name: http
port: 8000
targetPort: 8000
- name: grpc
port: 8001
targetPort: 8001
- name: metrics
port: 8002
targetPort: 8002
12.3 트러블슈팅 가이드
GPU가 노드에서 인식되지 않는 경우
# 1. GPU Operator Pod 상태 확인
kubectl get pods -n gpu-operator
# 2. 드라이버 Pod 로그 확인
kubectl logs -n gpu-operator -l app=nvidia-driver-daemonset
# 3. Device Plugin Pod 로그 확인
kubectl logs -n gpu-operator -l app=nvidia-device-plugin-daemonset
# 4. 노드의 allocatable 리소스 확인
kubectl describe node gpu-node-01 | grep -A 5 "Allocatable"
# 5. NFD Label 확인
kubectl get node gpu-node-01 -o json | \
jq '.metadata.labels | to_entries[] | select(.key | startswith("nvidia"))'
Pod가 GPU 노드에 스케줄링되지 않는 경우
# 1. Pod 이벤트 확인
kubectl describe pod <pod-name>
# "Insufficient nvidia.com/gpu" 메시지 확인
# 2. 노드의 GPU 할당 상태 확인
kubectl describe node gpu-node-01 | grep -A 3 "Allocated resources"
# 3. GPU를 사용 중인 Pod 목록 확인
kubectl get pods --all-namespaces -o json | \
jq '.items[] | select(.spec.containers[].resources.limits["nvidia.com/gpu"] != null) | .metadata.name'
MIG 구성이 적용되지 않는 경우
# 1. MIG Manager 로그 확인
kubectl logs -n gpu-operator -l app=nvidia-mig-manager
# 2. MIG 구성 상태 Label 확인
kubectl get node gpu-node-01 -o jsonpath='{.metadata.labels.nvidia\.com/mig\.config\.state}'
# "success" 가 아니면 구성 실패
# 3. GPU 모드 확인 (노드에서)
nvidia-smi -L
nvidia-smi --query-gpu=mig.mode.current --format=csv
Time-Slicing 적용 후 GPU 수가 변경되지 않는 경우
# 1. ConfigMap 내용 확인
kubectl get configmap -n gpu-operator time-slicing-config -o yaml
# 2. Device Plugin 재시작
kubectl rollout restart -n gpu-operator \
daemonset/nvidia-device-plugin-daemonset
# 3. 재시작 후 노드 리소스 확인
kubectl get node gpu-node-01 -o jsonpath='{.status.allocatable.nvidia\.com/gpu}'
References
- NVIDIA GPU Operator - 공식 문서
- NVIDIA GPU Operator - 설치 가이드
- NVIDIA GPU Operator - GPU Sharing (Time-Slicing)
- NVIDIA GPU Operator - MIG 구성
- NVIDIA Device Plugin for Kubernetes - GitHub
- NVIDIA GPU Feature Discovery - 문서
- NVIDIA Multi-Instance GPU User Guide
- NVIDIA MPS (Multi-Process Service) 공식 문서
- NVIDIA DCGM Exporter - GitHub
- NVIDIA DCGM Exporter - 공식 문서
- NVIDIA DCGM Exporter Grafana Dashboard
- Prometheus GPU 텔레메트리 설정 가이드
- Kubernetes Device Plugins - 공식 문서
- NVIDIA Cloud Native Technologies
- NVIDIA GPU Operator - GitHub
- NVIDIA GPU Operator Helm Chart - NGC Catalog