- Published on
NVIDIA GPU Operator 완벽 가이드: 구성요소, 설치, KubeVirt GPU 패스스루까지 총정리
- Authors
- Name
- 1. GPU Operator 소개
- 2. 7대 핵심 구성요소 상세 분석
- 3. 설치 가이드 (Helm 기반)
- 4. GPU 공유 전략
- 5. KubeVirt와 GPU Operator 통합
- 6. 모니터링 및 Observability
- 7. 프로덕션 배포 베스트 프랙티스
- 8. 트러블슈팅 가이드
- 9. 참고 자료 (References)
1. GPU Operator 소개
1.1 GPU Operator란?
NVIDIA GPU Operator는 Kubernetes 클러스터에서 GPU를 활용하기 위해 필요한 모든 소프트웨어 컴포넌트의 설치, 설정, 관리를 자동화하는 Kubernetes Operator이다. Kubernetes의 Operator Framework를 기반으로, GPU 워크로드 실행에 필요한 드라이버, 런타임, 디바이스 플러그인, 모니터링 도구 등을 Day-0 프로비저닝부터 Day-2 운영까지 일관되게 관리한다.
전통적으로 Kubernetes에서 GPU를 사용하려면 다음과 같은 작업을 각 노드마다 수동으로 수행해야 했다:
- NVIDIA 드라이버 설치 (커널 버전에 맞는 정확한 버전)
- NVIDIA Container Toolkit 설치 및 Container Runtime 설정
- NVIDIA Device Plugin 배포
- 모니터링 도구 (DCGM Exporter) 설치
- Node Feature Discovery 배포
GPU Operator는 이 모든 과정을 ClusterPolicy라는 단일 Custom Resource Definition(CRD)으로 선언적(declarative)으로 관리한다.
1.2 왜 GPU Operator가 필요한가?
수동 GPU 드라이버 설치 방식에는 다음과 같은 심각한 운영 문제가 있다:
| 문제점 | 수동 관리 | GPU Operator |
|---|---|---|
| 드라이버 설치 | 각 노드 SSH 접속 후 수동 설치 | DaemonSet으로 자동 배포 |
| 커널 업데이트 대응 | 커널 업데이트 시 드라이버 재컴파일 필요 | Pre-compiled 드라이버 자동 매칭 |
| 버전 일관성 | 노드별 드라이버 버전 불일치 위험 | ClusterPolicy로 버전 통일 |
| 신규 노드 추가 | 프로비저닝 스크립트 유지보수 필요 | 라벨 기반 자동 감지 및 설치 |
| 모니터링 | 별도 설정 필요 | DCGM Exporter 자동 배포 |
| GPU 공유 | MIG/Time-Slicing 수동 설정 | ConfigMap 기반 선언적 설정 |
| 업그레이드 | 노드 드레인 후 수동 업데이트 | Rolling Update 지원 |
1.3 지원 환경
지원 OS:
| OS | 버전 |
|---|---|
| Ubuntu | 20.04, 22.04, 24.04 LTS |
| Red Hat Enterprise Linux | 8.x, 9.x |
| CentOS Stream | 8, 9 |
| Rocky Linux | 8.x, 9.x |
| SUSE Linux Enterprise | 15 SP4+ |
지원 GPU:
| GPU 세대 | 모델 예시 | MIG 지원 |
|---|---|---|
| Turing | T4, RTX 2080 | X |
| Ampere | A100, A30, A10, A2 | O (A100, A30) |
| Hopper | H100, H200 | O |
| Ada Lovelace | L40, L40S, L4 | X |
| Blackwell | B100, B200, GB200 | O |
지원 Kubernetes 버전: v1.25 이상 (권장: v1.28+)
지원 Container Runtime: containerd, CRI-O
1.4 아키텍처 개요
┌─────────────────────────────────────────────────────────────────────┐
│ Kubernetes Control Plane │
│ ┌──────────────────────────────────────────────────────────────┐ │
│ │ GPU Operator Controller │ │
│ │ (Deployment in gpu-operator namespace) │ │
│ │ │ │
│ │ ┌────────────────┐ ┌─────────────────────────────────┐ │ │
│ │ │ ClusterPolicy │───▶│ Reconciliation Loop │ │ │
│ │ │ (CRD) │ │ - Watch GPU Nodes │ │ │
│ │ └────────────────┘ │ - Deploy DaemonSets │ │ │
│ │ │ - Manage Lifecycle │ │ │
│ │ └─────────────────────────────────┘ │ │
│ └──────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────┘
│
┌──────────────┼──────────────┐
▼ ▼ ▼
┌──────────────────┐ ┌──────────────┐ ┌──────────────────┐
│ GPU Worker #1 │ │ GPU Worker #2│ │ GPU Worker #3 │
│ │ │ │ │ │
│ ┌──────────────┐ │ │ ┌──────────┐ │ │ ┌──────────────┐ │
│ │ NFD │ │ │ │ NFD │ │ │ │ NFD │ │
│ │ (Node Feature│ │ │ │ │ │ │ │ │ │
│ │ Discovery) │ │ │ └──────────┘ │ │ └──────────────┘ │
│ └──────────────┘ │ │ ┌──────────┐ │ │ ┌──────────────┐ │
│ ┌──────────────┐ │ │ │ GFD │ │ │ │ GFD │ │
│ │ GFD │ │ │ │ │ │ │ │ │ │
│ │ (GPU Feature │ │ │ └──────────┘ │ │ └──────────────┘ │
│ │ Discovery) │ │ │ ┌──────────┐ │ │ ┌──────────────┐ │
│ └──────────────┘ │ │ │ Driver │ │ │ │ Driver │ │
│ ┌──────────────┐ │ │ │ │ │ │ │ │ │
│ │ NVIDIA Driver│ │ │ └──────────┘ │ │ └──────────────┘ │
│ │ (DaemonSet) │ │ │ ┌──────────┐ │ │ ┌──────────────┐ │
│ └──────────────┘ │ │ │ Toolkit │ │ │ │ Toolkit │ │
│ ┌──────────────┐ │ │ │ │ │ │ │ │ │
│ │ Container │ │ │ └──────────┘ │ │ └──────────────┘ │
│ │ Toolkit │ │ │ ┌──────────┐ │ │ ┌──────────────┐ │
│ └──────────────┘ │ │ │ Device │ │ │ │ Device │ │
│ ┌──────────────┐ │ │ │ Plugin │ │ │ │ Plugin │ │
│ │ Device Plugin│ │ │ └──────────┘ │ │ └──────────────┘ │
│ └──────────────┘ │ │ ┌──────────┐ │ │ ┌──────────────┐ │
│ ┌──────────────┐ │ │ │ DCGM │ │ │ │ DCGM │ │
│ │ DCGM Exporter│ │ │ │ Exporter │ │ │ │ Exporter │ │
│ └──────────────┘ │ │ └──────────┘ │ │ └──────────────┘ │
│ ┌──────────────┐ │ │ ┌──────────┐ │ │ ┌──────────────┐ │
│ │ MIG Manager │ │ │ │ MIG Mgr │ │ │ │ MIG Manager │ │
│ └──────────────┘ │ │ └──────────┘ │ │ └──────────────┘ │
│ │ │ │ │ │
│ ╔════════════╗ │ │ ╔══════════╗ │ │ ╔════════════╗ │
│ ║ NVIDIA GPU ║ │ │ ║ NVIDIA ║ │ │ ║ NVIDIA GPU ║ │
│ ║ (A100) ║ │ │ ║ GPU(H100)║ │ │ ║ (T4) ║ │
│ ╚════════════╝ │ │ ╚══════════╝ │ │ ╚════════════╝ │
└──────────────────┘ └──────────────┘ └──────────────────┘
GPU Operator Controller는 ClusterPolicy CRD를 감시(watch)하며, GPU가 탑재된 워커 노드를 자동으로 감지하여 필요한 모든 컴포넌트를 DaemonSet 형태로 배포한다. 노드에 feature.node.kubernetes.io/pci-10de.present=true 라벨이 있으면 NVIDIA GPU가 존재하는 것으로 인식한다.
2. 7대 핵심 구성요소 상세 분석
GPU Operator는 GPU 워크로드 실행에 필요한 전체 소프트웨어 스택을 7개의 핵심 컴포넌트로 구성한다. 각 컴포넌트는 DaemonSet으로 배포되며, 서로 의존 관계를 가진다.
2.1 NVIDIA Driver (nvidia-driver-daemonset)
NVIDIA Driver DaemonSet은 GPU 하드웨어와 통신하기 위한 **커널 모듈(kernel module)**을 각 GPU 노드에 자동으로 설치한다. 이것은 GPU Operator의 가장 기초적이고 핵심적인 컴포넌트이다.
주요 기능:
- NVIDIA 커널 모듈 (
nvidia.ko,nvidia-modeset.ko,nvidia-uvm.ko) 자동 빌드 및 로드 - 호스트 커널 버전에 맞는 드라이버 자동 매칭
- Pre-compiled 드라이버와 Run-compiled 드라이버 지원
- 드라이버 버전 관리 및 업그레이드
Pre-compiled vs Run-compiled:
| 특성 | Pre-compiled | Run-compiled |
|---|---|---|
| 빌드 시간 | 없음 (이미 빌드됨) | 노드에서 10-20분 소요 |
| 커널 호환성 | 특정 커널 버전에 매칭 | 모든 커널 버전 지원 |
| 노드 부팅 시간 | 빠름 | 느림 |
| 지원 OS | Ubuntu (주로) | 대부분의 Linux |
| 설정 | kernelModuleType: precompiled | kernelModuleType: runcompiled |
ClusterPolicy에서 Driver 설정 예시:
apiVersion: nvidia.com/v1
kind: ClusterPolicy
metadata:
name: cluster-policy
spec:
driver:
enabled: true
repository: nvcr.io/nvidia
image: driver
version: '560.35.03'
kernelModuleType: auto # auto | precompiled | runcompiled
manager:
env:
- name: ENABLE_AUTO_DRAIN
value: 'true'
rdma:
enabled: false
licensingConfig:
nlsEnabled: false
configMapName: ''
주의: 호스트에 이미 NVIDIA 드라이버가 설치되어 있는 경우
driver.enabled=false로 설정해야 한다. 두 드라이버가 충돌하면 GPU가 정상 작동하지 않는다.
2.2 NVIDIA Container Toolkit (nvidia-container-toolkit)
NVIDIA Container Toolkit은 Container Runtime(containerd, CRI-O)이 컨테이너 내부에서 GPU에 접근할 수 있도록 연결하는 브릿지 역할을 한다.
핵심 동작 원리:
┌─────────────────────────────────────────────────────┐
│ Container Creation Flow │
│ │
│ kubelet │
│ │ │
│ ▼ │
│ containerd/CRI-O │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────┐ │
│ │ NVIDIA Container Runtime Hook │ │
│ │ (nvidia-container-runtime-hook) │ │
│ │ │ │
│ │ 1. OCI spec 수정 │ │
│ │ 2. GPU 디바이스 마운트 │ │
│ │ 3. NVIDIA 라이브러리 주입 │ │
│ │ 4. 환경변수 설정 │ │
│ └─────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────┐ │
│ │ libnvidia-container │ │
│ │ - GPU 디바이스 노드 바인딩 │ │
│ │ - CUDA 라이브러리 마운트 │ │
│ │ - Driver 라이브러리 마운트 │ │
│ └─────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ Container (with GPU access) │
│ /dev/nvidia0, /dev/nvidiactl, ... │
└─────────────────────────────────────────────────────┘
CDI (Container Device Interface) 지원:
GPU Operator v25.x부터 CDI가 기본 활성화되어, 컨테이너 런타임이 GPU 디바이스를 표준화된 방식으로 인식한다. CDI는 OCI 런타임 hook 방식보다 더 안정적이고 예측 가능한 디바이스 할당을 제공한다.
spec:
toolkit:
enabled: true
version: v1.17.3-ubuntu22.04
cdi:
enabled: true # CDI 활성화 (기본값: true)
default: true # CDI를 기본 디바이스 할당 방식으로 사용
2.3 NVIDIA Device Plugin (nvidia-device-plugin)
NVIDIA Device Plugin은 kubelet에 GPU를 Kubernetes Extended Resource로 등록하는 역할을 한다. 이를 통해 Pod이 nvidia.com/gpu 리소스를 요청할 수 있게 된다.
동작 흐름:
- Device Plugin이 kubelet의 Device Plugin gRPC 인터페이스에 등록
- 노드에 있는 GPU 개수를 kubelet에 보고
- Kubernetes Scheduler가
nvidia.com/gpu리소스 요청이 있는 Pod을 해당 노드에 스케줄링 - Pod 실행 시 Device Plugin이 할당할 GPU 디바이스 정보를 kubelet에 전달
Pod에서 GPU 요청 예시:
apiVersion: v1
kind: Pod
metadata:
name: cuda-test
spec:
restartPolicy: OnFailure
containers:
- name: cuda-test
image: nvcr.io/nvidia/cuda:12.6.0-base-ubuntu22.04
command: ['nvidia-smi']
resources:
limits:
nvidia.com/gpu: 1 # GPU 1개 요청
Device Plugin이 관리하는 리소스 종류:
| 리소스 이름 | 설명 | 사용 상황 |
|---|---|---|
nvidia.com/gpu | 전체 GPU (또는 Time-Slicing 공유) | 기본 GPU 워크로드 |
nvidia.com/mig-1g.5gb | MIG 1g.5gb 인스턴스 | A100 MIG 파티션 |
nvidia.com/mig-2g.10gb | MIG 2g.10gb 인스턴스 | A100 MIG 파티션 |
nvidia.com/mig-3g.20gb | MIG 3g.20gb 인스턴스 | A100 MIG 파티션 |
nvidia.com/mig-7g.40gb | MIG 7g.40gb 인스턴스 | A100 전체 MIG |
nvidia.com/gpu.shared | Time-Slicing 공유 GPU | renameByDefault 활성화 시 |
2.4 NVIDIA DCGM & DCGM Exporter
**DCGM (Data Center GPU Manager)**은 NVIDIA GPU의 상태와 성능을 모니터링하기 위한 도구이며, DCGM Exporter는 이 메트릭을 Prometheus 포맷으로 노출하는 Exporter이다.
주요 수집 메트릭:
| 메트릭 이름 | 설명 | 단위 |
|---|---|---|
DCGM_FI_DEV_GPU_UTIL | GPU 코어 사용률 | % |
DCGM_FI_DEV_MEM_COPY_UTIL | 메모리 대역폭 사용률 | % |
DCGM_FI_DEV_GPU_TEMP | GPU 온도 | C |
DCGM_FI_DEV_POWER_USAGE | 전력 소비량 | W |
DCGM_FI_DEV_FB_FREE | 사용 가능한 프레임버퍼 메모리 | MiB |
DCGM_FI_DEV_FB_USED | 사용 중인 프레임버퍼 메모리 | MiB |
DCGM_FI_DEV_SM_CLOCK | SM 클럭 주파수 | MHz |
DCGM_FI_DEV_MEM_CLOCK | 메모리 클럭 주파수 | MHz |
DCGM_FI_DEV_ENC_UTIL | 인코더 사용률 | % |
DCGM_FI_DEV_DEC_UTIL | 디코더 사용률 | % |
DCGM_FI_DEV_PCIE_TX_THROUGHPUT | PCIe 송신 처리량 | KB/s |
DCGM_FI_DEV_PCIE_RX_THROUGHPUT | PCIe 수신 처리량 | KB/s |
DCGM_FI_DEV_XID_ERRORS | XID 에러 발생 횟수 | count |
DCGM_FI_DEV_ECC_SBE_VOL_TOTAL | Single-bit ECC 에러 (일시적) | count |
DCGM_FI_DEV_ECC_DBE_VOL_TOTAL | Double-bit ECC 에러 (영구적) | count |
DCGM Exporter 아키텍처:
┌──────────────┐ ┌───────────────┐ ┌──────────────┐
│ NVIDIA GPU │────▶│ DCGM Daemon │────▶│ DCGM Exporter│
│ (Hardware) │ │ (libdcgm.so) │ │ (:9400/metrics)
└──────────────┘ └───────────────┘ └──────┬───────┘
│
▼
┌──────────────┐
│ Prometheus │
│ (scrape) │
└──────┬───────┘
│
▼
┌──────────────┐
│ Grafana │
│ (Dashboard) │
└──────────────┘
ClusterPolicy 설정:
spec:
dcgm:
enabled: true # standalone DCGM daemon
dcgmExporter:
enabled: true
version: '3.3.9-3.6.1-ubuntu22.04'
config:
name: 'dcgm-metrics-config' # 커스텀 메트릭 설정
serviceMonitor:
enabled: true # Prometheus ServiceMonitor 자동 생성
interval: '15s'
honorLabels: false
additionalLabels:
monitoring: 'gpu'
2.5 NVIDIA MIG Manager
MIG (Multi-Instance GPU) Manager는 NVIDIA Ampere 이상 아키텍처의 GPU(A100, A30, H100 등)에서 하나의 물리 GPU를 여러 개의 독립적인 GPU 인스턴스로 분할하는 것을 관리한다.
MIG는 Time-Slicing과 달리 하드웨어 수준의 메모리 격리와 연산 격리를 제공한다. 각 MIG 인스턴스는 자체 메모리, 캐시, SM(Streaming Multiprocessor)을 가진다.
A100 40GB MIG 프로파일:
| 프로파일 | GPU 슬라이스 | 메모리 | 최대 인스턴스 수 |
|---|---|---|---|
1g.5gb | 1/7 | 5 GB | 7 |
1g.5gb+me | 1/7 | 5 GB (+MPS) | 1 |
1g.10gb | 1/7 | 10 GB | 4 |
2g.10gb | 2/7 | 10 GB | 3 |
3g.20gb | 3/7 | 20 GB | 2 |
4g.20gb | 4/7 | 20 GB | 1 |
7g.40gb | 7/7 | 40 GB | 1 |
H100 80GB MIG 프로파일:
| 프로파일 | GPU 슬라이스 | 메모리 | 최대 인스턴스 수 |
|---|---|---|---|
1g.10gb | 1/7 | 10 GB | 7 |
1g.20gb | 1/7 | 20 GB | 4 |
2g.20gb | 2/7 | 20 GB | 3 |
3g.40gb | 3/7 | 40 GB | 2 |
4g.40gb | 4/7 | 40 GB | 1 |
7g.80gb | 7/7 | 80 GB | 1 |
MIG Manager 동작 원리:
- 관리자가 노드에
nvidia.com/mig.config=<profile>라벨 적용 - MIG Manager가 라벨 변경 감지
- 기존 GPU 워크로드 자동 종료 (drain)
nvidia-smi mig명령으로 MIG 인스턴스 생성/삭제- Device Plugin이 새 MIG 인스턴스를 Kubernetes 리소스로 등록
- 완료 후
nvidia.com/mig.config.state=success라벨 업데이트
2.6 Node Feature Discovery (NFD)
**Node Feature Discovery (NFD)**는 Kubernetes 노드의 하드웨어 특성을 자동으로 감지하고 노드 라벨로 등록하는 컴포넌트이다. GPU Operator의 의존성으로, GPU 노드를 식별하는 데 핵심적인 역할을 한다.
NFD가 생성하는 주요 라벨:
| 라벨 | 설명 | 예시 값 |
|---|---|---|
feature.node.kubernetes.io/pci-10de.present | NVIDIA PCI 디바이스 존재 여부 | true |
feature.node.kubernetes.io/cpu-cpuid.AVX512F | CPU AVX-512 지원 | true |
feature.node.kubernetes.io/kernel-version.full | 커널 버전 | 5.15.0-91-generic |
feature.node.kubernetes.io/system-os_release.ID | OS 종류 | ubuntu |
feature.node.kubernetes.io/system-os_release.VERSION_ID | OS 버전 | 22.04 |
GPU Operator는 feature.node.kubernetes.io/pci-10de.present=true 라벨을 통해 NVIDIA GPU가 장착된 노드를 자동으로 식별하고, 해당 노드에만 GPU 관련 DaemonSet을 배포한다.
참고: 클러스터에 이미 NFD가 설치되어 있다면 GPU Operator 설치 시
nfd.enabled=false로 설정하여 중복 배포를 방지해야 한다.
2.7 GPU Feature Discovery (GFD)
**GPU Feature Discovery (GFD)**는 NFD와 유사하지만, GPU 전용 상세 정보를 노드 라벨로 등록하는 역할을 한다. GFD는 NVIDIA Driver와 통신하여 GPU 모델, 드라이버 버전, CUDA 버전 등의 정보를 수집한다.
GFD가 생성하는 주요 라벨:
| 라벨 | 설명 | 예시 값 |
|---|---|---|
nvidia.com/gpu.product | GPU 모델명 | NVIDIA-A100-SXM4-40GB |
nvidia.com/gpu.memory | GPU 메모리 (MiB) | 40960 |
nvidia.com/gpu.count | GPU 개수 | 4 |
nvidia.com/gpu.family | GPU 아키텍처 패밀리 | ampere |
nvidia.com/gpu.compute.major | Compute Capability Major | 8 |
nvidia.com/gpu.compute.minor | Compute Capability Minor | 0 |
nvidia.com/cuda.driver.major | CUDA 드라이버 Major 버전 | 12 |
nvidia.com/cuda.driver.minor | CUDA 드라이버 Minor 버전 | 6 |
nvidia.com/cuda.runtime.major | CUDA Runtime Major 버전 | 12 |
nvidia.com/cuda.runtime.minor | CUDA Runtime Minor 버전 | 6 |
nvidia.com/mig.capable | MIG 지원 여부 | true |
nvidia.com/gpu.replicas | Time-Slicing 레플리카 수 | 4 |
nvidia.com/mig.strategy | MIG 전략 | single |
GFD 라벨 활용 - nodeSelector 예시:
apiVersion: v1
kind: Pod
metadata:
name: a100-workload
spec:
nodeSelector:
nvidia.com/gpu.product: 'NVIDIA-A100-SXM4-40GB'
nvidia.com/gpu.memory: '40960'
containers:
- name: training
image: my-training:latest
resources:
limits:
nvidia.com/gpu: 4
2.8 컴포넌트 관계 다이어그램 및 요약
컴포넌트 배포 순서 (의존성 체인):
NFD (Node Feature Discovery)
└──▶ GPU Feature Discovery (GFD)
└──▶ NVIDIA Driver
└──▶ NVIDIA Container Toolkit
└──▶ NVIDIA Device Plugin
└──▶ DCGM / DCGM Exporter
└──▶ MIG Manager (MIG 지원 GPU만)
└──▶ Validator (검증)
컴포넌트별 역할 요약 테이블:
| 컴포넌트 | DaemonSet 이름 | 역할 | 네임스페이스 |
|---|---|---|---|
| NFD | node-feature-discovery-worker | 노드 하드웨어 라벨링 | gpu-operator |
| GFD | gpu-feature-discovery | GPU 상세 정보 라벨링 | gpu-operator |
| Driver | nvidia-driver-daemonset | GPU 커널 모듈 설치 | gpu-operator |
| Toolkit | nvidia-container-toolkit-daemonset | Container Runtime GPU 연동 | gpu-operator |
| Device Plugin | nvidia-device-plugin-daemonset | GPU 리소스 kubelet 등록 | gpu-operator |
| DCGM | nvidia-dcgm | GPU 메트릭 수집 데몬 | gpu-operator |
| DCGM Exporter | nvidia-dcgm-exporter | Prometheus 메트릭 노출 | gpu-operator |
| MIG Manager | nvidia-mig-manager | MIG 파티션 관리 | gpu-operator |
| Validator | nvidia-operator-validator | 전체 스택 검증 | gpu-operator |
3. 설치 가이드 (Helm 기반)
3.1 사전 요구사항
3.1.1 하드웨어 요구사항
- NVIDIA GPU가 장착된 워커 노드 (Turing 아키텍처 이상 권장)
- PCIe 3.0 이상 슬롯
- IOMMU 지원 (KubeVirt GPU Passthrough 사용 시)
3.1.2 소프트웨어 요구사항
# kubectl 및 helm 설치 확인
kubectl version --client
helm version
# Kubernetes 클러스터 접근 확인
kubectl get nodes
# Container Runtime 확인 (containerd 또는 CRI-O)
kubectl get nodes -o wide
3.1.3 Nouveau 드라이버 비활성화
GPU Operator의 Driver DaemonSet이 NVIDIA 드라이버를 로드하려면, 오픈소스 Nouveau 드라이버가 비활성화되어 있어야 한다.
# nouveau 모듈 로드 여부 확인
lsmod | grep nouveau
# nouveau 비활성화 (필요한 경우)
cat <<EOF | sudo tee /etc/modprobe.d/blacklist-nouveau.conf
blacklist nouveau
options nouveau modeset=0
EOF
# initramfs 재생성
sudo update-initramfs -u
# 재부팅
sudo reboot
참고: GPU Operator v25.x부터는 Driver DaemonSet이 Nouveau 모듈을 자동으로 언로드하려고 시도하지만, 일부 환경에서는 수동 비활성화가 필요할 수 있다.
3.1.4 Pod Security Admission 설정
GPU Operator는 privileged 권한이 필요한 컨테이너를 실행하므로, 네임스페이스에 적절한 PSA 라벨이 필요하다.
# gpu-operator 네임스페이스에 PSA 라벨 설정
kubectl create namespace gpu-operator
kubectl label namespace gpu-operator \
pod-security.kubernetes.io/enforce=privileged
3.2 Helm Repo 추가 및 기본 설치
# NVIDIA Helm repository 추가
helm repo add nvidia https://helm.ngc.nvidia.com/nvidia
helm repo update
# 사용 가능한 버전 확인
helm search repo nvidia/gpu-operator --versions
# 기본 설치 (최신 버전)
helm install gpu-operator \
-n gpu-operator --create-namespace \
nvidia/gpu-operator \
--version=v25.10.1 \
--wait
설치 확인:
# GPU Operator Pod 상태 확인
kubectl get pods -n gpu-operator
# 기대 출력 (정상 상태):
# NAME READY STATUS RESTARTS AGE
# gpu-operator-xxxxx 1/1 Running 0 5m
# gpu-feature-discovery-xxxxx 1/1 Running 0 4m
# nvidia-container-toolkit-daemonset-xxxxx 1/1 Running 0 4m
# nvidia-cuda-validator-xxxxx 0/1 Completed 0 3m
# nvidia-dcgm-exporter-xxxxx 1/1 Running 0 4m
# nvidia-device-plugin-daemonset-xxxxx 1/1 Running 0 4m
# nvidia-driver-daemonset-xxxxx 1/1 Running 0 4m
# nvidia-operator-validator-xxxxx 1/1 Running 0 3m
# node-feature-discovery-gc-xxxxx 1/1 Running 0 5m
# node-feature-discovery-master-xxxxx 1/1 Running 0 5m
# node-feature-discovery-worker-xxxxx 1/1 Running 0 5m
3.3 ClusterPolicy CRD 설정 상세
GPU Operator의 모든 설정은 ClusterPolicy CRD를 통해 관리된다. Helm chart의 values.yaml이 ClusterPolicy를 생성한다.
apiVersion: nvidia.com/v1
kind: ClusterPolicy
metadata:
name: cluster-policy
spec:
# ─────────────────────────────────────────────────────
# 1. NVIDIA Driver 설정
# ─────────────────────────────────────────────────────
driver:
enabled: true
repository: nvcr.io/nvidia
image: driver
version: '560.35.03'
kernelModuleType: auto # auto | precompiled | runcompiled
manager:
env:
- name: ENABLE_AUTO_DRAIN
value: 'true'
- name: DRAIN_USE_FORCE
value: 'false'
- name: DRAIN_POD_SELECTOR_LABEL
value: ''
rdma:
enabled: false
useHostMofed: false
licensingConfig:
nlsEnabled: false
configMapName: ''
# ─────────────────────────────────────────────────────
# 2. NVIDIA Container Toolkit 설정
# ─────────────────────────────────────────────────────
toolkit:
enabled: true
version: v1.17.3-ubuntu22.04
env:
- name: CONTAINERD_CONFIG
value: /etc/containerd/config.toml
- name: CONTAINERD_SOCKET
value: /run/containerd/containerd.sock
# ─────────────────────────────────────────────────────
# 3. CDI (Container Device Interface) 설정
# ─────────────────────────────────────────────────────
cdi:
enabled: true
default: true
# ─────────────────────────────────────────────────────
# 4. Device Plugin 설정
# ─────────────────────────────────────────────────────
devicePlugin:
enabled: true
version: v0.17.0
config:
name: '' # Time-Slicing/MIG ConfigMap 이름
default: '' # 기본 설정 키
env:
- name: PASS_DEVICE_SPECS
value: 'true'
- name: DEVICE_LIST_STRATEGY
value: 'envvar'
# ─────────────────────────────────────────────────────
# 5. DCGM & DCGM Exporter 설정
# ─────────────────────────────────────────────────────
dcgm:
enabled: true
dcgmExporter:
enabled: true
version: '3.3.9-3.6.1-ubuntu22.04'
config:
name: '' # 커스텀 메트릭 ConfigMap
serviceMonitor:
enabled: true
interval: '15s'
# ─────────────────────────────────────────────────────
# 6. MIG Manager 설정
# ─────────────────────────────────────────────────────
migManager:
enabled: true
env:
- name: WITH_REBOOT
value: 'false'
# ─────────────────────────────────────────────────────
# 7. MIG 전략 설정
# ─────────────────────────────────────────────────────
mig:
strategy: single # single | mixed
# ─────────────────────────────────────────────────────
# 8. Node Feature Discovery 설정
# ─────────────────────────────────────────────────────
nodeFeatureDiscovery:
enabled: true
# ─────────────────────────────────────────────────────
# 9. GPU Feature Discovery 설정
# ─────────────────────────────────────────────────────
gfd:
enabled: true
version: v0.17.0
# ─────────────────────────────────────────────────────
# 10. Sandbox Workloads (KubeVirt 연동)
# ─────────────────────────────────────────────────────
sandboxWorkloads:
enabled: false # KubeVirt 사용 시 true
defaultWorkload: container # container | vm-passthrough | vm-vgpu
# ─────────────────────────────────────────────────────
# 11. Validator 설정
# ─────────────────────────────────────────────────────
validator:
plugin:
env:
- name: WITH_WORKLOAD
value: 'true'
3.4 values.yaml 커스터마이징 예제
프로덕션 환경 values.yaml 예시:
# production-values.yaml
# 드라이버가 호스트에 이미 설치된 경우
driver:
enabled: false
# Container Toolkit
toolkit:
enabled: true
# Device Plugin + Time-Slicing 설정
devicePlugin:
config:
name: 'time-slicing-config'
default: 'tesla-t4'
# DCGM Exporter + ServiceMonitor
dcgmExporter:
serviceMonitor:
enabled: true
interval: '15s'
additionalLabels:
release: prometheus
# NFD가 이미 설치된 경우
nfd:
enabled: false
# MIG 설정 (A100/H100 사용 시)
mig:
strategy: mixed
# Node affinity - GPU 노드에만 배포
daemonsets:
tolerations:
- key: nvidia.com/gpu
operator: Exists
effect: NoSchedule
설치 명령어:
helm install gpu-operator \
-n gpu-operator --create-namespace \
nvidia/gpu-operator \
--version=v25.10.1 \
-f production-values.yaml \
--wait
3.5 에어갭(Air-gapped) 환경 설치
인터넷이 차단된 환경에서는 모든 컨테이너 이미지를 Private Registry로 미러링해야 한다.
# 1. 필요한 이미지 목록 확인
helm template gpu-operator nvidia/gpu-operator \
--version=v25.10.1 | grep "image:" | sort -u
# 2. 이미지 미러링 (예: Harbor)
PRIVATE_REGISTRY="harbor.internal.company.com/nvidia"
# 주요 이미지 목록
IMAGES=(
"nvcr.io/nvidia/driver:560.35.03-ubuntu22.04"
"nvcr.io/nvidia/k8s-device-plugin:v0.17.0"
"nvcr.io/nvidia/gpu-feature-discovery:v0.17.0"
"nvcr.io/nvidia/cloud-native/dcgm:3.3.9-1-ubuntu22.04"
"nvcr.io/nvidia/k8s/dcgm-exporter:3.3.9-3.6.1-ubuntu22.04"
"nvcr.io/nvidia/cloud-native/k8s-mig-manager:v0.9.0"
"nvcr.io/nvidia/k8s/container-toolkit:v1.17.3-ubuntu22.04"
"nvcr.io/nvidia/cloud-native/gpu-operator-validator:v25.10.1"
"registry.k8s.io/nfd/node-feature-discovery:v0.16.6"
)
for img in "${IMAGES[@]}"; do
# 이미지 이름 추출
name=$(echo $img | sed 's|.*/||')
docker pull $img
docker tag $img ${PRIVATE_REGISTRY}/${name}
docker push ${PRIVATE_REGISTRY}/${name}
done
# 3. Private Registry를 사용하는 values.yaml 생성
cat <<EOF > airgap-values.yaml
driver:
repository: ${PRIVATE_REGISTRY}
image: driver
version: "560.35.03-ubuntu22.04"
toolkit:
repository: ${PRIVATE_REGISTRY}
devicePlugin:
repository: ${PRIVATE_REGISTRY}
dcgm:
repository: ${PRIVATE_REGISTRY}
dcgmExporter:
repository: ${PRIVATE_REGISTRY}
gfd:
repository: ${PRIVATE_REGISTRY}
migManager:
repository: ${PRIVATE_REGISTRY}
validator:
repository: ${PRIVATE_REGISTRY}
nfd:
image:
repository: ${PRIVATE_REGISTRY}/node-feature-discovery
EOF
# 4. 에어갭 환경 설치
helm install gpu-operator \
-n gpu-operator --create-namespace \
nvidia/gpu-operator \
--version=v25.10.1 \
-f airgap-values.yaml \
--wait
3.6 검증 방법
nvidia-smi Pod 테스트
# nvidia-smi 실행 확인
kubectl run nvidia-smi \
--restart=Never \
--image=nvcr.io/nvidia/cuda:12.6.0-base-ubuntu22.04 \
--overrides='{"spec":{"restartPolicy":"Never","containers":[{"name":"nvidia-smi","image":"nvcr.io/nvidia/cuda:12.6.0-base-ubuntu22.04","command":["nvidia-smi"],"resources":{"limits":{"nvidia.com/gpu":"1"}}}]}}' \
&& kubectl logs nvidia-smi
# 기대 출력:
# +-----------------------------------------------------------------------------------------+
# | NVIDIA-SMI 560.35.03 Driver Version: 560.35.03 CUDA Version: 12.6 |
# |-------------------------------+----------------------+----------------------+
# | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC |
# | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. |
# |===============================+======================+======================|
# | 0 NVIDIA A100-SXM... On | 00000000:00:1E.0 Off | 0 |
# | N/A 32C P0 52W / 400W | 0MiB / 40960MiB | 0% Default |
# +-------------------------------+----------------------+----------------------+
# 정리
kubectl delete pod nvidia-smi
cuda-vectoradd 테스트
# cuda-vectoradd-test.yaml
apiVersion: v1
kind: Pod
metadata:
name: cuda-vectoradd
spec:
restartPolicy: OnFailure
containers:
- name: cuda-vectoradd
image: nvcr.io/nvidia/k8s/cuda-sample:vectoradd-cuda12.5.0-ubuntu22.04
resources:
limits:
nvidia.com/gpu: 1
kubectl apply -f cuda-vectoradd-test.yaml
kubectl logs cuda-vectoradd
# 기대 출력:
# [Vector addition of 50000 elements]
# Copy input data from the host memory to the CUDA device
# CUDA kernel launch with 196 blocks of 256 threads
# Copy output data from the CUDA device to the host memory
# Test PASSED
# Done
kubectl delete pod cuda-vectoradd
노드 GPU 리소스 확인
# 노드별 GPU 리소스 확인
kubectl describe node <gpu-node-name> | grep -A 10 "Capacity:"
# 기대 출력:
# Capacity:
# nvidia.com/gpu: 4
# Allocatable:
# nvidia.com/gpu: 4
# Allocated resources:
# nvidia.com/gpu 0 4
# GPU 관련 라벨 확인
kubectl get node <gpu-node-name> -o json | jq '.metadata.labels | with_entries(select(.key | startswith("nvidia.com")))'
4. GPU 공유 전략
GPU는 비용이 높은 리소스이므로, 여러 워크로드가 하나의 GPU를 공유하는 전략이 중요하다. GPU Operator는 세 가지 GPU 공유 방식을 지원한다.
4.1 Time-Slicing (시분할)
Time-Slicing은 하나의 물리 GPU를 시간 기반으로 분할하여 여러 컨테이너가 공유하게 하는 방식이다. CUDA Time-Slicing 메커니즘을 활용하며, 모든 NVIDIA GPU에서 지원된다.
특징:
- 하드웨어 수준 격리 없음 (메모리 격리 없음)
- GPU 메모리 OOM 위험 존재
- 모든 NVIDIA GPU 지원 (Turing 이상)
- 설정이 간단하고 유연함
설정 방법:
# time-slicing-config.yaml
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
# ConfigMap 생성
kubectl apply -f time-slicing-config.yaml
# ClusterPolicy에 ConfigMap 연결
kubectl patch clusterpolicies.nvidia.com/cluster-policy \
-n gpu-operator --type merge \
-p '{"spec": {"devicePlugin": {"config": {"name": "time-slicing-config", "default": "any"}}}}'
# Device Plugin DaemonSet 재시작 (ConfigMap 변경 반영)
kubectl rollout restart daemonset/nvidia-device-plugin-daemonset -n gpu-operator
결과 확인:
kubectl describe node <gpu-node> | grep nvidia.com/gpu
# Time-Slicing 적용 전 (GPU 4개 노드):
# nvidia.com/gpu: 4
# Time-Slicing 적용 후 (replicas: 4):
# nvidia.com/gpu: 16 (4 GPU x 4 replicas)
4.2 MIG (Multi-Instance GPU)
MIG는 NVIDIA Ampere 이상 아키텍처(A100, A30, H100, H200)에서 지원하는 하드웨어 수준의 GPU 분할 기술이다.
MIG 전략:
| 전략 | 설명 | 사용 사례 |
|---|---|---|
single | 모든 GPU에 동일한 MIG 프로파일 적용 | 균일한 워크로드 |
mixed | 노드별/GPU별 다른 MIG 프로파일 적용 가능 | 다양한 크기의 워크로드 공존 |
MIG 설정 방법:
# 1. GPU Operator 설치 시 MIG 전략 설정
helm install gpu-operator \
-n gpu-operator --create-namespace \
nvidia/gpu-operator \
--version=v25.10.1 \
--set mig.strategy=single
# 2. MIG 프로파일 적용 (노드 라벨)
kubectl label nodes <gpu-node> nvidia.com/mig.config=all-1g.10gb --overwrite
# 3. MIG 설정 상태 확인
kubectl get node <gpu-node> -o jsonpath='{.metadata.labels.nvidia\.com/mig\.config\.state}'
# 출력: success
커스텀 MIG 프로파일 ConfigMap:
apiVersion: v1
kind: ConfigMap
metadata:
name: custom-mig-config
namespace: gpu-operator
data:
config.yaml: |
version: v1
mig-configs:
# MIG 비활성화
all-disabled:
- devices: all
mig-enabled: false
# A100: 7개의 1g.10gb 인스턴스
all-1g.10gb:
- devices: all
mig-enabled: true
mig-devices:
"1g.10gb": 7
# A100: 균형 잡힌 혼합 프로파일
balanced:
- devices: all
mig-enabled: true
mig-devices:
"1g.10gb": 2
"2g.20gb": 1
"3g.20gb": 1
# H100: 추론 최적화 프로파일
h100-inference:
- devices: all
mig-enabled: true
mig-devices:
"1g.10gb": 4
"3g.40gb": 1
MIG 리소스 요청 예시:
apiVersion: v1
kind: Pod
metadata:
name: mig-workload
spec:
containers:
- name: cuda-app
image: nvcr.io/nvidia/cuda:12.6.0-base-ubuntu22.04
command: ['nvidia-smi']
resources:
limits:
nvidia.com/mig-1g.10gb: 1 # MIG 1g.10gb 인스턴스 1개 요청
4.3 vGPU (Virtual GPU)
NVIDIA vGPU는 GPU를 가상화하여 여러 가상 머신에서 공유하는 기술이다. 주로 KubeVirt 가상 머신 환경에서 사용되며, NVIDIA의 별도 라이선스(NVIDIA AI Enterprise 또는 vGPU 라이선스)가 필요하다.
특징:
- 하드웨어 수준 격리 (메모리, 연산)
- VM 환경에 최적화
- 라이선스 비용 발생
- vGPU Manager 설치 필요
4.4 GPU 공유 전략 비교
| 특성 | Time-Slicing | MIG | vGPU |
|---|---|---|---|
| 격리 수준 | 없음 (시분할만) | 하드웨어 (메모리+연산) | 하드웨어 (가상화) |
| 메모리 격리 | X | O | O |
| Fault Isolation | X | O | O |
| 지원 GPU | 모든 NVIDIA GPU | A100, A30, H100, H200 | vGPU 지원 GPU |
| 최대 분할 수 | 설정에 따라 무제한 | GPU별 상이 (최대 7) | GPU별 상이 |
| 성능 오버헤드 | Context Switching | 최소 | 가상화 오버헤드 |
| 라이선스 | 무료 | 무료 | 유료 (NVIDIA AI Enterprise) |
| 설정 복잡도 | 낮음 | 중간 | 높음 |
| 사용 사례 | 개발/테스트, 가벼운 추론 | 프로덕션 추론, 멀티테넌트 | VM 기반 워크로드 |
| QoS 보장 | X | O | O |
5. KubeVirt와 GPU Operator 통합
5.1 KubeVirt 소개
KubeVirt는 Kubernetes 위에서 가상 머신(VM)을 관리할 수 있게 하는 프로젝트이다. 전통적인 VM 워크로드를 Kubernetes의 선언적 관리 체계 안에서 운영할 수 있으며, VirtualMachine과 VirtualMachineInstance라는 Custom Resource를 통해 VM을 관리한다.
KubeVirt와 GPU Operator를 통합하면, 가상 머신에 물리 GPU를 직접 할당(Passthrough)하거나 가상 GPU(vGPU)를 할당할 수 있다. 이는 다음과 같은 시나리오에서 유용하다:
- Windows VM에서 GPU 기반 렌더링/AI 워크로드 실행
- GPU 드라이버가 컨테이너 환경을 지원하지 않는 레거시 애플리케이션
- VM 수준의 보안 격리가 필요한 워크로드
- GPU 기반 VDI (Virtual Desktop Infrastructure)
GPU Operator의 KubeVirt 워크로드 타입:
┌─────────────────────────────────────────────────────────────────┐
│ GPU Operator Workload Types │
│ │
│ ┌──────────────┐ ┌──────────────────┐ ┌──────────────────┐ │
│ │ container │ │ vm-passthrough │ │ vm-vgpu │ │
│ │ (기본값) │ │ │ │ │ │
│ │ │ │ │ │ │ │
│ │ ▪ NVIDIA │ │ ▪ VFIO Manager │ │ ▪ vGPU Manager │ │
│ │ Driver │ │ ▪ Sandbox Device │ │ ▪ vGPU Device │ │
│ │ ▪ Container │ │ Plugin │ │ Manager │ │
│ │ Toolkit │ │ │ │ ▪ Sandbox Device │ │
│ │ ▪ Device │ │ │ │ Plugin │ │
│ │ Plugin │ │ │ │ │ │
│ │ ▪ DCGM │ │ │ │ │ │
│ └──────────────┘ └──────────────────┘ └──────────────────┘ │
│ │
│ nvidia.com/gpu.workload.config=container | vm-passthrough | │
│ vm-vgpu │
└─────────────────────────────────────────────────────────────────┘
중요: 하나의 GPU 워커 노드는 한 가지 타입의 GPU 워크로드만 실행할 수 있다. container, vm-passthrough, vm-vgpu를 동일 노드에서 혼합 실행할 수 없다.
5.2 GPU Passthrough (PCI Passthrough)
GPU Passthrough는 물리 GPU 전체를 KubeVirt 가상 머신에 직접 할당하는 방식이다. VM 내부에서 GPU를 네이티브 성능으로 사용할 수 있지만, GPU 공유는 불가능하다.
5.2.1 Step 1: IOMMU/VT-d 활성화
BIOS 설정:
- Intel: VT-d (Intel Virtualization Technology for Directed I/O) 활성화
- AMD: AMD-Vi / IOMMU 활성화
커널 파라미터 추가:
# Intel CPU
sudo sed -i 's/GRUB_CMDLINE_LINUX="/GRUB_CMDLINE_LINUX="intel_iommu=on iommu=pt /' /etc/default/grub
# AMD CPU
sudo sed -i 's/GRUB_CMDLINE_LINUX="/GRUB_CMDLINE_LINUX="amd_iommu=on iommu=pt /' /etc/default/grub
# GRUB 업데이트 및 재부팅
sudo update-grub
sudo reboot
# IOMMU 활성화 확인
dmesg | grep -i iommu
# 출력 예: DMAR: IOMMU enabled
5.2.2 Step 2: VFIO 드라이버 모듈 로드
# vfio-pci 모듈 로드
sudo modprobe vfio-pci
# 부팅 시 자동 로드 설정
echo "vfio-pci" | sudo tee /etc/modules-load.d/vfio-pci.conf
# 확인
lsmod | grep vfio
5.2.3 Step 3: GPU Operator 설치 (Sandbox Workloads 활성화)
# GPU Operator 설치 시 sandboxWorkloads 활성화
helm install gpu-operator \
-n gpu-operator --create-namespace \
nvidia/gpu-operator \
--version=v25.10.1 \
--set sandboxWorkloads.enabled=true \
--set sandboxWorkloads.defaultWorkload=vm-passthrough
# 또는 기존 설치에 패치
kubectl patch clusterpolicies.nvidia.com/cluster-policy \
-n gpu-operator --type merge \
-p '{"spec": {"sandboxWorkloads": {"enabled": true, "defaultWorkload": "vm-passthrough"}}}'
5.2.4 Step 4: GPU 노드 라벨링
# GPU Passthrough용 워커 노드 라벨링
kubectl label node <gpu-node> \
nvidia.com/gpu.workload.config=vm-passthrough --overwrite
# 라벨 확인
kubectl get node <gpu-node> -o jsonpath='{.metadata.labels.nvidia\.com/gpu\.workload\.config}'
# 출력: vm-passthrough
이 라벨을 적용하면 GPU Operator가 해당 노드에 NVIDIA Driver 대신 VFIO Manager와 Sandbox Device Plugin을 배포한다.
5.2.5 Step 5: GPU PCI ID 확인
# GPU의 PCI Vendor/Device ID 확인
lspci -nn | grep -i nvidia
# 출력 예: 00:1e.0 3D controller [0302]: NVIDIA Corporation GA102GL [A10] [10DE:2236]
# Vendor: 10DE, Device: 2236
# IOMMU Group 확인
find /sys/kernel/iommu_groups/ -type l | sort -t '/' -k5 -n | \
while read line; do
echo "IOMMU Group $(echo $line | awk -F'/' '{print $5}'):"
lspci -nns $(basename $line)
done | grep -A1 NVIDIA
5.2.6 Step 6: KubeVirt CR에 GPU 디바이스 등록
# kubevirt-cr-gpu-passthrough.yaml
apiVersion: kubevirt.io/v1
kind: KubeVirt
metadata:
name: kubevirt
namespace: kubevirt
spec:
configuration:
developerConfiguration:
featureGates:
- GPU
- DisableMDEVConfiguration
permittedHostDevices:
pciHostDevices:
- externalResourceProvider: true
pciVendorSelector: '10DE:2236' # NVIDIA A10
resourceName: nvidia.com/GA102GL_A10
kubectl apply -f kubevirt-cr-gpu-passthrough.yaml
5.2.7 Step 7: VirtualMachine에서 GPU 할당
# vm-gpu-passthrough.yaml
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
name: gpu-vm
namespace: default
spec:
running: true
template:
metadata:
labels:
kubevirt.io/vm: gpu-vm
spec:
domain:
cpu:
cores: 4
memory:
guest: 16Gi
devices:
disks:
- name: rootdisk
disk:
bus: virtio
- name: cloudinitdisk
disk:
bus: virtio
gpus:
- deviceName: nvidia.com/GA102GL_A10
name: gpu1
resources:
requests:
memory: 16Gi
volumes:
- name: rootdisk
dataVolume:
name: ubuntu-dv
- name: cloudinitdisk
cloudInitNoCloud:
userData: |
#cloud-config
password: ubuntu
chpasswd: { expire: false }
ssh_pwauth: true
packages:
- build-essential
- linux-headers-$(uname -r)
runcmd:
- echo "GPU VM is ready"
kubectl apply -f vm-gpu-passthrough.yaml
# VM 상태 확인
kubectl get vmi gpu-vm
# VM 콘솔 접속
virtctl console gpu-vm
# VM 내부에서 GPU 확인 (NVIDIA 드라이버 설치 후)
nvidia-smi
5.2.8 전체 GPU Passthrough 설정 플로우
┌─────────────────────────────────────────────────────────────────┐
│ GPU Passthrough 설정 전체 플로우 │
│ │
│ 1. BIOS: IOMMU/VT-d 활성화 │
│ │ │
│ ▼ │
│ 2. Kernel: intel_iommu=on iommu=pt │
│ │ │
│ ▼ │
│ 3. Module: vfio-pci 로드 │
│ │ │
│ ▼ │
│ 4. GPU Operator: sandboxWorkloads.enabled=true │
│ │ │
│ ▼ │
│ 5. Node Label: nvidia.com/gpu.workload.config=vm-passthrough │
│ │ │
│ ▼ │
│ 6. GPU Operator 자동 배포: │
│ ├── VFIO Manager (GPU를 vfio-pci에 바인딩) │
│ └── Sandbox Device Plugin (GPU 리소스 노출) │
│ │ │
│ ▼ │
│ 7. KubeVirt CR: permittedHostDevices에 GPU 등록 │
│ │ │
│ ▼ │
│ 8. VirtualMachine: spec.domain.devices.gpus 설정 │
│ │ │
│ ▼ │
│ 9. VM 내부: NVIDIA 드라이버 수동 설치 │
│ │ │
│ ▼ │
│ 10. nvidia-smi 확인 및 CUDA 워크로드 실행 │
└─────────────────────────────────────────────────────────────────┘
5.3 vGPU with KubeVirt
vGPU는 하나의 물리 GPU를 여러 개의 가상 GPU로 분할하여 여러 VM에서 공유하는 방식이다. GPU Passthrough와 달리 하나의 GPU를 여러 VM에서 동시에 사용할 수 있다.
5.3.1 사전 요구사항
- NVIDIA AI Enterprise 라이선스 또는 vGPU 라이선스
- vGPU를 지원하는 GPU (A100, A10, A30, A16, L40, L4, T4 등)
- Ampere 이상: SR-IOV 기반 vGPU
- Turing/Volta: NVIDIA vGPU Manager
5.3.2 vGPU Manager 이미지 빌드
NVIDIA vGPU Manager는 라이선스가 필요하여 공개 레지스트리에서 제공되지 않는다. NVIDIA Licensing Portal에서 vGPU 소프트웨어를 다운로드하고 컨테이너 이미지를 직접 빌드해야 한다.
# 1. NVIDIA Licensing Portal에서 vGPU Manager 다운로드
# https://ui.licensing.nvidia.com/software
# 2. vGPU Manager 컨테이너 이미지 빌드
export PRIVATE_REGISTRY="registry.internal.company.com/nvidia"
export VGPU_HOST_DRIVER_VERSION="560.35.06"
export OS_TAG="ubuntu22.04"
# GPU Operator 소스 클론
git clone https://github.com/NVIDIA/gpu-operator.git
cd gpu-operator
# vGPU Manager 이미지 빌드
VGPU_HOST_DRIVER_VERSION=${VGPU_HOST_DRIVER_VERSION} \
IMAGE_NAME=${PRIVATE_REGISTRY}/vgpu-manager \
OS_TAG=${OS_TAG} \
make build-vgpu-manager
# 3. 이미지 Push
docker push ${PRIVATE_REGISTRY}/vgpu-manager:${VGPU_HOST_DRIVER_VERSION}-${OS_TAG}
5.3.3 GPU Operator에 vGPU 설정
# Private Registry 접근을 위한 Secret 생성
kubectl create secret docker-registry vgpu-registry-secret \
-n gpu-operator \
--docker-server=${PRIVATE_REGISTRY} \
--docker-username=<username> \
--docker-password=<password>
# vGPU 지원으로 GPU Operator 설치
helm install gpu-operator \
-n gpu-operator --create-namespace \
nvidia/gpu-operator \
--version=v25.10.1 \
--set sandboxWorkloads.enabled=true \
--set sandboxWorkloads.defaultWorkload=vm-vgpu \
--set vgpuManager.enabled=true \
--set vgpuManager.repository=${PRIVATE_REGISTRY} \
--set vgpuManager.image=vgpu-manager \
--set vgpuManager.version="${VGPU_HOST_DRIVER_VERSION}-${OS_TAG}" \
--set vgpuManager.imagePullSecrets[0]=vgpu-registry-secret
5.3.4 vGPU 타입 설정
# vGPU 노드 라벨 설정
kubectl label node <gpu-node> \
nvidia.com/gpu.workload.config=vm-vgpu --overwrite
# vGPU 프로파일 설정
kubectl label node <gpu-node> \
nvidia.com/vgpu.config=A10-4Q --overwrite
사용 가능한 vGPU 타입 (A10 예시):
| vGPU 타입 | 프레임버퍼 | 최대 인스턴스 | 사용 사례 |
|---|---|---|---|
| A10-1B | 1 GB | 16 | VDI (기본) |
| A10-2B | 2 GB | 8 | VDI (향상) |
| A10-1Q | 1 GB | 16 | 3D 디자인 (기본) |
| A10-2Q | 2 GB | 8 | 3D 디자인 |
| A10-4Q | 4 GB | 4 | AI/ML 추론 |
| A10-6Q | 6 GB | 3 | AI/ML 학습 |
| A10-8Q | 8 GB | 2 | 고성능 AI |
| A10-12Q | 12 GB | 1 | 최대 성능 |
| A10-4C | 4 GB | 4 | CUDA Compute |
| A10-6C | 6 GB | 3 | CUDA Compute |
| A10-8C | 8 GB | 2 | CUDA Compute |
커스텀 vGPU 설정 ConfigMap:
apiVersion: v1
kind: ConfigMap
metadata:
name: vgpu-devices-config
namespace: gpu-operator
data:
config.yaml: |
version: v1
vgpu-configs:
A10-4Q:
- devices: all
vgpu-devices:
"A10-4Q": 4
A10-mixed:
- devices: all
vgpu-devices:
"A10-4Q": 2
"A10-6Q": 1
A10-inference:
- devices: [0, 1]
vgpu-devices:
"A10-4Q": 4
- devices: [2, 3]
vgpu-devices:
"A10-8Q": 2
5.3.5 KubeVirt CR에 vGPU 등록
# kubevirt-cr-vgpu.yaml
apiVersion: kubevirt.io/v1
kind: KubeVirt
metadata:
name: kubevirt
namespace: kubevirt
spec:
configuration:
developerConfiguration:
featureGates:
- GPU
- DisableMDEVConfiguration # GPU Operator가 mdev를 관리하므로 KubeVirt의 mdev 관리 비활성화
permittedHostDevices:
mediatedDevices:
- externalResourceProvider: true
mdevNameSelector: 'NVIDIA A10-4Q'
resourceName: nvidia.com/NVIDIA_A10-4Q
- externalResourceProvider: true
mdevNameSelector: 'NVIDIA A10-6Q'
resourceName: nvidia.com/NVIDIA_A10-6Q
- externalResourceProvider: true
mdevNameSelector: 'NVIDIA A10-8Q'
resourceName: nvidia.com/NVIDIA_A10-8Q
kubectl apply -f kubevirt-cr-vgpu.yaml
5.3.6 VirtualMachine에서 vGPU 할당
# vm-vgpu.yaml
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
name: vgpu-vm
namespace: default
spec:
running: true
template:
metadata:
labels:
kubevirt.io/vm: vgpu-vm
spec:
domain:
cpu:
cores: 4
memory:
guest: 8Gi
devices:
disks:
- name: rootdisk
disk:
bus: virtio
gpus:
- deviceName: nvidia.com/NVIDIA_A10-4Q
name: vgpu1
resources:
requests:
memory: 8Gi
volumes:
- name: rootdisk
dataVolume:
name: ubuntu-dv
5.4 KubeVirt + GPU Operator ClusterPolicy 통합 설정
GPU Passthrough와 vGPU를 모두 지원하는 종합적인 ClusterPolicy 설정:
apiVersion: nvidia.com/v1
kind: ClusterPolicy
metadata:
name: cluster-policy
spec:
# Container 워크로드용 드라이버 (container 노드에 배포)
driver:
enabled: true
version: '560.35.03'
# Sandbox Workloads 활성화 (KubeVirt 연동 핵심)
sandboxWorkloads:
enabled: true
defaultWorkload: container # 기본은 container, 노드 라벨로 오버라이드
# vGPU Manager (vm-vgpu 노드에 배포)
vgpuManager:
enabled: true
repository: 'registry.internal.company.com/nvidia'
image: vgpu-manager
version: '560.35.06-ubuntu22.04'
imagePullSecrets:
- vgpu-registry-secret
# vGPU Device Manager
vgpuDeviceManager:
enabled: true
config:
name: 'vgpu-devices-config'
default: 'A10-4Q'
# VFIO Manager (vm-passthrough 노드에 배포)
vfioManager:
enabled: true
# Sandbox Device Plugin
sandboxDevicePlugin:
enabled: true
# Container 워크로드 공통
toolkit:
enabled: true
devicePlugin:
enabled: true
dcgm:
enabled: true
dcgmExporter:
enabled: true
gfd:
enabled: true
nodeFeatureDiscovery:
enabled: true
노드 라벨링으로 워크로드 타입 지정:
# Container 워크로드용 GPU 노드
kubectl label node gpu-worker-1 nvidia.com/gpu.workload.config=container
# GPU Passthrough용 GPU 노드
kubectl label node gpu-worker-2 nvidia.com/gpu.workload.config=vm-passthrough
# vGPU용 GPU 노드
kubectl label node gpu-worker-3 nvidia.com/gpu.workload.config=vm-vgpu
5.5 VM 내부에서 GPU 사용 확인
GPU Passthrough 또는 vGPU가 할당된 VM 내부에서 NVIDIA 드라이버를 설치하고 GPU 사용을 확인한다.
주의: GPU Operator는 KubeVirt VM 내부에 NVIDIA 드라이버를 자동 설치하지 않는다. VM 내부의 드라이버는 사용자가 직접 설치해야 한다.
# VM 콘솔 접속
virtctl console gpu-vm
# VM 내부에서 NVIDIA 드라이버 설치 (Ubuntu)
sudo apt-get update
sudo apt-get install -y linux-headers-$(uname -r)
# GPU Passthrough의 경우: 데이터센터 드라이버 설치
wget https://us.download.nvidia.com/tesla/560.35.03/NVIDIA-Linux-x86_64-560.35.03.run
sudo bash NVIDIA-Linux-x86_64-560.35.03.run --silent
# vGPU의 경우: vGPU Guest 드라이버 설치 (NVIDIA Licensing Portal에서 다운로드)
sudo bash NVIDIA-Linux-x86_64-560.35.06-grid.run --silent
# GPU 확인
nvidia-smi
# CUDA 워크로드 테스트
sudo apt-get install -y nvidia-cuda-toolkit
cat <<'EOF' > hello_cuda.cu
#include <stdio.h>
__global__ void hello() { printf("Hello from GPU!\n"); }
int main() { hello<<<1,1>>>(); cudaDeviceSynchronize(); return 0; }
EOF
nvcc hello_cuda.cu -o hello_cuda
./hello_cuda
# 출력: Hello from GPU!
5.6 Live Migration with GPU 제약사항
KubeVirt는 VM의 Live Migration(무중단 이전)을 지원하지만, GPU가 할당된 VM에는 다음과 같은 제약이 있다:
| 제약사항 | GPU Passthrough | vGPU |
|---|---|---|
| Live Migration | 지원 안 됨 | 제한적 지원 (NVIDIA vGPU Migration) |
| 원인 | PCIe 디바이스 직접 할당은 이전 불가 | vGPU 상태 전송이 필요 |
| 대안 | Cold Migration (VM 중지 후 이전) | NVIDIA vGPU Migration 라이선스 필요 |
| Node Drain | evictionStrategy 설정 필요 | evictionStrategy 설정 필요 |
# GPU VM의 evictionStrategy 설정
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
name: gpu-vm
spec:
template:
spec:
evictionStrategy: None # GPU VM은 Live Migration 불가이므로 None 또는 External
domain:
devices:
gpus:
- deviceName: nvidia.com/GA102GL_A10
name: gpu1
6. 모니터링 및 Observability
6.1 DCGM Exporter -> Prometheus -> Grafana 파이프라인
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ GPU Node #1 │ │ GPU Node #2 │ │ GPU Node #3 │
│ │ │ │ │ │
│ ┌─────────────┐ │ │ ┌─────────────┐ │ │ ┌─────────────┐ │
│ │DCGM Exporter│ │ │ │DCGM Exporter│ │ │ │DCGM Exporter│ │
│ │ :9400 │ │ │ │ :9400 │ │ │ │ :9400 │ │
│ └──────┬──────┘ │ │ └──────┬──────┘ │ │ └──────┬──────┘ │
└────────┼────────┘ └────────┼────────┘ └────────┼────────┘
│ │ │
└───────────┬───────────┘───────────────────────┘
│
▼
┌──────────────────┐
│ Prometheus │
│ (ServiceMonitor) │
│ scrape :9400 │
└────────┬─────────┘
│
▼
┌──────────────────┐
│ Grafana │
│ Dashboard #12239│
│ (NVIDIA DCGM │
│ Exporter) │
└──────────────────┘
6.2 주요 GPU 메트릭 테이블
| 카테고리 | 메트릭 이름 | 설명 | 타입 | 임계값 (예시) |
|---|---|---|---|---|
| 연산 | DCGM_FI_DEV_GPU_UTIL | GPU 코어 사용률 | gauge | 경고: 90% 초과 |
| 연산 | DCGM_FI_DEV_SM_CLOCK | SM 클럭 주파수 (MHz) | gauge | - |
| 메모리 | DCGM_FI_DEV_MEM_COPY_UTIL | 메모리 대역폭 사용률 | gauge | 경고: 95% 초과 |
| 메모리 | DCGM_FI_DEV_FB_FREE | 사용 가능 프레임버퍼 (MiB) | gauge | 경고: 1024 미만 |
| 메모리 | DCGM_FI_DEV_FB_USED | 사용 중 프레임버퍼 (MiB) | gauge | - |
| 온도 | DCGM_FI_DEV_GPU_TEMP | GPU 온도 (C) | gauge | 경고: 85 초과, 위험: 90 초과 |
| 전력 | DCGM_FI_DEV_POWER_USAGE | 전력 소비 (W) | gauge | 경고: TDP의 90% 초과 |
| 에러 | DCGM_FI_DEV_XID_ERRORS | XID 에러 수 | counter | 경고: 0 초과 |
| 에러 | DCGM_FI_DEV_ECC_SBE_VOL_TOTAL | Single-bit ECC 에러 | counter | 경고: 100 초과 |
| 에러 | DCGM_FI_DEV_ECC_DBE_VOL_TOTAL | Double-bit ECC 에러 | counter | 위험: 0 초과 |
| PCIe | DCGM_FI_DEV_PCIE_TX_THROUGHPUT | PCIe 송신 (KB/s) | gauge | - |
| PCIe | DCGM_FI_DEV_PCIE_RX_THROUGHPUT | PCIe 수신 (KB/s) | gauge | - |
| 인코더 | DCGM_FI_DEV_ENC_UTIL | 인코더 사용률 | gauge | - |
| 디코더 | DCGM_FI_DEV_DEC_UTIL | 디코더 사용률 | gauge | - |
| 프로세스 | DCGM_FI_DEV_GPU_UTIL_SAMPLES | GPU 사용률 샘플 수 | counter | - |
6.3 ServiceMonitor 설정
Prometheus Operator와 연동하기 위한 ServiceMonitor 설정:
# servicemonitor-dcgm.yaml
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: nvidia-dcgm-exporter
namespace: gpu-operator
labels:
app: nvidia-dcgm-exporter
release: prometheus # Prometheus Operator의 serviceMonitorSelector에 맞춰야 함
spec:
selector:
matchLabels:
app: nvidia-dcgm-exporter
namespaceSelector:
matchNames:
- gpu-operator
endpoints:
- port: gpu-metrics
interval: 15s
honorLabels: true
path: /metrics
relabelings:
- sourceLabels: [__meta_kubernetes_pod_node_name]
targetLabel: node
- sourceLabels: [__meta_kubernetes_namespace]
targetLabel: namespace
ClusterPolicy에서 ServiceMonitor 자동 생성:
spec:
dcgmExporter:
enabled: true
serviceMonitor:
enabled: true
interval: '15s'
honorLabels: true
additionalLabels:
release: prometheus # Prometheus Operator 라벨 매칭
6.4 Grafana 대시보드
Grafana에서 NVIDIA DCGM Exporter 공식 대시보드를 사용할 수 있다.
대시보드 Import:
- Grafana 웹 UI 접속
- Dashboards > Import 클릭
- Dashboard ID
12239입력 (NVIDIA DCGM Exporter Dashboard) - Prometheus 데이터 소스 선택
- Import 클릭
대시보드에서 표시되는 주요 패널:
- GPU 사용률 (%) - 시계열 그래프
- GPU 메모리 사용량 (MiB) - 시계열 그래프
- GPU 온도 (C) - 게이지
- 전력 소비 (W) - 시계열 그래프
- PCIe 처리량 - 시계열 그래프
- ECC 에러 카운트 - 카운터 패널
- GPU별 상세 정보 테이블
6.5 Alert 규칙 예제
# gpu-alerts.yaml
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: gpu-alerts
namespace: gpu-operator
labels:
release: prometheus
spec:
groups:
- name: gpu-health
rules:
# GPU 온도 경고 (85도 이상)
- alert: GPUTemperatureHigh
expr: DCGM_FI_DEV_GPU_TEMP > 85
for: 5m
labels:
severity: warning
annotations:
summary: 'GPU 온도 경고 ({{ $labels.gpu }})'
description: >
노드 {{ $labels.node }}의 GPU {{ $labels.gpu }}
온도가 {{ $value }}C입니다. (임계값: 85C)
# GPU 온도 위험 (90도 이상)
- alert: GPUTemperatureCritical
expr: DCGM_FI_DEV_GPU_TEMP > 90
for: 2m
labels:
severity: critical
annotations:
summary: 'GPU 온도 위험 ({{ $labels.gpu }})'
description: >
노드 {{ $labels.node }}의 GPU {{ $labels.gpu }}
온도가 {{ $value }}C입니다. 즉시 확인이 필요합니다.
# GPU 메모리 부족 경고
- alert: GPUMemoryAlmostFull
expr: (DCGM_FI_DEV_FB_USED / (DCGM_FI_DEV_FB_USED + DCGM_FI_DEV_FB_FREE)) * 100 > 95
for: 5m
labels:
severity: warning
annotations:
summary: 'GPU 메모리 부족 ({{ $labels.gpu }})'
description: >
노드 {{ $labels.node }}의 GPU {{ $labels.gpu }}
메모리 사용률이 {{ $value | printf "%.1f" }}%입니다.
# Double-bit ECC 에러 발생 (즉시 경고)
- alert: GPUDoublebitECCError
expr: DCGM_FI_DEV_ECC_DBE_VOL_TOTAL > 0
for: 0m
labels:
severity: critical
annotations:
summary: 'GPU Double-bit ECC 에러 ({{ $labels.gpu }})'
description: >
노드 {{ $labels.node }}의 GPU {{ $labels.gpu }}에서
교정 불가능한 Double-bit ECC 에러가 감지되었습니다.
GPU 하드웨어 교체를 검토하세요.
# GPU 사용률 장기 과부하
- alert: GPUHighUtilization
expr: DCGM_FI_DEV_GPU_UTIL > 95
for: 30m
labels:
severity: warning
annotations:
summary: 'GPU 장기 과부하 ({{ $labels.gpu }})'
description: >
노드 {{ $labels.node }}의 GPU {{ $labels.gpu }}가
30분 이상 95% 이상 사용률을 유지하고 있습니다.
# XID 에러 발생
- alert: GPUXidError
expr: increase(DCGM_FI_DEV_XID_ERRORS[5m]) > 0
for: 0m
labels:
severity: warning
annotations:
summary: 'GPU XID 에러 발생 ({{ $labels.gpu }})'
description: >
노드 {{ $labels.node }}의 GPU {{ $labels.gpu }}에서
XID 에러가 발생했습니다. dmesg 로그를 확인하세요.
- name: gpu-operator-health
rules:
# GPU Operator Pod 비정상
- alert: GPUOperatorPodNotReady
expr: |
kube_pod_status_ready{namespace="gpu-operator", condition="true"} == 0
for: 10m
labels:
severity: warning
annotations:
summary: 'GPU Operator Pod 비정상'
description: >
GPU Operator 네임스페이스의 {{ $labels.pod }}
Pod이 10분 이상 Ready 상태가 아닙니다.
kubectl apply -f gpu-alerts.yaml
7. 프로덕션 배포 베스트 프랙티스
7.1 Node Labeling 전략 (GPU 노드 vs CPU 노드)
프로덕션 환경에서는 GPU 노드와 CPU 노드를 명확히 구분하여 관리해야 한다.
# GPU 노드 라벨링
kubectl label node gpu-worker-{1..4} \
node-role.kubernetes.io/gpu-worker=""
# GPU 용도별 라벨링
kubectl label node gpu-worker-1 gpu-workload=training
kubectl label node gpu-worker-2 gpu-workload=training
kubectl label node gpu-worker-3 gpu-workload=inference
kubectl label node gpu-worker-4 gpu-workload=inference
# GPU 세대별 라벨링 (GFD가 자동으로 하지만, 커스텀 라벨도 유용)
kubectl label node gpu-worker-1 gpu-tier=high # A100/H100
kubectl label node gpu-worker-3 gpu-tier=standard # T4/L4
7.2 Taints & Tolerations
GPU 노드에 Taint를 설정하여 GPU 워크로드만 스케줄링되도록 한다.
# GPU 노드에 Taint 적용
kubectl taint nodes gpu-worker-{1..4} \
nvidia.com/gpu=present:NoSchedule
GPU 워크로드 Pod에 Toleration 추가:
apiVersion: v1
kind: Pod
metadata:
name: gpu-training
spec:
tolerations:
- key: nvidia.com/gpu
operator: Equal
value: present
effect: NoSchedule
nodeSelector:
nvidia.com/gpu.product: 'NVIDIA-A100-SXM4-40GB'
containers:
- name: training
image: my-training:latest
resources:
limits:
nvidia.com/gpu: 4
7.3 ResourceQuota로 GPU 할당량 제한
네임스페이스별로 GPU 사용량을 제한한다.
# gpu-resourcequota.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: gpu-quota
namespace: ml-team-a
spec:
hard:
requests.nvidia.com/gpu: '8' # 최대 GPU 8개 요청 가능
limits.nvidia.com/gpu: '8' # 최대 GPU 8개 제한
pods: '20' # 최대 Pod 20개
---
apiVersion: v1
kind: ResourceQuota
metadata:
name: gpu-quota
namespace: ml-team-b
spec:
hard:
requests.nvidia.com/gpu: '4'
limits.nvidia.com/gpu: '4'
pods: '10'
kubectl apply -f gpu-resourcequota.yaml
# 할당량 확인
kubectl get resourcequota -n ml-team-a
# NAME AGE REQUEST LIMIT
# gpu-quota 1m requests.nvidia.com/gpu: 2/8 limits.nvidia.com/gpu: 2/8
7.4 PriorityClass 설정
GPU 리소스 부족 시 우선순위가 낮은 워크로드를 Preemption(선점)하기 위해 PriorityClass를 설정한다.
# gpu-priority-classes.yaml
# 프로덕션 학습 작업 (최고 우선순위)
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: gpu-production-training
value: 1000000
globalDefault: false
description: '프로덕션 GPU 학습 워크로드'
---
# 프로덕션 추론 서비스
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: gpu-production-inference
value: 900000
globalDefault: false
description: '프로덕션 GPU 추론 서비스'
---
# 개발/실험 워크로드 (낮은 우선순위)
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: gpu-development
value: 100000
globalDefault: false
preemptionPolicy: Never # 다른 Pod을 선점하지 않음
description: '개발/실험 GPU 워크로드'
# PriorityClass 사용 예시
apiVersion: v1
kind: Pod
metadata:
name: important-training
spec:
priorityClassName: gpu-production-training
containers:
- name: training
image: my-training:latest
resources:
limits:
nvidia.com/gpu: 4
7.5 드라이버 업그레이드 전략
GPU Operator는 드라이버 업그레이드를 위한 Rolling Update를 지원한다.
# 1. 현재 드라이버 버전 확인
kubectl get clusterpolicy cluster-policy -o jsonpath='{.spec.driver.version}'
# 2. 드라이버 버전 업그레이드
kubectl patch clusterpolicies.nvidia.com/cluster-policy \
--type merge \
-p '{"spec": {"driver": {"version": "565.57.01"}}}'
# 3. 업그레이드 진행 상태 확인
kubectl get pods -n gpu-operator -l app=nvidia-driver-daemonset -w
# 4. 노드별 업그레이드 완료 확인
kubectl get nodes -o custom-columns=\
'NAME:.metadata.name,DRIVER:.metadata.labels.nvidia\.com/cuda\.driver\.major'
업그레이드 시 주의사항:
ENABLE_AUTO_DRAIN=true설정 시 드라이버 업그레이드 전 자동으로 노드를 드레인한다- 프로덕션 환경에서는 한 번에 한 노드씩 업그레이드하도록
maxUnavailable: 1을 설정한다 - 업그레이드 전 GPU 워크로드의 Checkpoint/저장 상태를 확인한다
7.6 Multi-GPU 노드 관리
DGX 같은 Multi-GPU 서버에서는 NVIDIA Fabric Manager와 NVLink/NVSwitch 설정도 고려해야 한다.
# Multi-GPU 노드 스케줄링을 위한 Topology 인식
apiVersion: v1
kind: Pod
metadata:
name: multi-gpu-training
spec:
containers:
- name: training
image: nvcr.io/nvidia/pytorch:24.05-py3
env:
- name: NVIDIA_VISIBLE_DEVICES
value: 'all'
- name: NCCL_P2P_LEVEL
value: 'NVL' # NVLink 사용
- name: NCCL_TOPO_DUMP_FILE
value: '/tmp/nccl_topo.xml'
resources:
limits:
nvidia.com/gpu: 8 # 8-GPU 학습
8. 트러블슈팅 가이드
8.1 GPU not detected (드라이버 로딩 실패)
증상: nvidia-driver-daemonset Pod이 CrashLoopBackOff 또는 Error 상태
# 1. Driver Pod 로그 확인
kubectl logs -n gpu-operator -l app=nvidia-driver-daemonset --tail=100
# 2. Nouveau 모듈 충돌 확인
kubectl exec -n gpu-operator -it <driver-pod> -- lsmod | grep nouveau
# 해결: nouveau 블랙리스트
cat <<EOF | sudo tee /etc/modprobe.d/blacklist-nouveau.conf
blacklist nouveau
options nouveau modeset=0
EOF
sudo update-initramfs -u && sudo reboot
# 3. 커널 헤더 누락 확인
kubectl logs -n gpu-operator <driver-pod> | grep "kernel headers"
# 해결: 커널 헤더 설치
sudo apt-get install -y linux-headers-$(uname -r)
# 4. dmesg에서 GPU 관련 에러 확인
dmesg | grep -i "NVRM\|nvidia\|Xid"
# 5. GPU 하드웨어 인식 확인
lspci | grep -i nvidia
8.2 nvidia-smi not found in container
증상: 컨테이너 내부에서 nvidia-smi 명령어를 찾을 수 없음
# 1. Container Toolkit Pod 상태 확인
kubectl get pods -n gpu-operator -l app=nvidia-container-toolkit-daemonset
# 2. Device Plugin Pod 상태 확인
kubectl get pods -n gpu-operator -l app=nvidia-device-plugin-daemonset
# 3. 노드의 GPU 리소스 확인
kubectl describe node <node> | grep "nvidia.com/gpu"
# nvidia.com/gpu가 0이면 Device Plugin 문제
# 4. Pod의 GPU 리소스 요청 확인
kubectl get pod <pod-name> -o yaml | grep -A5 resources
# limits에 nvidia.com/gpu가 있는지 확인
# 5. CDI 설정 확인
kubectl exec -n gpu-operator -it <toolkit-pod> -- \
ls /var/run/cdi/
8.3 CUDA version mismatch
증상: CUDA 애플리케이션 실행 시 "CUDA driver version is insufficient" 에러
# 1. 드라이버의 CUDA 지원 버전 확인
kubectl exec -n gpu-operator -it <driver-pod> -- nvidia-smi
# 출력의 "CUDA Version" 확인
# 2. 컨테이너 이미지의 CUDA 버전 확인
kubectl exec -it <app-pod> -- nvcc --version
# 3. 호환성 확인
# 드라이버 CUDA 버전 >= 애플리케이션 CUDA 버전이어야 함
# 예: 드라이버 CUDA 12.6 >= 애플리케이션 CUDA 12.4 (OK)
# 드라이버 CUDA 12.2 < 애플리케이션 CUDA 12.6 (FAIL)
# 해결: 드라이버 업그레이드 또는 애플리케이션 CUDA 버전 다운그레이드
8.4 MIG partition 실패
증상: nvidia.com/mig.config.state=failed 라벨
# 1. MIG Manager 로그 확인
kubectl logs -n gpu-operator -l app=nvidia-mig-manager --tail=100
# 2. MIG 상태 확인 (노드에서)
nvidia-smi mig -lgi
nvidia-smi mig -lci
# 3. GPU에서 실행 중인 프로세스 확인
nvidia-smi pmon -s u -d 1 -c 1
# 4. MIG 모드 활성화 확인
nvidia-smi -i 0 --query-gpu=mig.mode.current --format=csv
# "Enabled"여야 함
# 5. MIG 설정 재시도
kubectl label node <node> nvidia.com/mig.config=all-disabled --overwrite
# 잠시 대기 후
kubectl label node <node> nvidia.com/mig.config=all-1g.10gb --overwrite
# 6. 리부트가 필요한 경우 (특히 클라우드 환경)
# ClusterPolicy에서 WITH_REBOOT=true 설정
kubectl patch clusterpolicies.nvidia.com/cluster-policy \
--type merge \
-p '{"spec":{"migManager":{"env":[{"name":"WITH_REBOOT","value":"true"}]}}}'
8.5 KubeVirt VM에서 GPU 인식 안 됨
증상: VM 내부에서 lspci | grep NVIDIA 출력이 없음
# 1. 노드 워크로드 라벨 확인
kubectl get node <node> -o jsonpath='{.metadata.labels.nvidia\.com/gpu\.workload\.config}'
# vm-passthrough 또는 vm-vgpu여야 함
# 2. VFIO Manager 또는 vGPU Manager 상태 확인
kubectl get pods -n gpu-operator | grep -E "vfio|vgpu"
# 3. Sandbox Device Plugin 상태 확인
kubectl get pods -n gpu-operator -l app=nvidia-sandbox-device-plugin-daemonset
# 4. 노드의 GPU 리소스 확인
kubectl describe node <node> | grep nvidia.com
# nvidia.com/GA102GL_A10 또는 nvidia.com/NVIDIA_A10-4Q 등이 있어야 함
# 5. KubeVirt CR의 permittedHostDevices 확인
kubectl get kubevirt kubevirt -n kubevirt -o yaml | grep -A20 permittedHostDevices
# 6. VMI 상태 확인
kubectl describe vmi <vm-name>
# Events에 GPU 할당 관련 에러 확인
# 7. IOMMU 그룹 확인 (Passthrough의 경우)
# IOMMU 그룹 내 모든 디바이스가 vfio-pci에 바인딩되어야 함
ls /sys/kernel/iommu_groups/*/devices/
8.6 DCGM Exporter 메트릭 누락
증상: Prometheus에서 DCGM 메트릭이 수집되지 않음
# 1. DCGM Exporter Pod 상태 확인
kubectl get pods -n gpu-operator -l app=nvidia-dcgm-exporter
# 2. DCGM Exporter 메트릭 직접 확인
kubectl port-forward -n gpu-operator svc/nvidia-dcgm-exporter 9400:9400
curl http://localhost:9400/metrics | head -50
# 3. ServiceMonitor 확인
kubectl get servicemonitor -n gpu-operator
kubectl describe servicemonitor nvidia-dcgm-exporter -n gpu-operator
# 4. Prometheus 타겟 확인
# Prometheus UI > Status > Targets에서 dcgm-exporter 타겟 확인
# 상태가 "DOWN"이면 네트워크 또는 라벨 매칭 문제
# 5. ServiceMonitor 라벨이 Prometheus의 serviceMonitorSelector와 일치하는지 확인
kubectl get prometheus -n monitoring -o yaml | grep -A5 serviceMonitorSelector
# 6. DCGM Exporter 로그 확인
kubectl logs -n gpu-operator -l app=nvidia-dcgm-exporter --tail=50
8.7 진단 명령어 모음
# ═══════════════════════════════════════════════════════════
# GPU Operator 전체 상태 점검 스크립트
# ═══════════════════════════════════════════════════════════
echo "=== 1. GPU Operator Pod 상태 ==="
kubectl get pods -n gpu-operator -o wide
echo ""
echo "=== 2. ClusterPolicy 상태 ==="
kubectl get clusterpolicy -o jsonpath='{.items[0].status.state}'
echo ""
echo ""
echo "=== 3. GPU 노드 라벨 ==="
kubectl get nodes -o custom-columns=\
'NAME:.metadata.name,GPU_PRESENT:.metadata.labels.feature\.node\.kubernetes\.io/pci-10de\.present,GPU_PRODUCT:.metadata.labels.nvidia\.com/gpu\.product,GPU_COUNT:.metadata.labels.nvidia\.com/gpu\.count,GPU_MEMORY:.metadata.labels.nvidia\.com/gpu\.memory,MIG_CONFIG:.metadata.labels.nvidia\.com/mig\.config,WORKLOAD:.metadata.labels.nvidia\.com/gpu\.workload\.config'
echo ""
echo "=== 4. GPU 리소스 할당 상태 ==="
kubectl describe nodes | grep -A6 "nvidia.com/gpu"
echo ""
echo "=== 5. Driver DaemonSet 상태 ==="
kubectl get ds -n gpu-operator nvidia-driver-daemonset -o wide 2>/dev/null || echo "Driver DaemonSet not found"
echo ""
echo "=== 6. 문제 있는 Pod 확인 ==="
kubectl get pods -n gpu-operator --field-selector=status.phase!=Running,status.phase!=Succeeded
echo ""
echo "=== 7. 최근 이벤트 ==="
kubectl get events -n gpu-operator --sort-by='.lastTimestamp' | tail -20
echo ""
echo "=== 8. Validator 로그 ==="
kubectl logs -n gpu-operator -l app=nvidia-operator-validator --tail=20 2>/dev/null
echo ""
echo "=== 9. ClusterPolicy 전체 설정 ==="
kubectl get clusterpolicy cluster-policy -o yaml
개별 컴포넌트 디버깅:
# Driver 디버깅
kubectl logs -n gpu-operator -l app=nvidia-driver-daemonset -c nvidia-driver-ctr --tail=100
# Toolkit 디버깅
kubectl logs -n gpu-operator -l app=nvidia-container-toolkit-daemonset --tail=100
# Device Plugin 디버깅
kubectl logs -n gpu-operator -l app=nvidia-device-plugin-daemonset --tail=100
# DCGM Exporter 디버깅
kubectl logs -n gpu-operator -l app=nvidia-dcgm-exporter --tail=100
# MIG Manager 디버깅
kubectl logs -n gpu-operator -l app=nvidia-mig-manager --tail=100
# Validator 디버깅
kubectl logs -n gpu-operator -l app=nvidia-operator-validator --tail=100
# VFIO Manager 디버깅 (KubeVirt Passthrough)
kubectl logs -n gpu-operator -l app=nvidia-vfio-manager --tail=100
# vGPU Manager 디버깅
kubectl logs -n gpu-operator -l app=nvidia-vgpu-manager-daemonset --tail=100
9. 참고 자료 (References)
공식 문서
| 리소스 | URL |
|---|---|
| NVIDIA GPU Operator 공식 문서 | https://docs.nvidia.com/datacenter/cloud-native/gpu-operator/latest/ |
| GPU Operator 설치 가이드 | https://docs.nvidia.com/datacenter/cloud-native/gpu-operator/latest/getting-started.html |
| GPU Operator with KubeVirt | https://docs.nvidia.com/datacenter/cloud-native/gpu-operator/latest/gpu-operator-kubevirt.html |
| GPU Time-Slicing 가이드 | https://docs.nvidia.com/datacenter/cloud-native/gpu-operator/latest/gpu-sharing.html |
| GPU Operator MIG 가이드 | https://docs.nvidia.com/datacenter/cloud-native/gpu-operator/latest/gpu-operator-mig.html |
| GPU Operator 트러블슈팅 | https://docs.nvidia.com/datacenter/cloud-native/gpu-operator/latest/troubleshooting.html |
| NVIDIA DCGM Exporter | https://github.com/NVIDIA/dcgm-exporter |
| NVIDIA MIG User Guide | https://docs.nvidia.com/datacenter/tesla/mig-user-guide/index.html |
KubeVirt 관련
| 리소스 | URL |
|---|---|
| KubeVirt 공식 문서 | https://kubevirt.io/user-guide/ |
| KubeVirt Host Devices | https://kubevirt.io/user-guide/compute/host-devices/ |
| KubeVirt GPU Device Plugin | https://github.com/NVIDIA/kubevirt-gpu-device-plugin |
추가 리소스
| 리소스 | URL |
|---|---|
| GPU Operator GitHub | https://github.com/NVIDIA/gpu-operator |
| NVIDIA NGC GPU Operator Helm Chart | https://catalog.ngc.nvidia.com/orgs/nvidia/helm-charts/gpu-operator |
| DCGM Exporter Grafana Dashboard | https://grafana.com/grafana/dashboards/12239 |
| NVIDIA GPU Telemetry 문서 | https://docs.nvidia.com/datacenter/cloud-native/gpu-telemetry/latest/ |
| GPU Operator Platform Support | https://docs.nvidia.com/datacenter/cloud-native/gpu-operator/latest/platform-support.html |