Skip to content

Split View: GPU Operator × KubeVirt 총정리 — 구성요소·설정·버전, 부분 MIG와 수동 MIG까지

|

GPU Operator × KubeVirt 총정리 — 구성요소·설정·버전, 부분 MIG와 수동 MIG까지

들어가며 — 컨테이너의 GPU, VM의 GPU

쿠버네티스 위의 GPU 인프라는 두 세계로 나뉩니다. 컨테이너에 GPU를 꽂는 세계(GPU Operator)와, 쿠버네티스에서 가상 머신을 돌리며 GPU를 통째로 넘겨주는 세계(KubeVirt)입니다. 재미있는 것은 이 둘이 결국 하나의 스택으로 만난다는 점입니다 — GPU Operator가 KubeVirt VM용 GPU 프로비저닝까지 담당합니다. 이 글은 두 기둥의 구성요소·설정·버전을 총정리하고, 자주 묻는 두 가지 — 일부 GPU에만 MIG 적용MIG 수동 조작 — 를 실전 명령어로 다룹니다. GPU Operator 설치와 MIG 기본편을 먼저 읽으면 이 글이 두 배로 쉬워집니다.

1부 — GPU Operator: 구성요소·설정·버전

구성요소 (오퍼랜드)

GPU Operator는 "GPU 노드에 필요한 모든 것"을 데몬셋 오퍼랜드로 배포하고 ClusterPolicy 하나로 조정하는 오퍼레이터입니다.

오퍼랜드                     역할
─────────────────────────  ─────────────────────────────────────
driver                     NVIDIA 드라이버를 컨테이너로 로드
container-toolkit          런타임이 GPU를 컨테이너에 노출하게 설정
device-plugin              nvidia.com/gpu 리소스를 스케줄러에 광고
gpu-feature-discovery      GPU 모델·메모리·MIG 상태를 노드 라벨로
dcgm-exporter              사용률·온도·전력을 프로메테우스 메트릭으로
mig-manager                노드 라벨 기반 MIG 파티셔닝
node-feature-discovery     하드웨어 감지 (의존 컴포넌트)
validator                  각 단계 검증 잡
(sandbox 계열)             vfio-manager, vgpu-device-manager,
                           kubevirt-gpu-device-plugin — 5부에서

설정 — ClusterPolicy가 단일 진실

모든 오퍼랜드의 설정은 clusterpolicies.nvidia.com/cluster-policy CR 하나에 모입니다. Helm의 --set은 결국 이 CR의 필드를 채우는 것입니다. 실무에서 자주 만지는 필드:

# ClusterPolicy 주요 필드 (발췌)
spec:
  driver:
    enabled: true          # 노드에 드라이버가 이미 있으면 false
    version: "580.65.06"   # 드라이버 버전 고정
  toolkit:
    enabled: true
  mig:
    strategy: mixed        # single | mixed
  migManager:
    enabled: true
    config:
      name: custom-mig-config   # 커스텀 MIG 프로필 ConfigMap
    env:
      - name: WITH_REBOOT       # CSP처럼 재부팅이 필요한 환경
        value: "true"
  devicePlugin:
    config:
      name: time-slicing-config # 시분할 설정도 ConfigMap으로
  sandboxWorkloads:
    enabled: false         # KubeVirt 연동 시 true (5부)

수정은 Helm 업그레이드 또는 kubectl patch clusterpolicies...로 하며, 오퍼레이터가 변경을 감지해 해당 오퍼랜드만 재구성합니다.

버전 체계

GPU Operator는 연도 기반 버전(vYY.N.패치)을 씁니다 — 이 글 기준 최신 계열은 v26.x(예: v26.3.3)이고, 그 앞으로 v25.x, v24.9, v23.9 계열이 있습니다. 각 릴리스는 지원하는 드라이버 버전 묶음·쿠버네티스 버전 범위가 문서에 명시되므로, 업그레이드 전 호환성 매트릭스 확인이 필수입니다. 기억할 원칙: 오퍼레이터 버전이 드라이버 버전을 관리하므로, 드라이버만 따로 올리고 싶다면 ClusterPolicy의 driver.version을 쓰는 것이 정석입니다.

2부 — 일부 GPU에만 MIG 적용하기

8-GPU 노드에서 "0번 GPU만 잘게 쪼개 추론용으로, 나머지 7장은 통짜로 학습용으로" 쓰고 싶다는 요구는 아주 흔합니다. 답은 mixed 전략 + 커스텀 MIG 설정입니다.

apiVersion: v1
kind: ConfigMap
metadata:
  name: custom-mig-config
  namespace: gpu-operator
data:
  config.yaml: |
    version: v1
    mig-configs:
      # 0번 GPU만 MIG, 1~7번은 그대로
      partial-mig:
        - devices: [0]
          mig-enabled: true
          mig-devices:
            "1g.10gb": 4
            "3g.40gb": 1
        - devices: [1, 2, 3, 4, 5, 6, 7]
          mig-enabled: false
# ① ClusterPolicy가 이 ConfigMap을 보도록 지정 (이미 설정했다면 생략)
kubectl patch clusterpolicies.nvidia.com/cluster-policy --type='json' \
  -p='[{"op":"replace","path":"/spec/migManager/config/name","value":"custom-mig-config"}]'

# ② 전략이 mixed인지 확인 — 프로필이 섞이므로 single로는 표현 불가
kubectl patch clusterpolicies.nvidia.com/cluster-policy --type='json' \
  -p='[{"op":"replace","path":"/spec/mig/strategy","value":"mixed"}]'

# ③ 노드에 프로필 적용
kubectl label nodes <노드> nvidia.com/mig.config=partial-mig --overwrite

# ④ 결과: 리소스가 이렇게 광고됩니다
#   nvidia.com/gpu: 7                ← MIG 안 한 7장
#   nvidia.com/mig-1g.10gb: 4        ← 0번에서 나온 조각들
#   nvidia.com/mig-3g.40gb: 1

파드는 용도에 따라 nvidia.com/gpu(통짜) 또는 nvidia.com/mig-1g.10gb(조각)를 요청하면 됩니다. 핵심 규칙 두 가지 — 프로필이 GPU 간에 다르면 반드시 mixed 전략이어야 하고, devices 목록에 없는 GPU의 동작을 명시하려면 mig-enabled: false 항목을 꼭 함께 적어야 합니다(암묵 상태에 맡기지 마세요).

3부 — MIG 수동 적용: nvidia-smi로 직접 조작하기

쿠버네티스 밖의 베어메탈 서버, 또는 mig-manager를 쓰지 않는 환경에서는 nvidia-smi mig로 직접 파티셔닝합니다. GPU Operator가 내부에서 하는 일이 바로 이것이므로, 한 번 손으로 해 보면 오퍼레이터 디버깅 실력도 함께 늡니다.

# ① MIG 모드 켜기 (GPU 0번만) — 대상 GPU의 프로세스를 먼저 비워야 함
sudo nvidia-smi -i 0 -mig 1
# "Pending" 이 뜨면 GPU 리셋 또는 재부팅 필요:
sudo nvidia-smi --gpu-reset -i 0

# ② 만들 수 있는 GPU 인스턴스(GI) 프로필 확인
nvidia-smi mig -lgip
#  예: H100 80GB → 1g.10gb(ID 19), 2g.20gb(14), 3g.40gb(9), 7g.80gb(0) ...

# ③ GI 생성 — 3g.40gb 하나 + 1g.10gb 네 개, -C 는 컴퓨트 인스턴스(CI)까지 자동 생성
sudo nvidia-smi mig -i 0 -cgi 9,19,19,19,19 -C

# ④ 확인
nvidia-smi mig -lgi        # 생성된 GI 목록
nvidia-smi -L              # MIG 장치 UUID 목록 (MIG-xxxx 형식)

# ⑤ 특정 인스턴스에서 실행 — UUID로 지정
CUDA_VISIBLE_DEVICES=MIG-<uuid> python infer.py

# ⑥ 해제 — CI → GI 순서로 삭제 후 MIG 모드 끄기
sudo nvidia-smi mig -i 0 -dci && sudo nvidia-smi mig -i 0 -dgi
sudo nvidia-smi -i 0 -mig 0

알아둘 개념: MIG는 GI(GPU Instance — 메모리·SM의 하드웨어 분할) 안에 CI(Compute Instance — SM의 재분할) 가 들어가는 2단 구조입니다. 대부분의 경우 GI당 CI 하나(-C 옵션)면 충분하고, CI를 더 쪼개는 것은 같은 메모리 파티션을 공유하며 연산만 나누고 싶은 특수한 경우입니다. 그리고 ②의 프로필 ID는 GPU 모델마다 다르므로 항상 -lgip로 먼저 확인하세요.

4부 — KubeVirt: 구성요소·설정·버전

왜 쿠버네티스에서 VM인가

컨테이너로 못 옮기는 워크로드는 생각보다 많습니다 — 커널 모듈이 필요한 레거시, Windows 게스트, 강한 격리가 필요한 멀티테넌트 GPU 환경. KubeVirt는 VM을 쿠버네티스의 일급 시민(CRD)으로 만들어, 파드와 VM을 같은 클러스터·같은 네트워크·같은 kubectl로 다루게 해 줍니다.

4대 컴포넌트

컴포넌트          형태          역할
──────────────  ───────────  ─────────────────────────────────────
virt-operator    Deployment   KubeVirt 자체의 설치·업그레이드 관리
virt-controller  Deployment   클러스터 수준 VM 라이프사이클 (VMI 생성 등)
virt-handler     DaemonSet    노드 수준 데몬 — VMI 스펙과 libvirt 도메인 동기화
virt-launcher    Pod(VM당 1)  VM을 감싸는 파드 — 내부의 libvirtd가 QEMU/KVM 구동

흐름은 이렇습니다: 사용자가 VirtualMachine CR을 만들면 → virt-controller가 VirtualMachineInstance(VMI)와 virt-launcher 파드를 만들고 → 해당 노드의 virt-handler가 VMI 스펙을 libvirt 도메인으로 번역해 → virt-launcher 안의 libvirtd가 QEMU/KVM 프로세스를 띄웁니다. VM이 곧 파드 안의 프로세스이므로 쿠버네티스 네트워킹·스케줄링이 그대로 적용됩니다. 디스크 이미지 가져오기는 별도 프로젝트 CDI(Containerized Data Importer) 가 DataVolume CRD로 담당합니다.

설정 — KubeVirt CR과 featureGates

KubeVirt의 전역 설정도 CR 하나(kubevirt.io/v1KubeVirt)에 모입니다. GPU 패스스루에 필요한 핵심 설정:

apiVersion: kubevirt.io/v1
kind: KubeVirt
metadata:
  name: kubevirt
  namespace: kubevirt
spec:
  configuration:
    developerConfiguration:
      featureGates:
        - GPU                 # VM에 GPU 할당 허용
        - HostDevices
    permittedHostDevices:     # 어떤 호스트 장치를 VM에 넘길 수 있는가
      pciHostDevices:
        - pciVendorSelector: "10de:2331"     # NVIDIA H100 (vendor:device)
          resourceName: "nvidia.com/GH100_H100_PCIE"
          externalResourceProvider: true     # GPU Operator의 플러그인이 광고

버전 특징

KubeVirt는 2023년 v1.0으로 프로덕션 준비를 선언했고, 이후 분기별 마이너 릴리스(v1.1, v1.2, …)로 v1.x대를 이어가고 있습니다. CNCF 인큐베이팅 프로젝트로, 릴리스마다 지원하는 쿠버네티스 버전 범위가 명시됩니다(대체로 최신 K8s 3개 버전). 체감 변화의 축은 instancetype/preference API의 성숙(VM 크기를 티셔츠 사이즈처럼 선언), 메모리 핫플러그·CPU 핫플러그 같은 라이브 리소스 조정, 그리고 라이브 마이그레이션의 견고화입니다. GPU 패스스루된 VM은 장치가 노드에 물리적으로 묶이므로 라이브 마이그레이션이 안 된다는 제약은 버전과 무관한 물리 법칙으로 기억해 두세요.

5부 — 두 세계의 연결: GPU Operator × KubeVirt

GPU Operator는 sandboxWorkloads.enabled=true로 설치하면 VM용 GPU 프로비저닝까지 담당합니다.

helm install --wait gpu-operator \
  -n gpu-operator --create-namespace \
  nvidia/gpu-operator --version=v26.3.3 \
  --set sandboxWorkloads.enabled=true

이때 노드 라벨 nvidia.com/gpu.workload.config가 스위치가 됩니다:

값               노드의 용도            깔리는 오퍼랜드
──────────────  ────────────────────  ─────────────────────────────
container        일반 GPU 컨테이너      driver, device-plugin, ... (1부 구성)
vm-passthrough   VM에 GPU 통째로       vfio-manager (vfio-pci 바인딩),
                                       kubevirt-gpu-device-plugin
vm-vgpu          VM에 vGPU 조각        vgpu-manager, vgpu-device-manager

패스스루 노드에서는 vfio-manager가 GPU를 vfio-pci 드라이버에 바인딩하고(호스트 드라이버 대신), kubevirt-gpu-device-plugin이 그 장치를 nvidia.com/GH100_H100_PCIE 같은 리소스로 광고합니다. VM 스펙에서는 이렇게 요청합니다:

# VirtualMachine 스펙 발췌
spec:
  template:
    spec:
      domain:
        devices:
          gpus:
            - deviceName: nvidia.com/GH100_H100_PCIE
              name: gpu1

정리하면 — 같은 클러스터에서 라벨만 바꿔 어떤 노드는 컨테이너 GPU, 어떤 노드는 VM 패스스루, 어떤 노드는 vGPU로 운영할 수 있습니다. 강한 격리(보안·드라이버 자유)가 필요하면 VM 패스스루, 밀도가 필요하면 컨테이너 + MIG, 그 중간이 vGPU라는 감각으로 고르면 됩니다.

마치며

GPU Operator는 ClusterPolicy 하나로 오퍼랜드 함대를 지휘하고, KubeVirt는 4개 컴포넌트로 VM을 파드의 세계에 편입시키며, 둘은 sandboxWorkloads와 workload.config 라벨에서 만납니다. 부분 MIG는 mixed 전략 + devices 목록으로, 수동 MIG는 nvidia-smi mig -cgi/-dgi로 — 오퍼레이터가 자동화해 주는 일의 정체를 알면, 장애가 났을 때 어디를 봐야 할지도 보입니다. 쿠버네티스 기초 감각은 쿠버네티스 놀이터쿠버스트로넛 퀴즈에서 다질 수 있습니다.

참고 자료

GPU Operator × KubeVirt Complete Guide — Components, Configuration, Versions, Partial MIG, and Manual MIG

Introduction — GPUs for Containers, GPUs for VMs

GPU infrastructure on Kubernetes is split into two worlds: the one that plugs GPUs into containers (GPU Operator), and the one that runs virtual machines on Kubernetes and hands them a GPU wholesale (KubeVirt). The interesting part is that the two eventually meet in a single stack — the GPU Operator also takes care of GPU provisioning for KubeVirt VMs. This post is a complete rundown of both pillars — components, configuration, and versions — and covers two frequently asked topics with hands-on commands: applying MIG to only some GPUs and operating MIG manually. Reading the GPU Operator installation and MIG basics guide first will make this post twice as easy.

Part 1 — GPU Operator: Components, Configuration, Versions

Components (Operands)

The GPU Operator deploys "everything a GPU node needs" as DaemonSet operands and coordinates them all through a single ClusterPolicy.

Operand                    Role
─────────────────────────  ─────────────────────────────────────
driver                     Loads the NVIDIA driver as a container
container-toolkit          Configures the runtime to expose GPUs to containers
device-plugin              Advertises the nvidia.com/gpu resource to the scheduler
gpu-feature-discovery      Turns GPU model, memory, and MIG state into node labels
dcgm-exporter              Exports utilization, temperature, and power as Prometheus metrics
mig-manager                Node-label-driven MIG partitioning
node-feature-discovery     Hardware detection (dependency component)
validator                  Validation jobs for each stage
(sandbox family)           vfio-manager, vgpu-device-manager,
                           kubevirt-gpu-device-plugin — see Part 5

Configuration — ClusterPolicy Is the Single Source of Truth

Every operand's configuration converges on a single CR: clusterpolicies.nvidia.com/cluster-policy. Helm's --set flags ultimately just fill in fields of this CR. The fields you touch most often in practice:

# Key ClusterPolicy fields (excerpt)
spec:
  driver:
    enabled: true          # false if the driver is already on the node
    version: "580.65.06"   # pin the driver version
  toolkit:
    enabled: true
  mig:
    strategy: mixed        # single | mixed
  migManager:
    enabled: true
    config:
      name: custom-mig-config   # custom MIG profile ConfigMap
    env:
      - name: WITH_REBOOT       # environments that require a reboot, e.g. CSPs
        value: "true"
  devicePlugin:
    config:
      name: time-slicing-config # time-slicing settings also live in a ConfigMap
  sandboxWorkloads:
    enabled: false         # true for KubeVirt integration (Part 5)

Changes are made through a Helm upgrade or kubectl patch clusterpolicies..., and the operator detects them and reconfigures only the affected operands.

Versioning Scheme

The GPU Operator uses year-based versions (vYY.N.patch) — as of this writing the newest line is v26.x (e.g. v26.3.3), with the v25.x, v24.9, and v23.9 lines before it. Each release documents the exact bundle of supported driver versions and the supported Kubernetes range, so checking the compatibility matrix before an upgrade is a must. The principle to remember: the operator version manages the driver version, so if you want to bump only the driver, the proper lever is driver.version in the ClusterPolicy.

Part 2 — Applying MIG to Only Some GPUs

On an 8-GPU node, "slice only GPU 0 into small pieces for inference and keep the other seven whole for training" is a very common requirement. The answer is the mixed strategy plus a custom MIG config.

apiVersion: v1
kind: ConfigMap
metadata:
  name: custom-mig-config
  namespace: gpu-operator
data:
  config.yaml: |
    version: v1
    mig-configs:
      # MIG on GPU 0 only; GPUs 1-7 stay as they are
      partial-mig:
        - devices: [0]
          mig-enabled: true
          mig-devices:
            "1g.10gb": 4
            "3g.40gb": 1
        - devices: [1, 2, 3, 4, 5, 6, 7]
          mig-enabled: false
# ① Point the ClusterPolicy at this ConfigMap (skip if already configured)
kubectl patch clusterpolicies.nvidia.com/cluster-policy --type='json' \
  -p='[{"op":"replace","path":"/spec/migManager/config/name","value":"custom-mig-config"}]'

# ② Make sure the strategy is mixed — profiles vary per GPU, so single cannot express this
kubectl patch clusterpolicies.nvidia.com/cluster-policy --type='json' \
  -p='[{"op":"replace","path":"/spec/mig/strategy","value":"mixed"}]'

# ③ Apply the profile to the node
kubectl label nodes <node> nvidia.com/mig.config=partial-mig --overwrite

# ④ Result: resources are advertised like this
#   nvidia.com/gpu: 7                ← the 7 GPUs without MIG
#   nvidia.com/mig-1g.10gb: 4        ← slices carved out of GPU 0
#   nvidia.com/mig-3g.40gb: 1

Pods then request either nvidia.com/gpu (a whole GPU) or nvidia.com/mig-1g.10gb (a slice), depending on their purpose. Two core rules — whenever profiles differ between GPUs, the strategy must be mixed, and if you want the behavior of GPUs missing from a devices list to be explicit, always add a mig-enabled: false entry for them (do not leave it to implicit state).

Part 3 — Manual MIG: Working Directly with nvidia-smi

On bare-metal servers outside Kubernetes, or in environments that do not use mig-manager, you partition directly with nvidia-smi mig. This is exactly what the GPU Operator does under the hood, so doing it by hand once also sharpens your operator-debugging skills.

# ① Enable MIG mode (GPU 0 only) — drain processes from the target GPU first
sudo nvidia-smi -i 0 -mig 1
# If "Pending" appears, a GPU reset or reboot is required:
sudo nvidia-smi --gpu-reset -i 0

# ② Check which GPU instance (GI) profiles can be created
nvidia-smi mig -lgip
#  e.g. H100 80GB → 1g.10gb(ID 19), 2g.20gb(14), 3g.40gb(9), 7g.80gb(0) ...

# ③ Create GIs — one 3g.40gb plus four 1g.10gb; -C also creates the compute instances (CIs)
sudo nvidia-smi mig -i 0 -cgi 9,19,19,19,19 -C

# ④ Verify
nvidia-smi mig -lgi        # list the created GIs
nvidia-smi -L              # list MIG device UUIDs (MIG-xxxx format)

# ⑤ Run on a specific instance — target it by UUID
CUDA_VISIBLE_DEVICES=MIG-<uuid> python infer.py

# ⑥ Tear down — delete CIs, then GIs, then disable MIG mode
sudo nvidia-smi mig -i 0 -dci && sudo nvidia-smi mig -i 0 -dgi
sudo nvidia-smi -i 0 -mig 0

Concepts to know: MIG is a two-tier structure in which a GI (GPU Instance — a hardware partition of memory and SMs) contains CIs (Compute Instances — a further subdivision of the SMs). In most cases one CI per GI (the -C flag) is enough; splitting CIs further is for the special case where workloads share the same memory partition and divide only the compute. Also, the profile IDs in step ② differ per GPU model, so always check with -lgip first.

Part 4 — KubeVirt: Components, Configuration, Versions

Why VMs on Kubernetes

More workloads resist containerization than you might think — legacy systems that need kernel modules, Windows guests, multi-tenant GPU environments that demand strong isolation. KubeVirt makes VMs first-class citizens (CRDs) of Kubernetes, letting you handle pods and VMs with the same cluster, the same network, and the same kubectl.

The Four Components

Component        Form            Role
───────────────  ──────────────  ─────────────────────────────────────
virt-operator    Deployment      Installs and upgrades KubeVirt itself
virt-controller  Deployment      Cluster-level VM lifecycle (creates VMIs, etc.)
virt-handler     DaemonSet       Node-level daemon — syncs VMI specs with libvirt domains
virt-launcher    Pod (1 per VM)  The pod wrapping the VM — its libvirtd runs QEMU/KVM

The flow goes like this: a user creates a VirtualMachine CR → virt-controller creates a VirtualMachineInstance (VMI) and a virt-launcher pod → virt-handler on that node translates the VMI spec into a libvirt domain → libvirtd inside virt-launcher starts the QEMU/KVM process. The VM is literally a process inside a pod, so Kubernetes networking and scheduling apply as-is. Importing disk images is handled by a separate project, CDI (Containerized Data Importer), through the DataVolume CRD.

Configuration — the KubeVirt CR and featureGates

KubeVirt's global configuration also converges on a single CR (the KubeVirt resource in kubevirt.io/v1). The key settings needed for GPU passthrough:

apiVersion: kubevirt.io/v1
kind: KubeVirt
metadata:
  name: kubevirt
  namespace: kubevirt
spec:
  configuration:
    developerConfiguration:
      featureGates:
        - GPU                 # allow assigning GPUs to VMs
        - HostDevices
    permittedHostDevices:     # which host devices may be handed to VMs
      pciHostDevices:
        - pciVendorSelector: "10de:2331"     # NVIDIA H100 (vendor:device)
          resourceName: "nvidia.com/GH100_H100_PCIE"
          externalResourceProvider: true     # advertised by the GPU Operator plugin

Version Highlights

KubeVirt declared production readiness with v1.0 in 2023 and has continued the v1.x line with quarterly minor releases (v1.1, v1.2, ...). It is a CNCF incubating project, and each release specifies the range of Kubernetes versions it supports (generally the three most recent). The changes you actually feel are the maturing instancetype/preference API (declaring VM sizes like t-shirt sizes), live resource adjustment such as memory hotplug and CPU hotplug, and ever more robust live migration. A VM with a passed-through GPU is physically bound to its node, so live migration does not work for it — remember that as a law of physics, independent of any version.

Part 5 — Bridging the Two Worlds: GPU Operator × KubeVirt

Install the GPU Operator with sandboxWorkloads.enabled=true and it also takes charge of GPU provisioning for VMs.

helm install --wait gpu-operator \
  -n gpu-operator --create-namespace \
  nvidia/gpu-operator --version=v26.3.3 \
  --set sandboxWorkloads.enabled=true

The node label nvidia.com/gpu.workload.config then becomes the switch:

Value            Node purpose             Operands deployed
──────────────  ───────────────────────  ─────────────────────────────
container        Regular GPU containers   driver, device-plugin, ... (the Part 1 set)
vm-passthrough   Whole GPU to a VM        vfio-manager (binds vfio-pci),
                                          kubevirt-gpu-device-plugin
vm-vgpu          vGPU slices to a VM      vgpu-manager, vgpu-device-manager

On a passthrough node, vfio-manager binds the GPU to the vfio-pci driver (instead of the host driver), and kubevirt-gpu-device-plugin advertises that device as a resource like nvidia.com/GH100_H100_PCIE. The VM spec then requests it like this:

# VirtualMachine spec excerpt
spec:
  template:
    spec:
      domain:
        devices:
          gpus:
            - deviceName: nvidia.com/GH100_H100_PCIE
              name: gpu1

To sum up — within a single cluster, just by switching labels, some nodes can serve container GPUs, some VM passthrough, and some vGPU. If you need strong isolation (security, driver freedom), go with VM passthrough; if you need density, go with containers plus MIG; vGPU sits in between.

Closing Thoughts

The GPU Operator commands its fleet of operands through a single ClusterPolicy, KubeVirt brings VMs into the world of pods with four components, and the two meet at sandboxWorkloads and the workload.config label. Partial MIG is the mixed strategy plus a devices list; manual MIG is nvidia-smi mig -cgi/-dgi. Once you know what the operator is actually automating for you, you also know where to look when something breaks. You can build up your Kubernetes fundamentals with the Kubernetes Playground and the Kubestronaut Quiz.

References