HAMi + NVIDIA GPU Operator Coexistence Validation - Lesson 6 Part C¶
✅ STATUS: VALIDATED - captured on a real NVIDIA L40 (48 GB), 2026-07-18. The NVIDIA GPU Operator (device plugin disabled) and HAMi ran on one k3s node without fighting over
nvidia.com/gpu: the Operator owned the base stack and telemetry, HAMi owned the device plugin, and two pods shared the one card with the slice enforced by HAMi-core. Evidence: real command output fromcapture-evidence.sh(artifact files cited per row). Lab:hami-gpu-operator-coexistence/.
The claim this report backs: HAMi and the NVIDIA GPU Operator run on one node without fighting
over nvidia.com/gpu, with the Operator owning the base stack and HAMi owning the device
plugin.
Environment¶
| Item | Value |
|---|---|
| Date | 2026-07-18 |
| Machine | GPU VM (keen-galileo), Ubuntu 22.04.5 LTS, kernel 6.8.0-40-generic |
| GPU | NVIDIA L40, 48 GB (49140 MiB), UUID GPU-d109b6c4-8e03-c41e-faa1-822812575879; Ada Lovelace, no MIG - software sharing is the only option (the HAMi premise) |
| Driver | 535.183.06 (CUDA 12.4), from the VM image (not the Operator: driver.enabled=false) |
| Kubernetes | k3s v1.36.2+k3s1, containerd 2.3.2-k3s2, default-runtime: nvidia (k3s --default-runtime flag) |
| GPU Operator | v26.3.3, installed with driver.enabled=false, toolkit.enabled=false, devicePlugin.enabled=false (the base stack + DCGM/NFD/validator, minus the device plugin) |
| HAMi | 2.9.0, kube-scheduler sidecar pointed at registry.k8s.io (chart default is an Aliyun mirror that times out outside China); deviceSplitCount 10 (default) |
The driver came from the VM image, so the Operator ran with
driver.enabled=falseandtoolkit.enabled=false. A production cluster where the Operator owns the driver is a different configuration, and the reboot behaviour below is the part that would differ.
Validation checklist (6 artifacts)¶
| # | Claim | Pass criteria | Result | Evidence |
|---|---|---|---|---|
| 1 | Operator components run, its device plugin does not | Operator pods Running; no device-plugin pod in the namespace | ✅ GFD, NFD (master/worker/gc), operator, DCGM Exporter, operator-validator all Running; cuda-validator Completed; device-plugin grep returned none | 1-operator-pods.txt |
| 2 | The device plugin is disabled deliberately | devicePlugin.enabled=false in the released helm values / ClusterPolicy |
✅ helm user-supplied values show devicePlugin.enabled=false (also driver/toolkit false); ClusterPolicy devicePlugin.enabled=false |
2-operator-helm-values.txt |
| 3 | HAMi owns the device-plugin role | HAMi pods Running; nvidia.com/gpu allocatable at HAMi's virtual count; hami.io/node-nvidia-register present |
✅ hami-device-plugin 2/2 + hami-scheduler 2/2 Running; nvidia.com/gpu = 10 (1 card × split 10); register annotation devmem:49140, devcore:100, type:"NVIDIA L40", mode:"hami-core" |
3-hami-pods.txt, 3-node-allocatable.txt |
| 4 | nvidia is the default containerd runtime | default_runtime_name = "nvidia" in the generated containerd config |
✅ config.yaml: default-runtime: nvidia, and generated config.toml has default_runtime_name = "nvidia" |
4-default-runtime.txt |
| 5 | Two pods share one GPU, enforced | both pods Running on the same card; scheduled by the HAMi scheduler; each pod's in-pod nvidia-smi shows its slice, not the full card |
✅ hami-coexist-a + -b both Running on keen-galileo, both allocated the same GPU-d109b6c4-…; scheduled by hami-scheduler (FilteringSucceed, BindingSucceed); each in-pod nvidia-smi reports 0MiB / 4000MiB, not the 49140 MiB card; HAMi-core injected: CUDA_DEVICE_MEMORY_LIMIT_0=4000m, libvgpu.so present |
5-share-pods.txt, 5-in-pod-smi-hami-coexist-a.txt, -b.txt, 5-hami-core.txt |
| 6 | DCGM is unaffected by HAMi | DCGM Exporter still reports physical DCGM_FI_* counters alongside HAMi |
✅ DCGM reports the physical card for GPU-d109b6c4-…: DCGM_FI_DEV_FB_FREE = 48439 MiB (the full ~48 GB), while the pods each see a 4000 MiB slice |
6-dcgm-metrics.txt |
The two results that matter most¶
- Artifact 3 is the coexistence proof.
nvidia.com/gpucame back as10, HAMi's virtual count (one card ×deviceSplitCount10), not1. That means HAMi's device plugin won the role and the Operator's is genuinely out of the way. A value of1would have meant the Operator's plugin was still running and the setup was wrong. - Artifact 5 proves it is not merely cosmetic. Two pods co-resident on one card is the
sharing half (stock Kubernetes hands the whole device to the first pod); each pod's in-pod
nvidia-smireporting0MiB / 4000MiBinstead of the 49140 MiB card is the enforcement half. Both pods carry the same GPU UUID in their allocation annotation, so they really are on one physical device, andCUDA_DEVICE_MEMORY_LIMIT_0=4000mshows HAMi-core enforcing the cap (it is injected becausenvidiais the default runtime, Artifact 4).
Cross-check across artifacts: the same UUID
GPU-d109b6c4-…appears in the HAMi register annotation (Artifact 3), both pods' allocation annotations and in-pod views (Artifact 5), and DCGM's physical counters (Artifact 6). One physical L40, seen three ways: as ten schedulable HAMi slices, as two 4000 MiB in-pod caps, and as one ~48 GB card in DCGM. That is coexistence.
The reboot behaviour¶
⚠️ Only reproducible where the Operator owns the driver (
driver.enabled=true). On this VM the driver came from the image (driver.enabled=false), so the Operator does not reinstall it on boot.
| Question | Result |
|---|---|
| Configuration tested | Driver from the VM image (driver.enabled=false), not Operator-managed |
| Did HAMi's device-plugin pod CrashLoopBackOff after a reboot? | Not applicable to this configuration - reboot not exercised; the Operator does not reload the driver here, so the race cannot occur |
| Time from install to the share pods Running | Both pods Running within seconds of apply (AGE 4s in 5-share-pods.txt) |
Still to validate: the Operator-managed-driver case (
driver.enabled=true), where the reboot race in HAMi #136 / #157 can occur. This run does not cover it. Upstream discussion: #1708.
What this proves¶
A clean single-node coexistence: the Operator managing the base stack and telemetry (driver
off, but DCGM/GFD/NFD/validator all Running), HAMi managing fractional device allocation, one
device plugin (HAMi's) owning nvidia.com/gpu, two pods sharing the card, and the slice
enforced by HAMi-core. That is the configuration most clusters need, since the Operator is how
the GPU stack normally gets installed.
Scope limits¶
Single node, driver from the VM image. Proves the two components coexist and that fractional
allocation still works and is enforced; does not prove the Operator-managed-driver reboot
case, multi-node rollout, upgrade behaviour of either chart, MIG mode (the L40 has none), or
sharing performance under sustained load. The isolation mechanism itself is proven separately in
hami-isolation-validation.md. Full ledger:
fake-vs-real-limitations.md.