This is an old revision of the document!
| Component | Requirement | Notes |
|---|---|---|
| Kubernetes | v1.30–1.34 | Current GA-validated range |
| Helm | v3.5+ | |
| Node Feature Discovery (NFD) | 0.15.6–0.17.0 | Only one NFD instance per cluster — if GPU Operator is also installed, reuse its NFD rather than deploying a second copy |
| Container runtime | containerd or CRI-O | Which one depends on OS — see 1.3 |
| Product | Fabric | Max port speed | Notes |
|---|---|---|---|
| ConnectX-6 | Ethernet & InfiniBand | 200 Gb/s | IB RDMA and RoCE |
| ConnectX-6 Dx | Ethernet | 200 Gb/s | RoCE |
| ConnectX-7 | Ethernet & InfiniBand | 400 Gb/s | IB RDMA and RoCE |
| ConnectX-8 SuperNIC | Ethernet & InfiniBand | 800 Gb/s | IB RDMA and RoCE |
| BlueField-3 DPU | Ethernet | 200 Gb/s | NIC mode only, RoCE |
| BlueField-3 SuperNIC | Ethernet | 400 Gb/s | NIC mode only, RoCE |
| OS | Upstream K8s | OpenShift | RKE2 | MicroK8s | Runtime |
|---|---|---|---|---|---|
| Ubuntu 24.04 LTS | 1.30–1.34 | — | — | 1.30–1.34 | containerd |
| Ubuntu 22.04 LTS | 1.30–1.34 | — | — | 1.30–1.34 | containerd |
| Red Hat CoreOS | — | 4.17–4.20 | — | — | CRI-O |
| RHEL 8 / 9 / 10 | 1.30–1.34 | — | — | — | containerd + CRI-O |
| SLES 15 SP7 | 1.30–1.34 | — | 1.30–1.34 | — | containerd |
The operator manages a containerized DOCA-OFED driver (the successor to MLNX_OFED) rather than requiring it to be preinstalled on the host — this is one of the operator's core value props. Two delivery paths:
helm repo add nvidia https://helm.ngc.nvidia.com/nvidia helm repo update helm install network-operator nvidia/network-operator \ -n nvidia-network-operator \ --create-namespace \ --version v25.10.0 \ --set sriovNetworkOperator.enabled=true \ --wait kubectl -n nvidia-network-operator get pods
This installs the operator controller and CRDs only — no host is touched until a NicClusterPolicy is applied (Section 3).
For anything beyond quick-start defaults, fetch the chart and drive the install from a values.yaml instead of ad hoc –set flags:
helm fetch nvidia/network-operator --version v25.10.0 --untar # edit values.yaml helm install network-operator ./network-operator -n nvidia-network-operator \ --create-namespace -f values.yaml
| Area | What it controls |
|---|---|
| General parameters | Namespace, image pull secrets (imagePullSecrets customization for private/NGC-authenticated registries), node selectors/affinity, tolerations |
| NFD labels / Node Feature Discovery | Whether the chart deploys its own NFD instance or expects one to already exist (set to avoid the GPU Operator/NFD collision noted in 1.1) |
| SR-IOV Network Operator | sriovNetworkOperator.enabled — toggles deployment of the community SR-IOV Network Operator sub-chart, required for any SR-IOV use case |
| Maintenance Operator | maintenanceOperator.enabled — deploys the NVIDIA Maintenance Operator sub-chart, required if you want “requestor mode” upgrades (Section 5) instead of the operator's built-in cordon/drain logic |
| Proxy / air-gapped settings | HTTP proxy env vars for OpenShift and vanilla K8s; local-registry configuration for fully disconnected environments |
kubectl -n nvidia-network-operator get pods
All controller pods (network-operator, and any enabled sub-charts like sriov-network-operator) should reach Running. This confirms the control plane is up — it does not confirm anything about NIC configuration, which only happens once a NicClusterPolicy is applied.
NicClusterPolicy (mellanox.com/v1alpha1) is the single central custom resource the operator continuously reconciles against. It is effectively the declarative “desired state” for the entire host networking stack across the cluster: which driver version runs, which device plugins are active, which CNIs and IPAM are deployed, and how upgrades should behave. Everything downstream — SR-IOV networks, MacVLAN networks, IPoIB networks — depends on a healthy NicClusterPolicy first.
| Spec field | Purpose |
|---|---|
| ofedDriver | DOCA-OFED driver image/repository/version, plus upgradePolicy (auto-upgrade, drain behavior, safe-load — see Section 5) |
| rdmaSharedDevicePlugin | Configures the RDMA shared device plugin — resource naming, NIC selectors, how many pods can share a device |
| sriovDevicePlugin | Configures the SR-IOV device plugin for VF allocation |
| secondaryNetwork | Bundles Multus, NVIDIA IPAM (nvIpam), IPoIB CNI, and IB Kubernetes plugin settings — the plumbing behind MacVLAN/IPoIB/SR-IOV secondary networks |
| nicFeatureDiscovery | NIC-level feature labeling (link type, capabilities) used by selectors elsewhere in the CR |
| docaTelemetryService | Optional telemetry sidecar for NIC-level metrics |
| nicConfigurationOperator | Hand-off point to the separate NIC Configuration Operator for firmware-level settings (not covered by Network Operator itself) |
apiVersion: mellanox.com/v1alpha1
kind: NicClusterPolicy
metadata:
name: nic-cluster-policy
namespace: nvidia-network-operator
spec:
ofedDriver:
image: doca-driver
repository: nvcr.io/nvidia/mellanox
version: doca3.2.0-25.10-1.2.8.0-2
upgradePolicy:
autoUpgrade: true
maxParallelUpgrades: 1
safeLoad: false
drain:
enable: true
force: false
podSelector: ""
deleteEmptyDir: true
kubectl get -n nvidia-network-operator nicclusterpolicies.mellanox.com nic-cluster-policy -o yaml
status:
appliedStates:
- name: state-multus-cni
state: ready
- name: state-OFED
state: ready
- name: state-RDMA-device-plugin
state: ready
- name: state-nv-ipam-cni
state: ready
- name: state-SRIOV-device-plugin
state: ignore # not configured in this CR — not a failure
state: ready
state: ready at the top level means the declared policy has been fully rolled out cluster-wide. A sub-state of ignore means that feature simply wasn't requested — not an error.
Any manual edit affecting device plugin configuration (e.g., NIC selectors) requires a manual device-plugin pod restart — this is a standing operator limitation, independent of whether the edit was part of a version upgrade or a plain reconfiguration.
| Mode | How traffic reaches the pod | RDMA model | Isolation | Best fit |
|---|---|---|---|---|
| SR-IOV | A hardware Virtual Function (VF) is passed directly into the pod's network namespace via the SR-IOV CNI | Direct — each VF has its own RDMA context | Strong (dedicated VF per pod) | Max performance, HPC/AI training, low jitter |
| RDMA (shared device) | RDMA character devices exposed via the RDMA shared device plugin; the NIC itself stays on the host's primary interface | Shared — multiple pods share one physical device's RDMA resources | Weaker (shared) | Multi-tenant workloads needing RDMA without dedicating a whole NIC/VF per pod |
| Host Device | The entire physical NIC is PCI-passed into one pod, no sharing at all | Direct, exclusive | Strongest (whole device) | Legacy/DPDK apps needing raw, exclusive device control |
| MacVLAN | L2 MACVLAN sub-interface per pod, layered on a shared parent interface, typically paired with the RDMA shared device plugin for the RDMA path | Shared | Network-layer isolation via distinct MAC/IP per pod | Cloud-native multi-tenant HPC needing many pods/node with distinct L2 identities |
| IPoIB (IP over InfiniBand) | IP connectivity carried over an InfiniBand fabric via the IPoIB CNI; RDMA still available via the shared device plugin | Shared | Moderate | Distributed storage/analytics needing ordinary IP-routable traffic on an IB fabric |
| SR-IOV InfiniBand | SR-IOV VFs on a native InfiniBand fabric, with pkey/GUID management handled by the IB Kubernetes plugin | Strong (dedicated VF + IB partition) | Large-scale IB-based AI training clusters |
Each mode has a ready-made NicClusterPolicy + secondary-network manifest pair in the Quick Start Guide (SR-IOV Network with RDMA, Host Device Network with RDMA, IPoIB with RDMA Shared Device, MacVLAN with RDMA Shared Device, SR-IOV InfiniBand Network with RDMA) — these are the fastest way to see a working reference for each pattern rather than building NicClusterPolicy fields from scratch.
helm upgrade only updates the operator's own controller and CRDs. It does not change the DOCA-OFED driver or any component version actually running on nodes — those live in NicClusterPolicy and must be bumped in a separate, manual step. This is the single most common source of “I upgraded but nothing changed” confusion.
Step 1 — Fetch the new chart:
helm fetch https:%%//%%helm.ngc.nvidia.com/nvidia/charts/network-operator-25.10.0.tgz tar xf network-operator-25.10.0.tgz
Step 2 — Apply the Helm chart update (controller + CRDs only):
helm upgrade -n nvidia-network-operator network-operator nvidia/network-operator \ --version=25.10.0 -f values-25.10.0.yaml --force
Step 3 — Manually update NicClusterPolicy with the new release's component versions (driver image tag, device plugin images, etc., from that release's component matrix), then re-apply:
kubectl apply -f nicclusterpolicy.yaml
Known limitation: a devicePlugin config change without a matching image bump may not auto-restart the plugin pod — manual kubectl delete pod restart may be required.
Step 4 — Driver rollout across nodes. Governed by ofedDriver.upgradePolicy:
Each node walks a tracked state machine via the nvidia.com/ofed-driver-upgrade-state label: upgrade-required → cordon-required → wait-for-jobs-required → drain-required → pod-restart-required → uncordon-required → upgrade-done (or upgrade-failed, requiring manual intervention).
Two execution modes:
PodDisruptionBudget caveat: drains can silently fail if PDBs aren't accounted for — drain.podSelector must be scoped precisely to the pods that actually need to move. Over-broad selectors on clusters with strict PDBs (OpenShift especially) can block the whole drain.
Manual fallback (if autoUpgrade is off): the driver DaemonSet uses OnDelete update strategy, so a bare helm upgrade leaves the old driver pod running until it's explicitly deleted or the node reboots:
kubectl drain <NODE_NAME> --pod-selector=<SECONDARY_NETWORK_POD_SELECTOR> kubectl delete pod -n nvidia-network-operator -l app=mofed-<OS_NAME> kubectl uncordon <NODE_NAME>
Do this per-node in production rather than all at once, to bound blast radius.
Step 5 — Verify:
kubectl get nodes -L nvidia.com/ofed-driver-upgrade-state kubectl get -n nvidia-network-operator nicclusterpolicies.mellanox.com nic-cluster-policy -o yaml
Confirm every targeted node reads upgrade-done and the CR's overall status.state is ready. If a node sticks at upgrade-failed: drain it manually (kubectl drain –ignore-daemonsets), delete its driver pod, and — if Safe Driver Loading was enabled — remove the nvidia.com/ofed-driver-upgrade.driver-wait-for-safe-load node annotation to unblock the reload.
Calendar versioning: YY.MM.PP. When a new major (YY.MM) ships, the prior major moves to maintenance (patch/CVE fixes only); the one before that goes EOL. At time of writing: 25.10.x = GA, 25.7.x = Maintenance, 25.4.x and earlier = EOL. Plan upgrade cadence against this rather than waiting for forced EOL migration.
kubectl delete -n nvidia-network-operator nicclusterpolicies.mellanox.com nic-cluster-policy helm uninstall network-operator -n nvidia-network-operator kubectl get nicclusterpolicies.mellanox.com # expect "No resources found"
On OpenShift, OLM uninstall does not remove CRDs/CRs automatically — delete them explicitly afterward (oc delete crds hostdevicenetworks.mellanox.com macvlannetworks.mellanox.com nicclusterpolicies.mellanox.com).
| Limitation | Effect |
|---|---|
| No RDMA-capable NIC (local dev machines, generic cloud VMs, DGX Spark) | The operator's Helm chart/CRDs install fine — the controller has no hardware dependency. But NicClusterPolicy reconciles against nodes with no matching NVIDIA/Mellanox device, so NIC feature discovery, device-plugin, and driver-container states have nothing to attach to; the DOCA-OFED driver pod fails health checks or registers no usable device resources. |
| No VFs/RDMA devices to allocate | SR-IOV, Host-Device, MacVLAN, and IPoIB network CRs show pods stuck in scheduling or CNI failure — the underlying hardware resource simply doesn't exist to satisfy the request. |
| Kernel/OS mismatch | Precompiled DOCA-OFED driver containers are GA only for generic-flavor Ubuntu 22.04/24.04. Cloud-vendor kernels (aws/azure/oracle), custom kernels, or other distros need a custom-built precompiled driver container — meaningful extra lifecycle burden for a throwaway test environment. |
| NFD collisions | Running NFD from both GPU Operator and Network Operator on one cluster is unsupported; a cluster already running GPU Operator must reuse its NFD instance instead of deploying a second one via the Network Operator chart. |
| PodDisruptionBudget conflicts | Especially on OpenShift, over-broad or unset PDBs can silently block node drains during upgrade — more likely to go unnoticed on an ad hoc test cluster with no PDB discipline. |
| Virtualization/nesting | SR-IOV VFs and true RDMA generally can't pass through multiple virtualization layers, so SR-IOV and Host-Device modes are effectively unusable inside most local VMs or cloud dev sandboxes, even when the underlying physical host has a supported NIC. |
Practical conclusion: the mechanical/API layer — Helm install, CRD structure, editing NicClusterPolicy, reading status, running upgrade commands — is fully hardware-agnostic and can be exercised anywhere with a Kubernetes API server. What cannot be validated without real ConnectX/BlueField hardware is anything downstream of NIC discovery: driver loading against real silicon, VF creation, RDMA device allocation, and actual throughput/latency behavior. Local environments are useful for validating “does my NicClusterPolicy YAML apply and pass schema/reconciliation cleanly” — everything hardware-dependent should be assessed against NVIDIA's documented, validated hardware/OS matrix (Section 1) instead.
| Situation | Recommendation |
|---|---|
| Bare-metal/on-prem K8s cluster with ConnectX-6/7/8 or BlueField-3 NICs, GPU-to-GPU or GPU-to-storage RDMA needed | Use it — primary supported scenario; pair with GPU Operator for GPUDirect RDMA |
| HPC/AI training cluster needing dedicated per-pod NIC bandwidth with multi-tenant isolation | Use it, SR-IOV or SR-IOV InfiniBand mode |
| Multi-tenant cloud-native cluster where many pods need shared, moderate RDMA access | Use it, RDMA shared device plugin ± MacVLAN |
| Distributed storage/analytics on an InfiniBand fabric needing ordinary IP addressing | Use it, IPoIB mode |
| OpenShift environment | Use it — dedicated deployment/upgrade path via OLM, including disconnected/air-gapped install support |
| Local dev laptop, generic cloud VM, or DGX Spark without RDMA-capable NICs | Do not attempt hands-on deployment — no hardware to reconcile against; validate via documentation and CRD reference instead |
| Cluster already running GPU Operator's NFD | Reuse that NFD instance; don't deploy a second one via the Network Operator chart |
| Need firmware-level NIC configuration (not just driver/CNI) | Pair with the separate NIC Configuration Operator |
Reference links