Regular public and private communication in the clusters via eth0 and eth1 are not affected by the installation of the Multus CNI and continue to use Cilium.
How to Configure Networking for Multi-Node GPU Worker Nodes
Last verified 1 Sep 2026
DigitalOcean Kubernetes (DOKS) is a Kubernetes service with a fully managed control plane, high availability, and autoscaling. DOKS integrates with standard Kubernetes toolchains and DigitalOcean’s load balancers, volumes, CPU and GPU Droplets, API, and CLI.
Multi-node GPU clusters can only be created in multiples of 8 GPUs and are available by contract only. For more information on supported GPUs, see GPU Worker Nodes.
In a multi-node configuration, 8-GPU configurations are connected via a dedicated high-speed networking fabric in the DOKS cluster. The networking fabric is exposed on worker nodes through eight (or sixteen for NVIDIA B300) network interface controllers (NICs) named fabric0, fabric1, …, fabric7 (,fabric8, …, fabric15), which exist alongside the regular eth0 and eth1 interfaces. The eth0 interface provides public internet connectivity, and eth1 provides private connectivity to other nodes in the same VPC network. The fabric NICs enable AI/ML workloads to exchange data with very low latency and high throughput. To achieve high networking performance, we recommend using the Remote Direct Memory Access (RDMA) networking protocol for communication between the GPU nodes through the fabric NICs, which completely bypasses the CPU and kernel of the operating system for data transfer.
Additional plugins are required to enable the high-speed fabric for multi-node GPU networking. This guide covers the additional required components, how to configure them, and how to apply NCCL or RCCL settings in your workloads.
Required Plugins
To use the high-speed fabric with container-based workloads, the following Kubernetes plugins must be available on clusters with AMD or NVIDIA GPUs:
-
Mellanox k8s-rdma-shared-dev-plugin: This plugin is automatically installed in your DOKS cluster when you add a node pool with a fabric-connected slug. It exposes RDMA-related resources as Kubernetes resources, named
rdma/fabric0, rdma/fabric1, rdma/fabric2, …. You can manage these resources using resource requests and limits in your manifests. -
Multus CNI plugin: You must install this plugin manually. It moves the NICs
fabric0, fabric1, ...into the container namespace via thehost-deviceplugin. To install the plugin, run the following command:
kubectl apply -f https://raw.githubusercontent.com/k8snetworkplumbingwg/multus-cni/master/deployments/multus-daemonset-thick.ymlAfter installing the CNI plugin, create NetworkAttachmentDefinition resources for the fabric NICs as described in the Configure Multus CNI Plugin section below.
Manage RDMA-Related Resources
Expose the RDMA-related resources managed by the Mellanox k8s-rdma-shared-dev-plugin to your workloads. To do this for AMD GPU nodes, add the following resource requests and limits to your Pod or Deployment manifest:
resources:
requests:
amd.com/gpu: 8
rdma/fabric0: 1
rdma/fabric1: 1
rdma/fabric2: 1
rdma/fabric3: 1
rdma/fabric4: 1
rdma/fabric5: 1
rdma/fabric6: 1
rdma/fabric7: 1
limits:
amd.com/gpu: 8
rdma/fabric0: 1
rdma/fabric1: 1
rdma/fabric2: 1
rdma/fabric3: 1
rdma/fabric4: 1
rdma/fabric5: 1
rdma/fabric6: 1
rdma/fabric7: 1For NVIDIA GPU nodes, replace amd.com/gpu: 8 with nvidia.com/gpu: 8.
Configure Multus CNI Plugin
In addition to the RDMA-related resources, you must make the fabric NICs fabric0, fabric1, ... available to your containers. To do this, configure a set of NetworkAttachmentDefinition resources that use the host-device CNI plugin to expose each NIC.
Create a config file that contains the following fabric NICs:
apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
name: roce-net-fabric0
spec:
config: '{
"cniVersion": "0.3.1",
"type": "host-device",
"device": "fabric0"
}'
---
apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
name: roce-net-fabric1
spec:
config: '{
"cniVersion": "0.3.1",
"type": "host-device",
"device": "fabric1"
}'
---
apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
name: roce-net-fabric2
spec:
config: '{
"cniVersion": "0.3.1",
"type": "host-device",
"device": "fabric2"
}'
---
apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
name: roce-net-fabric3
spec:
config: '{
"cniVersion": "0.3.1",
"type": "host-device",
"device": "fabric3"
}'
---
apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
name: roce-net-fabric4
spec:
config: '{
"cniVersion": "0.3.1",
"type": "host-device",
"device": "fabric4"
}'
---
apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
name: roce-net-fabric5
spec:
config: '{
"cniVersion": "0.3.1",
"type": "host-device",
"device": "fabric5"
}'
---
apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
name: roce-net-fabric6
spec:
config: '{
"cniVersion": "0.3.1",
"type": "host-device",
"device": "fabric6"
}'
---
apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
name: roce-net-fabric7
spec:
config: '{
"cniVersion": "0.3.1",
"type": "host-device",
"device": "fabric7"
}'Remember that for NVIDIA B300, eight additional fabric8 to fabric15 stanzas are required. Install the resources in your desired namespace using the following command:
kubectl apply -f <your-manifest>.yaml --namespace=<your-namespace>Next, make the fabric NICs available in your containers by adding an annotation to your Pod or Deployment manifest (similarly here, add fabric8 to fabric15 if using NVIDIA B300):
metadata:
annotations:
k8s.v1.cni.cncf.io/networks: >-
roce-net-fabric0@fabric0,
roce-net-fabric1@fabric1,
roce-net-fabric2@fabric2,
roce-net-fabric3@fabric3,
roce-net-fabric4@fabric4,
roce-net-fabric5@fabric5,
roce-net-fabric6@fabric6,
roce-net-fabric7@fabric7Use kubectl apply to apply the updates.
The k8s.v1.cni.cncf.io/networks annotation tells Multus to attach each fabric* interface to the Pod’s network namespace using your NetworkAttachmentDefinition resources and the host-device plugin. The interfaces attach after the Pod is scheduled and running and the CNI finishes attaching the devices.
Unattached fabric interfaces appear in the worker node’s default network namespace. Use ip link or a similar command to list them.
When Multus attaches an interface, it moves that interface into the Pod’s network namespace, so while a Pod holds a fabric interface, it does not appear on the host. Use kubectl exec to run ip link or ip addr inside the Pod to inspect attached interfaces. Do not use host-only checks alone to conclude RDMA or the fabric is missing while a Pod already uses those NICs.
You can also reference NetworkAttachmentDefinition from another namespace by using the namespace resource name in the annotation (for example, custom-namespace/roce-net-fabric0@fabric0). Each fabric NIC can only be attached to a single container at a time.
Once the fabric NICs are available in the containers, high-speed networking using RDMA is enabled between the GPU nodes.
Configure NCCL or RCCL
For the best performance with multi-node training, configure NCCL on NVIDIA GPUs or RCCL on AMD GPUs after the fabric NICs are attached to your Pods.
The recommended parameter sets for each GPU family, including the NVIDIA H100 topology file and GID index guidance, are documented in How to Configure Multi-Node GPU Droplets. Use those values in your DigitalOcean Kubernetes workloads, with one DOKS-specific change: set NCCL_SOCKET_IFNAME to eth0 (the Pod’s primary CNI interface), not eth1 as on Droplets.
You can apply the settings as environment variables on your containers, pass them with mpirun -x, or write them to /etc/nccl.conf (NVIDIA) or /etc/rccl.conf (AMD). The following examples show complete configurations for common multi-node GPU worker types.
NVIDIA H100 workers require a NCCL topology file in addition to the configuration parameters. Download the topology file from the NVIDIA H100 section of the Droplet multi-node guide and save it as /etc/nccl/topo.xml in your container image or at container start. Then create /etc/nccl.conf with the following contents:
NCCL_TOPO_FILE=/etc/nccl/topo.xml
NCCL_SOCKET_IFNAME==eth0
NCCL_CROSS_NIC=0
NCCL_NET_DISABLE_INTRA=1
NCCL_IB_TC=104
NCCL_DEBUG=WARNYou can create these files in an init container or at the start of your worker container command. For parameter descriptions, see NVIDIA H100 in the Droplet guide.
For NVIDIA H200 and B300 workers, set the following environment variables on your training containers. For B300, also attach fabric8 through fabric15 as described in Configure Multus CNI Plugin.
env:
- name: NCCL_SOCKET_IFNAME
value: eth0
- name: NCCL_CROSS_NIC
value: "0"
- name: NCCL_NET_DISABLE_INTRA
value: "1"
- name: NCCL_IB_TC
value: "104"You can instead write the same settings to /etc/nccl.conf. For parameter descriptions, see NVIDIA H200 and NVIDIA B300 in the Droplet guide.
AMD Instinct MI300X and MI325X workers use the gfx942 architecture. Set the following environment variables on your training containers:
env:
- name: NCCL_SOCKET_IFNAME
value: eth0
- name: NCCL_CROSS_NIC
value: "0"
- name: NCCL_PXN_DISABLE
value: "0"
- name: NCCL_NET_DISABLE_INTRA
value: "1"
- name: NCCL_IB_GID_INDEX
value: "1"
- name: NCCL_IB_TC
value: "104"RCCL reads the same NCCL_* variable names. You can instead write these settings to /etc/rccl.conf. You may need to update the NCCL_IB_GID_INDEX value for your environment; see GID Index Selection. For parameter descriptions, see AMD MI3XX Family in the Droplet guide.
AMD Instinct MI350X and later workers use the gfx950 architecture. Set the following environment variables on your training containers:
env:
- name: NCCL_SOCKET_IFNAME
value: eth0
- name: NCCL_CROSS_NIC
value: "0"
- name: NCCL_PXN_DISABLE
value: "0"
- name: NCCL_NET_DISABLE_INTRA
value: "1"
- name: NCCL_IB_GID_INDEX
value: "1"
- name: NCCL_IB_TC
value: "104"RCCL reads the same NCCL_* variable names. You can instead write these settings to /etc/rccl.conf. You may need to update the NCCL_IB_GID_INDEX value for your environment; see GID Index Selection. For parameter descriptions, see AMD MI3XX Family in the Droplet guide.
If collective communication fails or you need more detail while debugging, set NCCL_DEBUG to INFO or TRACE instead of WARN. For more targeted logging, also set NCCL_DEBUG_SUBSYS=INIT,GRAPH,NET to collect additional detail for initialization, topology graph construction, and networking.
Example: Run a NCCL all_reduce Test on NVIDIA H100
The following example is a complete Kubeflow MPIJob that runs the NCCL Tests all_reduce_perf benchmark across two NVIDIA H100 worker nodes (16 GPUs total). It also showcases how to install the H100 NCCL topology file (topo.xml) and wire it through /etc/nccl.conf with NCCL_TOPO_FILE at worker start.
Before you apply the manifest:
- Install the Multus CNI plugin and create the
NetworkAttachmentDefinitionresources from Configure Multus CNI Plugin. - Install the Kubeflow MPI Operator, which provides the
MPIJobAPI (kubeflow.org/v2beta1). - Have at least two available multi-node H100 GPU worker nodes with free GPUs.
Create a file named mpijob-multus-nvidia-h100.yaml and add the following. The worker container writes /etc/nccl/topo.xml and /etc/nccl.conf before starting sshd. The example includes a topology file for illustration. Always use the latest topo.xml from the NVIDIA H100 section of the Droplet multi-node guide and replace the embedded contents if they differ.
apiVersion: kubeflow.org/v2beta1
kind: MPIJob
metadata:
name: mpi-multus-nvidia
spec:
slotsPerWorker: 8
runPolicy:
cleanPodPolicy: Running
mpiReplicaSpecs:
Launcher:
replicas: 1
template:
spec:
containers:
- name: mpi-launcher
image: ghcr.io/coreweave/nccl-tests:13.2.0-devel-ubuntu24.04-nccl2.29.7-1-7112046
command:
- mpirun
- --allow-run-as-root
- -np
- "16"
- -bind-to
- none
- -map-by
- slot
- -x
- PATH
- -mca
- plm_rsh_args
- "-p 2222 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null"
- -mca
- btl
- self,tcp
- -mca
- pml
- ^ucx
- /opt/nccl-tests/build/all_reduce_perf
- -b
- 1G
- -e
- 16G
- -f
- "2"
- -g
- "1"
- -w
- "5"
- --iters
- "200"
Worker:
replicas: 2
template:
metadata:
annotations:
k8s.v1.cni.cncf.io/networks: >-
roce-net-fabric0@fabric0,
roce-net-fabric1@fabric1,
roce-net-fabric2@fabric2,
roce-net-fabric3@fabric3,
roce-net-fabric4@fabric4,
roce-net-fabric5@fabric5,
roce-net-fabric6@fabric6,
roce-net-fabric7@fabric7
spec:
tolerations:
- key: "nvidia.com/gpu"
operator: "Exists"
effect: "NoSchedule"
initContainers:
- name: setup-ssh
image: ghcr.io/coreweave/nccl-tests:13.2.0-devel-ubuntu24.04-nccl2.29.7-1-7112046
command:
- /bin/bash
- -c
- |
set -ex
echo "Setting up SSH configuration..."
mkdir -p /ssh-setup/sshd
echo "Generating SSH host keys..."
ssh-keygen -t rsa -f /ssh-setup/sshd/ssh_host_rsa_key -N '' 2>/dev/null
ssh-keygen -t ecdsa -f /ssh-setup/sshd/ssh_host_ecdsa_key -N '' 2>/dev/null
ssh-keygen -t ed25519 -f /ssh-setup/sshd/ssh_host_ed25519_key -N '' 2>/dev/null
cat > /ssh-setup/sshd/sshd_config << 'SSHD_EOF'
Port 2222
HostKey /etc/ssh-runtime/ssh_host_rsa_key
HostKey /etc/ssh-runtime/ssh_host_ecdsa_key
HostKey /etc/ssh-runtime/ssh_host_ed25519_key
PermitRootLogin yes
PubkeyAuthentication yes
AuthorizedKeysFile /root/.ssh/authorized_keys /root/.ssh/id_rsa.pub
PasswordAuthentication no
ChallengeResponseAuthentication no
UsePAM no
PrintMotd no
PidFile /var/run/sshd.pid
StrictModes no
SSHD_EOF
echo "SSH setup complete"
echo "Files in /ssh-setup/sshd:"
ls -la /ssh-setup/sshd/
volumeMounts:
- name: ssh-setup
mountPath: /ssh-setup
containers:
- name: mpi-worker
image: ghcr.io/coreweave/nccl-tests:13.2.0-devel-ubuntu24.04-nccl2.29.7-1-7112046
command:
- /bin/bash
- -c
- |
set -ex
mkdir -p /etc/nccl
cat << 'EOF' > /etc/nccl/topo.xml
<system version="1">
<cpu numaid="0" affinity="00000000,00000000,0000ffff,ffffffff,ffffffff" arch="x86_64" vendor="GenuineIntel" familyid="6" modelid="143">
<pci busid="ffff:ff:01.0" class="0x060400" link_speed="32 GT/s" link_width="16" vendor="0x0000" device="0x0000" subsystem_vendor="0x0000" subsystem_device="0x0000">
<pci busid="0000:01:01.0" class="0x030200" link_speed="32.0 GT/s PCIe" link_width="16"/>
<pci busid="0000:01:02.0" class="0x020000" link_speed="32.0 GT/s PCIe" link_width="16">
<nic>
<net name="mlx5_0" dev="0" speed="400000" port="1" latency="0.000000" maxconn="131072" gdr="1"/>
</nic>
</pci>
</pci>
<pci busid="ffff:ff:02.0" class="0x060400" link_speed="32 GT/s" link_width="16" vendor="0x0000" device="0x0000" subsystem_vendor="0x0000" subsystem_device="0x0000">
<pci busid="0000:02:01.0" class="0x030200" link_speed="32.0 GT/s PCIe" link_width="16"/>
<pci busid="0000:02:02.0" class="0x020000" link_speed="32.0 GT/s PCIe" link_width="16">
<nic>
<net name="mlx5_1" dev="1" speed="400000" port="2" latency="0.000000" maxconn="131072" gdr="1"/>
</nic>
</pci>
</pci>
<pci busid="ffff:ff:03.0" class="0x060400" link_speed="32 GT/s" link_width="16" vendor="0x0000" device="0x0000" subsystem_vendor="0x0000" subsystem_device="0x0000">
<pci busid="0000:03:01.0" class="0x030200" link_speed="32.0 GT/s PCIe" link_width="16"/>
<pci busid="0000:03:02.0" class="0x020000" link_speed="32.0 GT/s PCIe" link_width="16">
<nic>
<net name="mlx5_2" dev="2" speed="400000" port="3" latency="0.000000" maxconn="131072" gdr="1"/>
</nic>
</pci>
</pci>
<pci busid="ffff:ff:04.0" class="0x060400" link_speed="32 GT/s" link_width="16" vendor="0x0000" device="0x0000" subsystem_vendor="0x0000" subsystem_device="0x0000">
<pci busid="0000:04:01.0" class="0x030200" link_speed="32.0 GT/s PCIe" link_width="16"/>
<pci busid="0000:04:02.0" class="0x020000" link_speed="32.0 GT/s PCIe" link_width="16">
<nic>
<net name="mlx5_3" dev="3" speed="400000" port="4" latency="0.000000" maxconn="131072" gdr="1"/>
</nic>
</pci>
</pci>
</cpu>
<cpu numaid="1" affinity="ffffffff,ffffffff,ffff0000,0000000,00000000" arch="x86_64" vendor="GenuineIntel" familyid="6" modelid="143">
<pci busid="ffff:ff:05.0" class="0x060400" link_speed="32 GT/s" link_width="16" vendor="0x0000" device="0x0000" subsystem_vendor="0x0000" subsystem_device="0x0000">
<pci busid="0000:05:01.0" class="0x030200" link_speed="32.0 GT/s PCIe" link_width="16"/>
<pci busid="0000:05:02.0" class="0x020000" link_speed="32.0 GT/s PCIe" link_width="16">
<nic>
<net name="mlx5_4" dev="4" speed="400000" port="5" latency="0.000000" maxconn="131072" gdr="1"/>
</nic>
</pci>
</pci>
<pci busid="ffff:ff:06.0" class="0x060400" link_speed="32 GT/s" link_width="16" vendor="0x0000" device="0x0000" subsystem_vendor="0x0000" subsystem_device="0x0000">
<pci busid="0000:06:01.0" class="0x030200" link_speed="32.0 GT/s PCIe" link_width="16"/>
<pci busid="0000:06:02.0" class="0x020000" link_speed="32.0 GT/s PCIe" link_width="16">
<nic>
<net name="mlx5_5" dev="5" speed="400000" port="6" latency="0.000000" maxconn="131072" gdr="1"/>
</nic>
</pci>
</pci>
<pci busid="ffff:ff:07.0" class="0x060400" link_speed="32 GT/s" link_width="16" vendor="0x0000" device="0x0000" subsystem_vendor="0x0000" subsystem_device="0x0000">
<pci busid="0000:07:01.0" class="0x030200" link_speed="32.0 GT/s PCIe" link_width="16"/>
<pci busid="0000:07:02.0" class="0x020000" link_speed="32.0 GT/s PCIe" link_width="16">
<nic>
<net name="mlx5_6" dev="6" speed="400000" port="7" latency="0.000000" maxconn="131072" gdr="1"/>
</nic>
</pci>
</pci>
<pci busid="ffff:ff:08.0" class="0x060400" link_speed="32 GT/s" link_width="16" vendor="0x0000" device="0x0000" subsystem_vendor="0x0000" subsystem_device="0x0000">
<pci busid="0000:08:01.0" class="0x030200" link_speed="32.0 GT/s PCIe" link_width="16"/>
<pci busid="0000:08:02.0" class="0x020000" link_speed="32.0 GT/s PCIe" link_width="16">
<nic>
<net name="mlx5_7" dev="7" speed="400000" port="8" latency="0.000000" maxconn="131072" gdr="1"/>
</nic>
</pci>
</pci>
</cpu>
</system>
EOF
cat << 'EOF' > /etc/nccl.conf
NCCL_TOPO_FILE=/etc/nccl/topo.xml
NCCL_SOCKET_IFNAME==eth0
NCCL_CROSS_NIC=0
NCCL_NET_DISABLE_INTRA=1
NCCL_IB_TC=104
NCCL_DEBUG=WARN
EOF
echo "Starting worker container..."
mkdir -p /var/run/sshd /etc/ssh-runtime
echo "Copying SSH host keys and config from init container..."
cp /ssh-setup/sshd/* /etc/ssh-runtime/
echo "SSH runtime files:"
ls -la /etc/ssh-runtime/
echo "Verifying operator-provided SSH keys at /root/.ssh..."
ls -la /root/.ssh/ || echo "Warning: /root/.ssh not found"
echo "Starting sshd in foreground..."
exec /usr/sbin/sshd -D -e -f /etc/ssh-runtime/sshd_config
securityContext:
privileged: true
capabilities:
add:
- IPC_LOCK
volumeMounts:
- name: ssh-setup
mountPath: /ssh-setup
- name: dshm
mountPath: /dev/shm
resources:
limits:
nvidia.com/gpu: 8
rdma/fabric0: 1
rdma/fabric1: 1
rdma/fabric2: 1
rdma/fabric3: 1
rdma/fabric4: 1
rdma/fabric5: 1
rdma/fabric6: 1
rdma/fabric7: 1
requests:
nvidia.com/gpu: 8
rdma/fabric0: 1
rdma/fabric1: 1
rdma/fabric2: 1
rdma/fabric3: 1
rdma/fabric4: 1
rdma/fabric5: 1
rdma/fabric6: 1
rdma/fabric7: 1
readinessProbe:
tcpSocket:
port: 2222
initialDelaySeconds: 5
periodSeconds: 3
timeoutSeconds: 2
livenessProbe:
tcpSocket:
port: 2222
initialDelaySeconds: 15
periodSeconds: 10
timeoutSeconds: 2
volumes:
- name: ssh-setup
emptyDir: {}
- name: dshm
emptyDir:
medium: Memory
sizeLimit: 16GiApply the manifest:
kubectl apply -f mpijob-multus-nvidia-h100.yamlThe launcher runs /opt/nccl-tests/build/all_reduce_perf, which measures all-reduce bandwidth across the fabric. NCCL reads the topology from /etc/nccl/topo.xml through the NCCL_TOPO_FILE setting in /etc/nccl.conf. For the latest NCCL topology file, download topo.xml from the NVIDIA H100 section of the Droplet multi-node guide. Watch the launcher logs for the test output:
kubectl logs -l training.kubeflow.org/job-role=launcher -fExpected Test Summary
A successful run ends with a summary like the following. Out of bounds values : 0 OK means the check passed. The average bus bandwidth value varies by GPU type and cluster configuration:
# Out of bounds values : 0 OK
# Avg bus bandwidth : <avg-bus-bandwidth>
#
# Collective test concluded: all_reduce_perfWhen the test finishes, delete the job:
kubectl delete mpijob mpi-multus-nvidiaExample: Run a NCCL all_reduce Test on NVIDIA H200
The following example is a complete Kubeflow MPIJob that runs the NCCL Tests all_reduce_perf benchmark across two NVIDIA H200 worker nodes (16 GPUs total). It attaches the fabric NICs with Multus, requests the RDMA resources, and passes the H200 NCCL parameters with mpirun -x. Unlike the H100 example, H200 does not require a custom topo.xml file.
Use the same Multus, MPI Operator, and cluster prerequisites as the H100 example, with at least two available multi-node H200 GPU worker nodes with free GPUs.
Create a file named mpijob-multus-nvidia-h200.yaml and add the following:
apiVersion: kubeflow.org/v2beta1
kind: MPIJob
metadata:
name: mpi-multus-nvidia
spec:
slotsPerWorker: 8
runPolicy:
cleanPodPolicy: Running
mpiReplicaSpecs:
Launcher:
replicas: 1
template:
spec:
containers:
- name: mpi-launcher
image: ghcr.io/coreweave/nccl-tests:13.2.0-devel-ubuntu24.04-nccl2.29.7-1-7112046
command:
- mpirun
- --allow-run-as-root
- -np
- "16"
- -bind-to
- none
- -map-by
- slot
- -x
- NCCL_SOCKET_IFNAME=eth0
- -x
- NCCL_CROSS_NIC=0
- -x
- NCCL_NET_DISABLE_INTRA=1
- -x
- NCCL_IB_TC=104
- -x
- NCCL_DEBUG=WARN
- -x
- PATH
- -mca
- plm_rsh_args
- "-p 2222 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null"
- -mca
- btl
- self,tcp
- -mca
- pml
- ^ucx
- /opt/nccl-tests/build/all_reduce_perf
- -b
- 1G
- -e
- 16G
- -f
- "2"
- -g
- "1"
- -w
- "5"
- --iters
- "200"
Worker:
replicas: 2
template:
metadata:
annotations:
k8s.v1.cni.cncf.io/networks: >-
roce-net-fabric0@fabric0,
roce-net-fabric1@fabric1,
roce-net-fabric2@fabric2,
roce-net-fabric3@fabric3,
roce-net-fabric4@fabric4,
roce-net-fabric5@fabric5,
roce-net-fabric6@fabric6,
roce-net-fabric7@fabric7
spec:
tolerations:
- key: "nvidia.com/gpu"
operator: "Exists"
effect: "NoSchedule"
initContainers:
- name: setup-ssh
image: ghcr.io/coreweave/nccl-tests:13.2.0-devel-ubuntu24.04-nccl2.29.7-1-7112046
command:
- /bin/bash
- -c
- |
set -ex
echo "Setting up SSH configuration..."
mkdir -p /ssh-setup/sshd
echo "Generating SSH host keys..."
ssh-keygen -t rsa -f /ssh-setup/sshd/ssh_host_rsa_key -N '' 2>/dev/null
ssh-keygen -t ecdsa -f /ssh-setup/sshd/ssh_host_ecdsa_key -N '' 2>/dev/null
ssh-keygen -t ed25519 -f /ssh-setup/sshd/ssh_host_ed25519_key -N '' 2>/dev/null
cat > /ssh-setup/sshd/sshd_config << 'SSHD_EOF'
Port 2222
HostKey /etc/ssh-runtime/ssh_host_rsa_key
HostKey /etc/ssh-runtime/ssh_host_ecdsa_key
HostKey /etc/ssh-runtime/ssh_host_ed25519_key
PermitRootLogin yes
PubkeyAuthentication yes
AuthorizedKeysFile /root/.ssh/authorized_keys /root/.ssh/id_rsa.pub
PasswordAuthentication no
ChallengeResponseAuthentication no
UsePAM no
PrintMotd no
PidFile /var/run/sshd.pid
StrictModes no
SSHD_EOF
echo "SSH setup complete"
echo "Files in /ssh-setup/sshd:"
ls -la /ssh-setup/sshd/
volumeMounts:
- name: ssh-setup
mountPath: /ssh-setup
containers:
- name: mpi-worker
image: ghcr.io/coreweave/nccl-tests:13.2.0-devel-ubuntu24.04-nccl2.29.7-1-7112046
command:
- /bin/bash
- -c
- |
set -ex
echo "Starting worker container..."
mkdir -p /var/run/sshd /etc/ssh-runtime
echo "Copying SSH host keys and config from init container..."
cp /ssh-setup/sshd/* /etc/ssh-runtime/
echo "SSH runtime files:"
ls -la /etc/ssh-runtime/
echo "Verifying operator-provided SSH keys at /root/.ssh..."
ls -la /root/.ssh/ || echo "Warning: /root/.ssh not found"
echo "Starting sshd in foreground..."
exec /usr/sbin/sshd -D -e -f /etc/ssh-runtime/sshd_config
securityContext:
privileged: true
capabilities:
add:
- IPC_LOCK
volumeMounts:
- name: ssh-setup
mountPath: /ssh-setup
- name: dshm
mountPath: /dev/shm
resources:
limits:
nvidia.com/gpu: 8
rdma/fabric0: 1
rdma/fabric1: 1
rdma/fabric2: 1
rdma/fabric3: 1
rdma/fabric4: 1
rdma/fabric5: 1
rdma/fabric6: 1
rdma/fabric7: 1
requests:
nvidia.com/gpu: 8
rdma/fabric0: 1
rdma/fabric1: 1
rdma/fabric2: 1
rdma/fabric3: 1
rdma/fabric4: 1
rdma/fabric5: 1
rdma/fabric6: 1
rdma/fabric7: 1
readinessProbe:
tcpSocket:
port: 2222
initialDelaySeconds: 5
periodSeconds: 3
timeoutSeconds: 2
livenessProbe:
tcpSocket:
port: 2222
initialDelaySeconds: 15
periodSeconds: 10
timeoutSeconds: 2
volumes:
- name: ssh-setup
emptyDir: {}
- name: dshm
emptyDir:
medium: Memory
sizeLimit: 16GiApply the manifest:
kubectl apply -f mpijob-multus-nvidia-h200.yamlThe launcher runs /opt/nccl-tests/build/all_reduce_perf, which measures all-reduce bandwidth across the fabric. Watch the launcher logs for the test output:
kubectl logs -l training.kubeflow.org/job-role=launcher -fA successful run ends with the same all_reduce_perf summary shown in Expected Test Summary.
When the test finishes, delete the job:
kubectl delete mpijob mpi-multus-nvidiaExample: Run a NCCL all_reduce Test on NVIDIA B300
The following example is a complete Kubeflow MPIJob that runs the NCCL Tests all_reduce_perf benchmark across two NVIDIA B300 worker nodes (16 GPUs total). B300 workers expose 16 fabric NICs (fabric0 through fabric15), so the Multus annotation and RDMA resource requests include all sixteen interfaces. Create the matching NetworkAttachmentDefinition resources for fabric8 through fabric15 in addition to fabric0 through fabric7, as described in Configure Multus CNI Plugin.
Use the same Multus, MPI Operator, and cluster prerequisites as the H100 example, with at least two available multi-node B300 GPU worker nodes with free GPUs. Like H200, B300 does not require a custom topo.xml file.
Create a file named mpijob-multus-nvidia-b300.yaml and add the following:
apiVersion: kubeflow.org/v2beta1
kind: MPIJob
metadata:
name: mpi-multus-nvidia
spec:
slotsPerWorker: 8
runPolicy:
cleanPodPolicy: Running
mpiReplicaSpecs:
Launcher:
replicas: 1
template:
spec:
containers:
- name: mpi-launcher
image: ghcr.io/coreweave/nccl-tests:13.2.0-devel-ubuntu24.04-nccl2.29.7-1-7112046
command:
- mpirun
- --allow-run-as-root
- -np
- "16"
- -bind-to
- none
- -map-by
- slot
- -x
- NCCL_SOCKET_IFNAME=eth0
- -x
- NCCL_CROSS_NIC=0
- -x
- NCCL_NET_DISABLE_INTRA=1
- -x
- NCCL_IB_TC=104
- -x
- NCCL_DEBUG=WARN
- -x
- PATH
- -mca
- plm_rsh_args
- "-p 2222 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null"
- -mca
- btl
- self,tcp
- -mca
- pml
- ^ucx
- /opt/nccl-tests/build/all_reduce_perf
- -b
- 1G
- -e
- 16G
- -f
- "2"
- -g
- "1"
- -w
- "5"
- --iters
- "200"
Worker:
replicas: 2
template:
metadata:
annotations:
k8s.v1.cni.cncf.io/networks: >-
roce-net-fabric0@fabric0,
roce-net-fabric1@fabric1,
roce-net-fabric2@fabric2,
roce-net-fabric3@fabric3,
roce-net-fabric4@fabric4,
roce-net-fabric5@fabric5,
roce-net-fabric6@fabric6,
roce-net-fabric7@fabric7,
roce-net-fabric8@fabric8,
roce-net-fabric9@fabric9,
roce-net-fabric10@fabric10,
roce-net-fabric11@fabric11,
roce-net-fabric12@fabric12,
roce-net-fabric13@fabric13,
roce-net-fabric14@fabric14,
roce-net-fabric15@fabric15
spec:
tolerations:
- key: "nvidia.com/gpu"
operator: "Exists"
effect: "NoSchedule"
initContainers:
- name: setup-ssh
image: ghcr.io/coreweave/nccl-tests:13.2.0-devel-ubuntu24.04-nccl2.29.7-1-7112046
command:
- /bin/bash
- -c
- |
set -ex
echo "Setting up SSH configuration..."
mkdir -p /ssh-setup/sshd
echo "Generating SSH host keys..."
ssh-keygen -t rsa -f /ssh-setup/sshd/ssh_host_rsa_key -N '' 2>/dev/null
ssh-keygen -t ecdsa -f /ssh-setup/sshd/ssh_host_ecdsa_key -N '' 2>/dev/null
ssh-keygen -t ed25519 -f /ssh-setup/sshd/ssh_host_ed25519_key -N '' 2>/dev/null
cat > /ssh-setup/sshd/sshd_config << 'SSHD_EOF'
Port 2222
HostKey /etc/ssh-runtime/ssh_host_rsa_key
HostKey /etc/ssh-runtime/ssh_host_ecdsa_key
HostKey /etc/ssh-runtime/ssh_host_ed25519_key
PermitRootLogin yes
PubkeyAuthentication yes
AuthorizedKeysFile /root/.ssh/authorized_keys /root/.ssh/id_rsa.pub
PasswordAuthentication no
ChallengeResponseAuthentication no
UsePAM no
PrintMotd no
PidFile /var/run/sshd.pid
StrictModes no
SSHD_EOF
echo "SSH setup complete"
echo "Files in /ssh-setup/sshd:"
ls -la /ssh-setup/sshd/
volumeMounts:
- name: ssh-setup
mountPath: /ssh-setup
containers:
- name: mpi-worker
image: ghcr.io/coreweave/nccl-tests:13.2.0-devel-ubuntu24.04-nccl2.29.7-1-7112046
command:
- /bin/bash
- -c
- |
set -ex
echo "Starting worker container..."
mkdir -p /var/run/sshd /etc/ssh-runtime
echo "Copying SSH host keys and config from init container..."
cp /ssh-setup/sshd/* /etc/ssh-runtime/
echo "SSH runtime files:"
ls -la /etc/ssh-runtime/
echo "Verifying operator-provided SSH keys at /root/.ssh..."
ls -la /root/.ssh/ || echo "Warning: /root/.ssh not found"
echo "Starting sshd in foreground..."
exec /usr/sbin/sshd -D -e -f /etc/ssh-runtime/sshd_config
securityContext:
privileged: true
capabilities:
add:
- IPC_LOCK
volumeMounts:
- name: ssh-setup
mountPath: /ssh-setup
- name: dshm
mountPath: /dev/shm
resources:
limits:
nvidia.com/gpu: 8
rdma/fabric0: 1
rdma/fabric1: 1
rdma/fabric2: 1
rdma/fabric3: 1
rdma/fabric4: 1
rdma/fabric5: 1
rdma/fabric6: 1
rdma/fabric7: 1
rdma/fabric8: 1
rdma/fabric9: 1
rdma/fabric10: 1
rdma/fabric11: 1
rdma/fabric12: 1
rdma/fabric13: 1
rdma/fabric14: 1
rdma/fabric15: 1
requests:
nvidia.com/gpu: 8
rdma/fabric0: 1
rdma/fabric1: 1
rdma/fabric2: 1
rdma/fabric3: 1
rdma/fabric4: 1
rdma/fabric5: 1
rdma/fabric6: 1
rdma/fabric7: 1
rdma/fabric8: 1
rdma/fabric9: 1
rdma/fabric10: 1
rdma/fabric11: 1
rdma/fabric12: 1
rdma/fabric13: 1
rdma/fabric14: 1
rdma/fabric15: 1
readinessProbe:
tcpSocket:
port: 2222
initialDelaySeconds: 5
periodSeconds: 3
timeoutSeconds: 2
livenessProbe:
tcpSocket:
port: 2222
initialDelaySeconds: 15
periodSeconds: 10
timeoutSeconds: 2
volumes:
- name: ssh-setup
emptyDir: {}
- name: dshm
emptyDir:
medium: Memory
sizeLimit: 16GiApply the manifest:
kubectl apply -f mpijob-multus-nvidia-b300.yamlThe launcher runs /opt/nccl-tests/build/all_reduce_perf, which measures all-reduce bandwidth across the fabric. Watch the launcher logs for the test output:
kubectl logs -l training.kubeflow.org/job-role=launcher -fA successful run ends with the same all_reduce_perf summary shown in Expected Test Summary.
When the test finishes, delete the job:
kubectl delete mpijob mpi-multus-nvidiaExample: Run a RCCL all_reduce Test on AMD MI300X and MI325X
The following example is a complete Kubeflow MPIJob that runs the RCCL Tests all_reduce_perf benchmark across two AMD Instinct MI300X or MI325X worker nodes (16 GPUs total). These GPUs use the gfx942 architecture. The launcher passes the RCCL parameters recommended for this family with mpirun -x.
Build a container image that includes RCCL Tests before you run the job. Follow AMD’s Using RCCL with Docker instructions, then push the image to a registry your cluster can pull from. Replace <your-rccl-tests-image> in the manifest with that image reference.
Use the same Multus, MPI Operator, and cluster prerequisites as the H100 example, with at least two available multi-node MI300X or MI325X GPU worker nodes with free GPUs.
Create a file named mpijob-multus-amd-gfx942.yaml and add the following. Set doks.digitalocean.com/gpu-model to mi300x or mi325x to match your worker nodes. The example sets NCCL_IB_GID_INDEX=1; you may need to update that value for your environment. See GID Index Selection.
apiVersion: kubeflow.org/v2beta1
kind: MPIJob
metadata:
name: mpi-multus-gfx942
spec:
slotsPerWorker: 8
runPolicy:
cleanPodPolicy: Running
mpiReplicaSpecs:
Launcher:
replicas: 1
template:
spec:
containers:
- name: mpi-launcher
image: <your-rccl-tests-image>
command:
- mpirun
- --allow-run-as-root
- -np
- "16"
- -bind-to
- none
- -map-by
- slot
- -x
- NCCL_SOCKET_IFNAME=eth0
- -x
- NCCL_CROSS_NIC=0
- -x
- NCCL_PXN_DISABLE=0
- -x
- NCCL_NET_DISABLE_INTRA=1
- -x
- NCCL_IB_GID_INDEX=1
- -x
- NCCL_IB_TC=104
- -x
- NCCL_DEBUG=WARN
- -x
- PATH
- -mca
- plm_rsh_args
- "-p 2222 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null"
- -mca
- btl
- self,tcp
- -mca
- pml
- ^ucx
- /workspace/rccl-tests/build/all_reduce_perf
- -b
- 1G
- -e
- 16G
- -f
- "2"
- -g
- "1"
- -w
- "5"
- --iters
- "200"
Worker:
replicas: 2
template:
metadata:
annotations:
k8s.v1.cni.cncf.io/networks: >-
roce-net-fabric0@fabric0,
roce-net-fabric1@fabric1,
roce-net-fabric2@fabric2,
roce-net-fabric3@fabric3,
roce-net-fabric4@fabric4,
roce-net-fabric5@fabric5,
roce-net-fabric6@fabric6,
roce-net-fabric7@fabric7
spec:
nodeSelector:
doks.digitalocean.com/gpu-model: mi325x
tolerations:
- key: "amd.com/gpu"
operator: "Exists"
effect: "NoSchedule"
initContainers:
- name: setup-ssh
image: <your-rccl-tests-image>
command:
- /bin/bash
- -c
- |
set -ex
echo "Setting up SSH configuration..."
mkdir -p /ssh-setup/sshd
echo "Generating SSH host keys..."
ssh-keygen -t rsa -f /ssh-setup/sshd/ssh_host_rsa_key -N '' 2>/dev/null
ssh-keygen -t ecdsa -f /ssh-setup/sshd/ssh_host_ecdsa_key -N '' 2>/dev/null
ssh-keygen -t ed25519 -f /ssh-setup/sshd/ssh_host_ed25519_key -N '' 2>/dev/null
cat > /ssh-setup/sshd/sshd_config << 'SSHD_EOF'
Port 2222
HostKey /etc/ssh-runtime/ssh_host_rsa_key
HostKey /etc/ssh-runtime/ssh_host_ecdsa_key
HostKey /etc/ssh-runtime/ssh_host_ed25519_key
PermitRootLogin yes
PubkeyAuthentication yes
AuthorizedKeysFile /root/.ssh/authorized_keys /root/.ssh/id_rsa.pub
PasswordAuthentication no
ChallengeResponseAuthentication no
UsePAM no
PrintMotd no
PidFile /var/run/sshd.pid
StrictModes no
SSHD_EOF
echo "SSH setup complete"
echo "Files in /ssh-setup/sshd:"
ls -la /ssh-setup/sshd/
volumeMounts:
- name: ssh-setup
mountPath: /ssh-setup
containers:
- name: mpi-worker
image: <your-rccl-tests-image>
command:
- /bin/bash
- -c
- |
set -ex
echo "Starting worker container..."
mkdir -p /var/run/sshd /etc/ssh-runtime
echo "Copying SSH host keys and config from init container..."
cp /ssh-setup/sshd/* /etc/ssh-runtime/
echo "SSH runtime files:"
ls -la /etc/ssh-runtime/
echo "Verifying operator-provided SSH keys at /root/.ssh..."
ls -la /root/.ssh/ || echo "Warning: /root/.ssh not found"
echo "Starting sshd in foreground..."
exec /usr/sbin/sshd -D -e -f /etc/ssh-runtime/sshd_config
securityContext:
privileged: true
capabilities:
add:
- IPC_LOCK
volumeMounts:
- name: ssh-setup
mountPath: /ssh-setup
- name: dshm
mountPath: /dev/shm
resources:
limits:
amd.com/gpu: 8
rdma/fabric0: 1
rdma/fabric1: 1
rdma/fabric2: 1
rdma/fabric3: 1
rdma/fabric4: 1
rdma/fabric5: 1
rdma/fabric6: 1
rdma/fabric7: 1
requests:
amd.com/gpu: 8
rdma/fabric0: 1
rdma/fabric1: 1
rdma/fabric2: 1
rdma/fabric3: 1
rdma/fabric4: 1
rdma/fabric5: 1
rdma/fabric6: 1
rdma/fabric7: 1
readinessProbe:
tcpSocket:
port: 2222
initialDelaySeconds: 5
periodSeconds: 3
timeoutSeconds: 2
livenessProbe:
tcpSocket:
port: 2222
initialDelaySeconds: 15
periodSeconds: 10
timeoutSeconds: 2
volumes:
- name: ssh-setup
emptyDir: {}
- name: dshm
emptyDir:
medium: Memory
sizeLimit: 16GiApply the manifest:
kubectl apply -f mpijob-multus-amd-gfx942.yamlThe launcher runs /workspace/rccl-tests/build/all_reduce_perf, which measures all-reduce bandwidth across the fabric. Watch the launcher logs for the test output:
kubectl logs -l training.kubeflow.org/job-role=launcher -fA successful run ends with the same all_reduce_perf summary shown in Expected Test Summary.
When the test finishes, delete the job:
kubectl delete mpijob mpi-multus-gfx942Example: Run a RCCL all_reduce Test on AMD MI350X and Later
The MPIJob for AMD Instinct MI350X and later workers is identical to the MI300X and MI325X example. These GPUs use the gfx950 architecture, so when you build the RCCL Tests Docker image, target gfx950 instead of gfx942. The image must also include the libionic1 package for fabric networking to function correctly. See AMD’s Using RCCL with Docker for build instructions.
Set doks.digitalocean.com/gpu-model in the worker nodeSelector to match your MI350X (or later) worker nodes.