|
| 1 | +# GKE GB200 (A4X) Networking Prerequisites |
| 2 | + |
| 3 | +For the **GB200 GKE COS** recipes (`gb200-gke-cos-training`, |
| 4 | +`gb200-gke-cos-training-kubeflow`, `gb200-gke-cos-training-slurm`, and |
| 5 | +`gb200-gke-cos-inference-dynamo`, all on `a4x-highgpu-4g` nodes), |
| 6 | +GPUDirect-RDMA over RoCE enables high-speed inter-node GPU communication on |
| 7 | +GKE. Without it, NCCL has no fabric to use and all-reduce falls back to the |
| 8 | +default network path. |
| 9 | + |
| 10 | +## Infrastructure Prerequisites |
| 11 | + |
| 12 | +GKE clusters must have multi-networking configured before deploying AICR bundles: |
| 13 | + |
| 14 | +- Multi-networking enabled (1 gVNIC + 4 RDMA NICs per `a4x-highgpu-4g` node) |
| 15 | +- `Network` + `GKENetworkParamSet` CRs for the gVNIC and 4 RDMA NICs (cluster-specific |
| 16 | + VPC/subnet values, but fixed object names — see below; not managed by AICR) |
| 17 | +- `nccl-rdma-installer` DaemonSet on GPU nodes (included in the AICR bundle) |
| 18 | + |
| 19 | +The last one ships in the AICR bundle. The first is **cluster provisioning** — |
| 20 | +AICR's `gke-gb200-rdma` health check detects it but does not create it. |
| 21 | + |
| 22 | +### Provisioning multi-networking |
| 23 | + |
| 24 | +These steps are ordered, following Google's |
| 25 | +[A4X custom setup guide](https://docs.cloud.google.com/ai-hypercomputer/docs/create/gke-ai-hypercompute-custom-a4x): |
| 26 | + |
| 27 | +1. **Create the VPCs and subnets** — one dedicated VPC + subnet per NIC, five in |
| 28 | + total (one gVNIC, four RDMA), in the cluster's region. |
| 29 | +2. **Create the cluster** with multi-networking enabled (HIPPO's `GKECluster` CR |
| 30 | + does this via `spec.networks.managed.gb200NetworkStrategy`). |
| 31 | +3. **Create the GPU node pool** on an `a4x-highgpu-4g` machine type, attaching |
| 32 | + the five VPC/subnet pairs as `additionalNodeNetworkConfigs`. |
| 33 | +4. **Apply the `Network` and `GKENetworkParamSet` CRs** — one pair per NIC, |
| 34 | + binding each additional node network into the cluster so pods can reference |
| 35 | + it. Unlike TCPXO (see [GKE TCPXO Networking](gke-tcpxo-networking.md)), the |
| 36 | + **object names are fixed, not cluster-specific**: `gvnic-1` for the gVNIC and |
| 37 | + `rdma-0` through `rdma-3` for the RDMA NICs. Only the `vpc`/`vpcSubnet` fields |
| 38 | + inside each `GKENetworkParamSet` vary per cluster (they name the VPC/subnet |
| 39 | + your cluster actually has): |
| 40 | + |
| 41 | +```yaml |
| 42 | +apiVersion: networking.gke.io/v1 |
| 43 | +kind: GKENetworkParamSet |
| 44 | +metadata: |
| 45 | + name: gvnic-1 |
| 46 | +spec: |
| 47 | + vpc: "PREFIX-gvnic" |
| 48 | + vpcSubnet: "PREFIX-gvnic" |
| 49 | + deviceMode: NetDevice |
| 50 | +--- |
| 51 | +apiVersion: networking.gke.io/v1 |
| 52 | +kind: Network |
| 53 | +metadata: |
| 54 | + name: gvnic-1 |
| 55 | +spec: |
| 56 | + type: "Device" |
| 57 | + parametersRef: |
| 58 | + group: networking.gke.io |
| 59 | + kind: GKENetworkParamSet |
| 60 | + name: gvnic-1 |
| 61 | +``` |
| 62 | +
|
| 63 | + Repeat for `rdma-0` through `rdma-3`, pointing `vpc`/`vpcSubnet` at |
| 64 | + `PREFIX-gpu-nic-{0..3}-gb` (or whatever names your VPCs/subnets were given |
| 65 | + in step 1, with `PREFIX` replaced by your own) — and set |
| 66 | + **`deviceMode: RDMA`** on all four, not `NetDevice` (that value is only |
| 67 | + correct for `gvnic-1` above). |
| 68 | + |
| 69 | +> **The fixed naming is a requirement, not a convention.** AICR's |
| 70 | +> `checks/gke-gb200-rdma/health-check.yaml` asserts these five objects by exact |
| 71 | +> name (`gvnic-1`, `rdma-0`..`rdma-3`), including `spec.deviceMode` and |
| 72 | +> `spec.parametersRef` linkage. A cluster provisioned with different `Network` |
| 73 | +> names passes Google's own setup guide but fails this check — rename to match |
| 74 | +> before running `aicr validate`. |
| 75 | + |
| 76 | +AICR installs the `nccl-rdma-installer` DaemonSet and detects the CRs; it does |
| 77 | +not provision the networking itself. These steps are a summary of the |
| 78 | +prerequisite AICR depends on, not a complete provisioning runbook — follow |
| 79 | +Google's guide above for the full procedure, including firewall rules and |
| 80 | +supported GKE version floors. |
| 81 | + |
| 82 | +Separately from GKE's own networking version floor, all AICR GB200 GKE |
| 83 | +recipes (including `gb200-gke-cos-training-slurm`, which inherits it from |
| 84 | +`gb200-gke-cos-training`) enforce `K8s.server.version >= 1.34`: NVLS |
| 85 | +provisions the IMEX channel through a DRA `ComputeDomain`, which requires |
| 86 | +the GA `resource.k8s.io/v1` API. `aicr validate` fails readiness on an |
| 87 | +older control plane with this constraint by name. |
| 88 | + |
| 89 | +### Verifying |
| 90 | + |
| 91 | +```shell |
| 92 | +kubectl get network.networking.gke.io |
| 93 | +kubectl get gkenetworkparamset.networking.gke.io |
| 94 | +``` |
| 95 | + |
| 96 | +Expect `gvnic-1` and `rdma-0` through `rdma-3` — the five prerequisite |
| 97 | +`Network`s from step 4 — each bound to its `GKENetworkParamSet` via |
| 98 | +`spec.parametersRef`. Fewer than five, or a `GKENetworkParamSet` with the |
| 99 | +wrong `deviceMode`, means the prerequisite is incomplete or misconfigured — |
| 100 | +`aicr validate` (via the `gke-gb200-rdma` health check) reports the |
| 101 | +shortfall by name. |
| 102 | + |
| 103 | +You'll also see a `default` network/`GKENetworkParamSet` pair in the same |
| 104 | +output — that one is GKE-managed (created automatically once |
| 105 | +multi-networking is enabled), not part of this prerequisite, and isn't |
| 106 | +checked by name. |
| 107 | + |
| 108 | +## Driver Installer |
| 109 | + |
| 110 | +`a4x-highgpu-4g` recipes generated with `--profile gpuStack=driver-installer` |
| 111 | +(see [GKE GPU Setup](gke-gpu-setup.md#alternative-let-gpu-operator-manage-the-device-plugin)) |
| 112 | +need Google's standalone `nvidia-driver-installer` DaemonSet applied before |
| 113 | +GPU workloads can schedule — this presumes the node-pool prerequisite |
| 114 | +(pools created with `gpu-driver-version=disabled` plus the |
| 115 | +`gke-no-default-nvidia-gpu-device-plugin=true` label) is already in place. |
| 116 | +GB200's NVL72 domain needs GPU partitioning that Google's generic upstream |
| 117 | +COS manifest doesn't include — use a manifest with an added |
| 118 | +`partition-gpus` init container pinned to a |
| 119 | +[COS-qualified driver version](https://cloud.google.com/kubernetes-engine/docs/how-to/gpus#cos): |
| 120 | + |
| 121 | +```yaml |
| 122 | +apiVersion: apps/v1 |
| 123 | +kind: DaemonSet |
| 124 | +metadata: |
| 125 | + name: nvidia-driver-installer |
| 126 | + namespace: kube-system |
| 127 | + labels: |
| 128 | + k8s-app: nvidia-driver-installer |
| 129 | +spec: |
| 130 | + selector: |
| 131 | + matchLabels: |
| 132 | + k8s-app: nvidia-driver-installer |
| 133 | + updateStrategy: |
| 134 | + type: RollingUpdate |
| 135 | + template: |
| 136 | + metadata: |
| 137 | + labels: |
| 138 | + name: nvidia-driver-installer |
| 139 | + k8s-app: nvidia-driver-installer |
| 140 | + spec: |
| 141 | + priorityClassName: system-node-critical |
| 142 | + affinity: |
| 143 | + nodeAffinity: |
| 144 | + requiredDuringSchedulingIgnoredDuringExecution: |
| 145 | + nodeSelectorTerms: |
| 146 | + - matchExpressions: |
| 147 | + - key: cloud.google.com/gke-accelerator |
| 148 | + operator: Exists |
| 149 | + - key: cloud.google.com/gke-gpu-driver-version |
| 150 | + operator: DoesNotExist |
| 151 | + - key: gke-no-default-nvidia-gpu-device-plugin |
| 152 | + operator: In |
| 153 | + values: ["true"] |
| 154 | + - key: cloud.google.com/gke-confidential-nodes-instance-type |
| 155 | + operator: DoesNotExist |
| 156 | + tolerations: |
| 157 | + - operator: Exists |
| 158 | + hostNetwork: true |
| 159 | + hostPID: true |
| 160 | + volumes: |
| 161 | + - name: dev |
| 162 | + hostPath: |
| 163 | + path: /dev |
| 164 | + - name: vulkan-icd-mount |
| 165 | + hostPath: |
| 166 | + path: /home/kubernetes/bin/nvidia/vulkan/icd.d |
| 167 | + - name: nvidia-install-dir-host |
| 168 | + hostPath: |
| 169 | + path: /home/kubernetes/bin/nvidia |
| 170 | + - name: root-mount |
| 171 | + hostPath: |
| 172 | + path: / |
| 173 | + - name: cos-tools |
| 174 | + hostPath: |
| 175 | + path: /var/lib/cos-tools |
| 176 | + - name: nvidia-config |
| 177 | + hostPath: |
| 178 | + path: /etc/nvidia |
| 179 | + initContainers: |
| 180 | + - image: "cos-nvidia-installer:fixed" |
| 181 | + imagePullPolicy: Never |
| 182 | + name: nvidia-driver-installer |
| 183 | + resources: |
| 184 | + requests: |
| 185 | + cpu: 150m |
| 186 | + securityContext: |
| 187 | + privileged: true |
| 188 | + env: |
| 189 | + - name: NVIDIA_INSTALL_DIR_HOST |
| 190 | + value: /home/kubernetes/bin/nvidia |
| 191 | + - name: NVIDIA_INSTALL_DIR_CONTAINER |
| 192 | + value: /usr/local/nvidia |
| 193 | + - name: VULKAN_ICD_DIR_HOST |
| 194 | + value: /home/kubernetes/bin/nvidia/vulkan/icd.d |
| 195 | + - name: VULKAN_ICD_DIR_CONTAINER |
| 196 | + value: /etc/vulkan/icd.d |
| 197 | + - name: ROOT_MOUNT_DIR |
| 198 | + value: /root |
| 199 | + - name: COS_TOOLS_DIR_HOST |
| 200 | + value: /var/lib/cos-tools |
| 201 | + - name: COS_TOOLS_DIR_CONTAINER |
| 202 | + value: /build/cos-tools |
| 203 | + volumeMounts: |
| 204 | + - name: nvidia-install-dir-host |
| 205 | + mountPath: /usr/local/nvidia |
| 206 | + - name: vulkan-icd-mount |
| 207 | + mountPath: /etc/vulkan/icd.d |
| 208 | + - name: dev |
| 209 | + mountPath: /dev |
| 210 | + - name: root-mount |
| 211 | + mountPath: /root |
| 212 | + - name: cos-tools |
| 213 | + mountPath: /build/cos-tools |
| 214 | + command: |
| 215 | + - bash |
| 216 | + - -c |
| 217 | + - | |
| 218 | + echo "Checking for existing GPU driver modules" |
| 219 | + if lsmod | grep nvidia; then |
| 220 | + echo "GPU driver is already installed, skipping installation" |
| 221 | + exit 0 |
| 222 | + else |
| 223 | + echo "No GPU driver module detected, installing 580.126.20" |
| 224 | + /cos-gpu-installer install --version=580.126.20 || exit 1 |
| 225 | + chmod 755 /root/home/kubernetes/bin/nvidia |
| 226 | + fi |
| 227 | + - image: "gcr.io/gke-release/nvidia-partition-gpu@sha256:de12f85ebfb4fb6c1893cd30c23aab662a72fa0448f97ef74fccb82d7522ef17" |
| 228 | + name: partition-gpus |
| 229 | + env: |
| 230 | + - name: LD_LIBRARY_PATH |
| 231 | + value: /usr/local/nvidia/lib64 |
| 232 | + resources: |
| 233 | + requests: |
| 234 | + cpu: 150m |
| 235 | + securityContext: |
| 236 | + privileged: true |
| 237 | + volumeMounts: |
| 238 | + - name: nvidia-install-dir-host |
| 239 | + mountPath: /usr/local/nvidia |
| 240 | + - name: dev |
| 241 | + mountPath: /dev |
| 242 | + - name: nvidia-config |
| 243 | + mountPath: /etc/nvidia |
| 244 | + containers: |
| 245 | + - image: "gke.gcr.io/pause:3.8@sha256:880e63f94b145e46f1b1082bb71b85e21f16b99b180b9996407d61240ceb9830" |
| 246 | + name: pause |
| 247 | +``` |
| 248 | + |
| 249 | +Re-pin the driver version (`580.126.20` above) and the `partition-gpus` image |
| 250 | +digest to whatever your GKE version's COS driver table and Google's release |
| 251 | +notes currently list — both drift over time and are not managed by AICR. |
| 252 | + |
| 253 | +## Storage Prerequisites |
| 254 | + |
| 255 | +`a4x-highgpu-4g` nodes reject the `pd-balanced` disk type that GKE's default |
| 256 | +StorageClass (`standard-rwo`) provisions: `pd-balanced disk type cannot be |
| 257 | +used by a4x-highgpu-4g machine type`. Any PVC scheduled onto a GB200 node — |
| 258 | +notably the `inference-perf` validator's model-weights cache |
| 259 | +(`AICR_INFERENCE_PERF_MODEL_CACHE_STORAGE_CLASS`, see |
| 260 | +[Validation](../user/validation.md)) — needs a Hyperdisk-backed StorageClass |
| 261 | +instead. Like the RDMA CRs above, this is a cluster prerequisite AICR does |
| 262 | +not provision: |
| 263 | + |
| 264 | +```yaml |
| 265 | +apiVersion: storage.k8s.io/v1 |
| 266 | +kind: StorageClass |
| 267 | +metadata: |
| 268 | + name: hyperdisk-balanced |
| 269 | +provisioner: pd.csi.storage.gke.io |
| 270 | +parameters: |
| 271 | + type: hyperdisk-balanced |
| 272 | +volumeBindingMode: WaitForFirstConsumer |
| 273 | +allowVolumeExpansion: true |
| 274 | +``` |
| 275 | + |
| 276 | +Apply it once per cluster, then point the validator's model cache at it via |
| 277 | +an `AICR_INFERENCE_PERF_MODEL_CACHE_STORAGE_CLASS=hyperdisk-balanced` entry |
| 278 | +on the `inference-perf` catalog entry's `env` (or a catalog overlay in the |
| 279 | +`aicr validate --data <dir>` directory). |
| 280 | + |
| 281 | +## Running the NCCL Benchmark |
| 282 | + |
| 283 | +The GB200 GKE training recipe (`gb200-gke-cos-training`) selects the |
| 284 | +NVLS-variant performance check (`nccl-all-reduce-bw-nvls`) — MNNVL across the |
| 285 | +A4X nodes' IMEX domain is the fabric that carries all-reduce traffic; gIB is the |
| 286 | +transport driver underneath, not the NCCL algorithm itself. Run it via: |
| 287 | + |
| 288 | +```shell |
| 289 | +aicr validate --recipe recipes/overlays/gb200-gke-cos-training.yaml \ |
| 290 | + --phase performance |
| 291 | +``` |
| 292 | + |
| 293 | +## References |
| 294 | + |
| 295 | +- [GKE A4X custom setup guide](https://docs.cloud.google.com/ai-hypercomputer/docs/create/gke-ai-hypercompute-custom-a4x) |
| 296 | +- [Component Catalog](../user/component-catalog.md) |
| 297 | +- [Validation readiness gate](../user/validation.md) |
| 298 | +- [GKE TCPXO Networking](gke-tcpxo-networking.md) |
0 commit comments