Skip to content
Published on

NVIDIA GPU Operator 완벽 가이드: 구성요소, 설치, KubeVirt GPU 패스스루까지 총정리

Authors
  • Name
    Twitter

1. GPU Operator 소개

1.1 GPU Operator란?

NVIDIA GPU Operator는 Kubernetes 클러스터에서 GPU를 활용하기 위해 필요한 모든 소프트웨어 컴포넌트의 설치, 설정, 관리를 자동화하는 Kubernetes Operator이다. Kubernetes의 Operator Framework를 기반으로, GPU 워크로드 실행에 필요한 드라이버, 런타임, 디바이스 플러그인, 모니터링 도구 등을 Day-0 프로비저닝부터 Day-2 운영까지 일관되게 관리한다.

전통적으로 Kubernetes에서 GPU를 사용하려면 다음과 같은 작업을 각 노드마다 수동으로 수행해야 했다:

  1. NVIDIA 드라이버 설치 (커널 버전에 맞는 정확한 버전)
  2. NVIDIA Container Toolkit 설치 및 Container Runtime 설정
  3. NVIDIA Device Plugin 배포
  4. 모니터링 도구 (DCGM Exporter) 설치
  5. 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버전
Ubuntu20.04, 22.04, 24.04 LTS
Red Hat Enterprise Linux8.x, 9.x
CentOS Stream8, 9
Rocky Linux8.x, 9.x
SUSE Linux Enterprise15 SP4+

지원 GPU:

GPU 세대모델 예시MIG 지원
TuringT4, RTX 2080X
AmpereA100, A30, A10, A2O (A100, A30)
HopperH100, H200O
Ada LovelaceL40, L40S, L4X
BlackwellB100, B200, GB200O

지원 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-compiledRun-compiled
빌드 시간없음 (이미 빌드됨)노드에서 10-20분 소요
커널 호환성특정 커널 버전에 매칭모든 커널 버전 지원
노드 부팅 시간빠름느림
지원 OSUbuntu (주로)대부분의 Linux
설정kernelModuleType: precompiledkernelModuleType: 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 리소스를 요청할 수 있게 된다.

동작 흐름:

  1. Device Plugin이 kubelet의 Device Plugin gRPC 인터페이스에 등록
  2. 노드에 있는 GPU 개수를 kubelet에 보고
  3. Kubernetes Scheduler가 nvidia.com/gpu 리소스 요청이 있는 Pod을 해당 노드에 스케줄링
  4. 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.5gbMIG 1g.5gb 인스턴스A100 MIG 파티션
nvidia.com/mig-2g.10gbMIG 2g.10gb 인스턴스A100 MIG 파티션
nvidia.com/mig-3g.20gbMIG 3g.20gb 인스턴스A100 MIG 파티션
nvidia.com/mig-7g.40gbMIG 7g.40gb 인스턴스A100 전체 MIG
nvidia.com/gpu.sharedTime-Slicing 공유 GPUrenameByDefault 활성화 시

2.4 NVIDIA DCGM & DCGM Exporter

**DCGM (Data Center GPU Manager)**은 NVIDIA GPU의 상태와 성능을 모니터링하기 위한 도구이며, DCGM Exporter는 이 메트릭을 Prometheus 포맷으로 노출하는 Exporter이다.

주요 수집 메트릭:

메트릭 이름설명단위
DCGM_FI_DEV_GPU_UTILGPU 코어 사용률%
DCGM_FI_DEV_MEM_COPY_UTIL메모리 대역폭 사용률%
DCGM_FI_DEV_GPU_TEMPGPU 온도C
DCGM_FI_DEV_POWER_USAGE전력 소비량W
DCGM_FI_DEV_FB_FREE사용 가능한 프레임버퍼 메모리MiB
DCGM_FI_DEV_FB_USED사용 중인 프레임버퍼 메모리MiB
DCGM_FI_DEV_SM_CLOCKSM 클럭 주파수MHz
DCGM_FI_DEV_MEM_CLOCK메모리 클럭 주파수MHz
DCGM_FI_DEV_ENC_UTIL인코더 사용률%
DCGM_FI_DEV_DEC_UTIL디코더 사용률%
DCGM_FI_DEV_PCIE_TX_THROUGHPUTPCIe 송신 처리량KB/s
DCGM_FI_DEV_PCIE_RX_THROUGHPUTPCIe 수신 처리량KB/s
DCGM_FI_DEV_XID_ERRORSXID 에러 발생 횟수count
DCGM_FI_DEV_ECC_SBE_VOL_TOTALSingle-bit ECC 에러 (일시적)count
DCGM_FI_DEV_ECC_DBE_VOL_TOTALDouble-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.5gb1/75 GB7
1g.5gb+me1/75 GB (+MPS)1
1g.10gb1/710 GB4
2g.10gb2/710 GB3
3g.20gb3/720 GB2
4g.20gb4/720 GB1
7g.40gb7/740 GB1

H100 80GB MIG 프로파일:

프로파일GPU 슬라이스메모리최대 인스턴스 수
1g.10gb1/710 GB7
1g.20gb1/720 GB4
2g.20gb2/720 GB3
3g.40gb3/740 GB2
4g.40gb4/740 GB1
7g.80gb7/780 GB1

MIG Manager 동작 원리:

  1. 관리자가 노드에 nvidia.com/mig.config=<profile> 라벨 적용
  2. MIG Manager가 라벨 변경 감지
  3. 기존 GPU 워크로드 자동 종료 (drain)
  4. nvidia-smi mig 명령으로 MIG 인스턴스 생성/삭제
  5. Device Plugin이 새 MIG 인스턴스를 Kubernetes 리소스로 등록
  6. 완료 후 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.presentNVIDIA PCI 디바이스 존재 여부true
feature.node.kubernetes.io/cpu-cpuid.AVX512FCPU AVX-512 지원true
feature.node.kubernetes.io/kernel-version.full커널 버전5.15.0-91-generic
feature.node.kubernetes.io/system-os_release.IDOS 종류ubuntu
feature.node.kubernetes.io/system-os_release.VERSION_IDOS 버전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.productGPU 모델명NVIDIA-A100-SXM4-40GB
nvidia.com/gpu.memoryGPU 메모리 (MiB)40960
nvidia.com/gpu.countGPU 개수4
nvidia.com/gpu.familyGPU 아키텍처 패밀리ampere
nvidia.com/gpu.compute.majorCompute Capability Major8
nvidia.com/gpu.compute.minorCompute Capability Minor0
nvidia.com/cuda.driver.majorCUDA 드라이버 Major 버전12
nvidia.com/cuda.driver.minorCUDA 드라이버 Minor 버전6
nvidia.com/cuda.runtime.majorCUDA Runtime Major 버전12
nvidia.com/cuda.runtime.minorCUDA Runtime Minor 버전6
nvidia.com/mig.capableMIG 지원 여부true
nvidia.com/gpu.replicasTime-Slicing 레플리카 수4
nvidia.com/mig.strategyMIG 전략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 이름역할네임스페이스
NFDnode-feature-discovery-worker노드 하드웨어 라벨링gpu-operator
GFDgpu-feature-discoveryGPU 상세 정보 라벨링gpu-operator
Drivernvidia-driver-daemonsetGPU 커널 모듈 설치gpu-operator
Toolkitnvidia-container-toolkit-daemonsetContainer Runtime GPU 연동gpu-operator
Device Pluginnvidia-device-plugin-daemonsetGPU 리소스 kubelet 등록gpu-operator
DCGMnvidia-dcgmGPU 메트릭 수집 데몬gpu-operator
DCGM Exporternvidia-dcgm-exporterPrometheus 메트릭 노출gpu-operator
MIG Managernvidia-mig-managerMIG 파티션 관리gpu-operator
Validatornvidia-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-SlicingMIGvGPU
격리 수준없음 (시분할만)하드웨어 (메모리+연산)하드웨어 (가상화)
메모리 격리XOO
Fault IsolationXOO
지원 GPU모든 NVIDIA GPUA100, A30, H100, H200vGPU 지원 GPU
최대 분할 수설정에 따라 무제한GPU별 상이 (최대 7)GPU별 상이
성능 오버헤드Context Switching최소가상화 오버헤드
라이선스무료무료유료 (NVIDIA AI Enterprise)
설정 복잡도낮음중간높음
사용 사례개발/테스트, 가벼운 추론프로덕션 추론, 멀티테넌트VM 기반 워크로드
QoS 보장XOO

5. KubeVirt와 GPU Operator 통합

5.1 KubeVirt 소개

KubeVirt는 Kubernetes 위에서 가상 머신(VM)을 관리할 수 있게 하는 프로젝트이다. 전통적인 VM 워크로드를 Kubernetes의 선언적 관리 체계 안에서 운영할 수 있으며, VirtualMachineVirtualMachineInstance라는 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 ManagerSandbox 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-1B1 GB16VDI (기본)
A10-2B2 GB8VDI (향상)
A10-1Q1 GB163D 디자인 (기본)
A10-2Q2 GB83D 디자인
A10-4Q4 GB4AI/ML 추론
A10-6Q6 GB3AI/ML 학습
A10-8Q8 GB2고성능 AI
A10-12Q12 GB1최대 성능
A10-4C4 GB4CUDA Compute
A10-6C6 GB3CUDA Compute
A10-8C8 GB2CUDA 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 PassthroughvGPU
Live Migration지원 안 됨제한적 지원 (NVIDIA vGPU Migration)
원인PCIe 디바이스 직접 할당은 이전 불가vGPU 상태 전송이 필요
대안Cold Migration (VM 중지 후 이전)NVIDIA vGPU Migration 라이선스 필요
Node DrainevictionStrategy 설정 필요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          └────────┬─────────┘
          ┌──────────────────┐
GrafanaDashboard #12239           (NVIDIA DCGMExporter)          └──────────────────┘

6.2 주요 GPU 메트릭 테이블

카테고리메트릭 이름설명타입임계값 (예시)
연산DCGM_FI_DEV_GPU_UTILGPU 코어 사용률gauge경고: 90% 초과
연산DCGM_FI_DEV_SM_CLOCKSM 클럭 주파수 (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_TEMPGPU 온도 (C)gauge경고: 85 초과, 위험: 90 초과
전력DCGM_FI_DEV_POWER_USAGE전력 소비 (W)gauge경고: TDP의 90% 초과
에러DCGM_FI_DEV_XID_ERRORSXID 에러 수counter경고: 0 초과
에러DCGM_FI_DEV_ECC_SBE_VOL_TOTALSingle-bit ECC 에러counter경고: 100 초과
에러DCGM_FI_DEV_ECC_DBE_VOL_TOTALDouble-bit ECC 에러counter위험: 0 초과
PCIeDCGM_FI_DEV_PCIE_TX_THROUGHPUTPCIe 송신 (KB/s)gauge-
PCIeDCGM_FI_DEV_PCIE_RX_THROUGHPUTPCIe 수신 (KB/s)gauge-
인코더DCGM_FI_DEV_ENC_UTIL인코더 사용률gauge-
디코더DCGM_FI_DEV_DEC_UTIL디코더 사용률gauge-
프로세스DCGM_FI_DEV_GPU_UTIL_SAMPLESGPU 사용률 샘플 수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:

  1. Grafana 웹 UI 접속
  2. Dashboards > Import 클릭
  3. Dashboard ID 12239 입력 (NVIDIA DCGM Exporter Dashboard)
  4. Prometheus 데이터 소스 선택
  5. 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)

공식 문서

KubeVirt 관련

추가 리소스