Skip to content

fix(validators): make GKE NCCL node selector dynamic#1262

Merged
yuanchen8911 merged 1 commit into
NVIDIA:mainfrom
xdu31:fix/nccl-bw-1256
Jun 10, 2026
Merged

fix(validators): make GKE NCCL node selector dynamic#1262
yuanchen8911 merged 1 commit into
NVIDIA:mainfrom
xdu31:fix/nccl-bw-1256

Conversation

@xdu31

@xdu31 xdu31 commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes the GKE NCCL all-reduce bandwidth validator to dynamically discover the cloud.google.com/gke-accelerator label from target nodes instead of hardcoding nvidia-h100-mega-80gb. Now fails explicitly when GKE nodes have missing or mixed accelerator labels to prevent WorkerCount divergence.

Motivation / Context

The NCCL validator hardcoded cloud.google.com/gke-accelerator=nvidia-h100-mega-80gb in platformWorkerScheduling, so worker pods could only schedule on a3-megagpu-8g nodes. Any GKE H100 SKU with a different accelerator label (e.g. a3-highgpu-1g with nvidia-h100-80gb) failed at scheduling.

Additionally, when GKE nodes had missing or mixed accelerator labels, the code silently fell through with no nodeSelector while WorkerCount was sized from config.Nodes. This could cause worker placement to diverge from the counted cohort, leading to invalid bandwidth measurements.

Fixes: #1256

Type of Change

  • Bug fix (non-breaking change that fixes an issue)

Component(s) Affected

  • Validator (pkg/validator)

Implementation Notes

  • Added commonGKEAccelerator(nodes []v1.Node) string helper that returns the cloud.google.com/gke-accelerator label shared by all nodes, or "" when nodes disagree or any node lacks the label (mirrors commonGPUProduct for OKE).
  • Modified platformWorkerScheduling() signature to return (map[string]string, []v1.Toleration, error) instead of just the first two values.
  • GKE branch now fails explicitly (returns error) when commonGKEAccelerator() returns "", preventing silent WorkerCount/scheduling divergence.
  • Error message uses the gkeAcceleratorLabel constant as requested in review.
  • Updated all call sites and tests to handle the new error return.

Testing

golangci-lint run -c .golangci.yaml ./validators/performance/...  # 0 issues
go test ./validators/performance/...                              # ok (all tests pass)

Updated TestPlatformWorkerScheduling:

  • Existing homogeneous-label cases (a3-megagpu-8g, a3-highgpu-1g) updated to handle error return
  • Previous "missing label" test now expects error instead of nil selector
  • Previous "mixed-SKU pool" test now expects error instead of nil selector

Risk Assessment

  • Low — Isolated change to one validator package. Changes function signature from (ns, tols) to (ns, tols, err) but this is an internal function. GKE nodes with homogeneous accelerator labels work as before; mixed/missing labels now fail fast instead of silently diverging.

Rollout notes: N/A — non-breaking for valid clusters. Clusters with mixed/missing GKE accelerator labels will now fail explicitly with a clear error message instead of silently producing invalid results.

Checklist

  • Tests pass locally (go test ./validators/performance/...)
  • Linter passes (golangci-lint on changed packages)
  • I did not skip/disable tests to make CI green
  • I added/updated tests for new functionality
  • I updated docs if user-facing behavior changed — N/A, no user-facing surface changed
  • Changes follow existing patterns in the codebase (mirrors commonGPUProduct)

@coderabbitai

coderabbitai Bot commented Jun 9, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Training overlay manifests received explanatory comments describing the calibrated nccl-all-reduce-bw absolute floor. The validator added a package constant gkeAcceleratorLabel. platformWorkerScheduling now returns (nodeSelector, tolerations, error), derives a GKE cloud.google.com/gke-accelerator selector via commonGKEAccelerator, and returns an ErrCodeInvalidRequest when the label is missing or inconsistent; OKE and other branches were adjusted to the new signature. Tests were updated and a table test for commonGKEAccelerator was added.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • NVIDIA/aicr#1233: Both PRs modify validators/performance/nccl_all_reduce_bw_constraint.go around worker scheduling and related helper logic.

Suggested labels

size/M

Suggested reviewers

  • mchmarny
  • njhensley
🚥 Pre-merge checks | ✅ 3 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Linked Issues check ❓ Inconclusive The PR partially addresses issue #1256 by fixing the GKE-specific hardcoded accelerator label problem but does not comprehensively implement the full fabric/transport-class-aware solution proposed in the issue. While this PR fixes the immediate GKE hardcoding issue (#1256's secondary concern), the broader objectives—making validators fabric-aware, fixing false-fails on smaller SKUs, and aligning declared-but-skipping overlays—require additional follow-up work.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly describes the main change: making GKE NCCL node selector dynamic instead of hardcoded.
Description check ✅ Passed The description is related to the changeset, explaining the motivation, implementation, testing, and risk assessment for the dynamic node selector changes.
Out of Scope Changes check ✅ Passed All changes are directly related to fixing the GKE NCCL node selector discovery and error handling, with no unrelated modifications.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

mchmarny
mchmarny previously approved these changes Jun 9, 2026

@mchmarny mchmarny left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clean fix. The discoverGKENodeConfig helper faithfully mirrors discoverEKSNodeConfig — same single-node-read pattern, same ErrCodeInternal for a missing label, same config.Nodes[0] call site (safe: determineGPUConfig guarantees a non-empty slice before returning). platformWorkerScheduling thread-through is correct; the gkeAccelerator zero-value-when-not-GKE pattern matches instanceType for EKS. Tests are table-driven and cover both valid SKUs plus the missing-label path. CI is fully green.

One nit inline (use the gkeAcceleratorLabel constant in the error message). Two mechanics items before merge:

  • Missing type label: add bug (per PR policy — type labels aren't auto-assigned).
  • Branch is behind main: rebase + squash before merging.

"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/client-go/dynamic"
)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: the error message duplicates the label string that's already in the gkeAcceleratorLabel constant one line above. fmt.Sprintf("GPU node missing %s label", gkeAcceleratorLabel) avoids the drift risk if the label name ever changes.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch — and self-resolved by the rebase. The new commit removes discoverGKENodeConfig entirely; the GKE lookup now happens inline in platformWorkerScheduling and uses the gkeAcceleratorLabel constant directly (matches the OKE pattern added in #1233). No more duplication to drift on.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@validators/performance/nccl_all_reduce_bw_constraint.go`:
- Around line 845-855: Ensure GKE accelerator labels are homogeneous before
deriving a nodeSelector: instead of using only nodes[0] in the
recipe.CriteriaServiceGKE branch, iterate over the target node slice
(nodes/config.Nodes and any place WorkerCount is sized) and verify every node
has a non-empty labels[gkeAcceleratorLabel] and that all values are identical;
if any node is missing the label or labels differ, fail fast (return an error)
rather than silently selecting the first node’s label and creating a selector
that may not match the full WorkerCount. Update the logic around nodeSelector,
the homogeneity check, and error handling in the same function where
recipe.CriteriaServiceGKE, nodes, WorkerCount, and gkeAcceleratorLabel are
referenced.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: 42ce4ad8-7f3c-4816-9766-271f13073655

📥 Commits

Reviewing files that changed from the base of the PR and between 513d7d7 and 7892188.

📒 Files selected for processing (5)
  • recipes/overlays/h100-eks-training.yaml
  • recipes/overlays/h100-gke-cos-training.yaml
  • validators/performance/nccl_all_reduce_bw_constraint.go
  • validators/performance/nccl_gke_utils.go
  • validators/performance/nccl_test.go

Comment thread validators/performance/nccl_all_reduce_bw_constraint.go Outdated
@xdu31 xdu31 force-pushed the fix/nccl-bw-1256 branch from 970a494 to 6c6ae1c Compare June 9, 2026 23:31
@xdu31 xdu31 requested a review from mchmarny June 10, 2026 00:03
Comment thread validators/performance/nccl_all_reduce_bw_constraint.go Outdated

@yuanchen8911 yuanchen8911 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Requesting changes on two items (details in the inline comment and review above):

  1. Mixed/missing GKE accelerator labels fail open in platformWorkerScheduling — when commonGKEAccelerator(nodes) returns "" on a non-empty GKE target set, no nodeSelector is emitted while WorkerCount/GPUCountPerNode were sized from config.Nodes, so worker placement can diverge from the counted cohort and the bandwidth result is measured against a mismatched set instead of erroring. Please fail closed (error on a mixed/missing set, mirroring narrowByAccelerator's zero-match error) or narrow the counted node set to the selected cohort.

  2. The PR description is stale — it references discoverGKENodeConfig, a new gkeAccelerator parameter, and TestDiscoverGKENodeConfig that don't exist; the code adds commonGKEAccelerator with an unchanged platformWorkerScheduling signature. Please update the description before merge.

Open question: do heterogeneous H100 GKE pools (a3-megagpu-8g + a3-highgpu-1g) occur in supported deployments? If pools are always single-SKU, item 1 is latent and can be deferred to #1256; if mixed pools are realistic, the fail-closed guard belongs in this PR.

@github-actions github-actions Bot added size/L and removed size/M labels Jun 10, 2026
@xdu31

xdu31 commented Jun 10, 2026

Copy link
Copy Markdown
Contributor Author

Updated to address review comments:

Fixed:
✅ Made platformWorkerScheduling fail when GKE nodes have missing/mixed cloud.google.com/gke-accelerator labels (prevents WorkerCount divergence)
✅ Error message uses gkeAcceleratorLabel constant as requested
✅ Updated PR description (removed references to non-existent discoverGKENodeConfig, gkeAccelerator parameter, and TestDiscoverGKENodeConfig)
✅ All tests pass

Label issue:
❌ Cannot add bug label — it doesn't exist in the repo label list. The closest available labels are invalid or needs-triage. Should I use one of those, or can you add the bug label?

Branch status:
Branch is behind main — will rebase + squash once approved.

@xdu31 xdu31 force-pushed the fix/nccl-bw-1256 branch from a9cbb65 to 79009f8 Compare June 10, 2026 01:02

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@validators/performance/nccl_all_reduce_bw_constraint.go`:
- Around line 857-860: Replace the fmt.Errorf usage in the error return after
commonGKEAccelerator(nodes) with the structured error constructor aicrErrors.New
using ErrCodeInvalidRequest: change the return that currently uses
fmt.Errorf("GKE nodes have missing or mixed %s labels — cannot derive a
nodeSelector that matches the full WorkerCount cohort", gkeAcceleratorLabel) to
return aicrErrors.New(aicrErrors.ErrCodeInvalidRequest, "<same message with
gkeAcceleratorLabel>") so the error carries the proper code; update the error
return site in the function containing acc := commonGKEAccelerator(nodes) and
ensure callers (notably the caller referenced in the review) will be adjusted to
propagate the structured error directly rather than re-wrapping it.
- Around line 602-605: The call site around platformWorkerScheduling currently
wraps returned errors with aicrErrors.Wrap; once platformWorkerScheduling is
changed to return structured aicrErrors (per the upstream change), remove the
extra wrapping and propagate the error directly (i.e., return the original err
from the function instead of re-wrapping), leaving the
defaultNodeSelector/defaultTolerations assignment and only handling nil-case
locally; update the code that does return aicrErrors.Wrap(...) to simply return
nil, err so structured codes are preserved.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: 8b9da964-1d75-4b40-bb61-9a8dafe43735

📥 Commits

Reviewing files that changed from the base of the PR and between 3d2d917 and 79009f8.

📒 Files selected for processing (2)
  • validators/performance/nccl_all_reduce_bw_constraint.go
  • validators/performance/nccl_test.go

Comment thread validators/performance/nccl_all_reduce_bw_constraint.go
Comment thread validators/performance/nccl_all_reduce_bw_constraint.go
yuanchen8911
yuanchen8911 previously approved these changes Jun 10, 2026

@yuanchen8911 yuanchen8911 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, both findings are fixed. Two minor issues from CodeRabbit remain unresolved.

@copy-pr-bot

copy-pr-bot Bot commented Jun 10, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@validators/performance/nccl_all_reduce_bw_constraint.go`:
- Around line 859-860: Replace the error code used when GKE nodes have
missing/mixed accelerator labels: in the return that currently calls
aicrErrors.New(aicrErrors.ErrCodeInvalidRequest, fmt.Sprintf(...,
gkeAcceleratorLabel)), change ErrCodeInvalidRequest to
aicrErrors.ErrCodeInternal so the error matches other cluster-state validation
failures (see nearby checks like the ones that report "node selector matches
zero nodes" and "no nodes match accelerator").
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: 898ecd04-9512-4b1b-a3a8-19e9e129592a

📥 Commits

Reviewing files that changed from the base of the PR and between 79009f8 and e5a0a09.

📒 Files selected for processing (1)
  • validators/performance/nccl_all_reduce_bw_constraint.go

Comment on lines +859 to +860
return nil, nil, aicrErrors.New(aicrErrors.ErrCodeInvalidRequest,
fmt.Sprintf("GKE nodes have missing or mixed %s labels — cannot derive a nodeSelector that matches the full WorkerCount cohort", gkeAcceleratorLabel))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Use ErrCodeInternal instead of ErrCodeInvalidRequest for consistency.

The missing/mixed GKE accelerator label is a cluster-state validation failure (discovered condition) rather than a malformed user request. Other cluster-state errors in this file use ErrCodeInternal: line 405 (node selector matches zero nodes), line 441 (no nodes match accelerator), line 515 (no schedulable GPU nodes), and line 531 (no GPUs found). ErrCodeInvalidRequest is reserved for user-input parsing failures (lines 204, 337, 623). For consistency and correct error classification, use ErrCodeInternal here.

🔧 Proposed fix
 		acc := commonGKEAccelerator(nodes)
 		if acc == "" {
-			return nil, nil, aicrErrors.New(aicrErrors.ErrCodeInvalidRequest,
+			return nil, nil, aicrErrors.New(aicrErrors.ErrCodeInternal,
 				fmt.Sprintf("GKE nodes have missing or mixed %s labels — cannot derive a nodeSelector that matches the full WorkerCount cohort", gkeAcceleratorLabel))
 		}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@validators/performance/nccl_all_reduce_bw_constraint.go` around lines 859 -
860, Replace the error code used when GKE nodes have missing/mixed accelerator
labels: in the return that currently calls
aicrErrors.New(aicrErrors.ErrCodeInvalidRequest, fmt.Sprintf(...,
gkeAcceleratorLabel)), change ErrCodeInvalidRequest to
aicrErrors.ErrCodeInternal so the error matches other cluster-state validation
failures (see nearby checks like the ones that report "node selector matches
zero nodes" and "no nodes match accelerator").

@yuanchen8911 yuanchen8911 self-requested a review June 10, 2026 20:12
yuanchen8911
yuanchen8911 previously approved these changes Jun 10, 2026

@yuanchen8911 yuanchen8911 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/lgtm

@yuanchen8911 yuanchen8911 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

need another rebase

@yuanchen8911 yuanchen8911 enabled auto-merge (squash) June 10, 2026 21:52
Derive the GKE NCCL all-reduce node selector from observed node
accelerator labels instead of a hardcoded value, and fail with a
structured error when nodes have missing or mixed accelerator labels.
@github-actions

Copy link
Copy Markdown
Contributor

Recipe evidence check

Affected leaf overlays: 7

Recipe Pointer Verify Digest match
h100-eks-training ⚠️ missing
h100-eks-ubuntu-training-kubeflow ⚠️ missing
h100-eks-ubuntu-training-slurm ⚠️ missing
h100-eks-ubuntu-training ⚠️ missing
h100-gke-cos-training-kubeflow ⚠️ missing
h100-gke-cos-training-slurm ⚠️ missing
h100-gke-cos-training ⚠️ missing

How to refresh evidence

Run on a cluster matching the recipe's criteria:

aicr snapshot -o snapshot.yaml
aicr validate \
  -r recipes/overlays/<slug>.yaml \
  -s snapshot.yaml \
  --emit-attestation ./out \
  --push ghcr.io/<your-fork>/aicr-evidence
cp ./out/pointer.yaml recipes/evidence/<slug>.yaml

This gate is warning-only and never blocks merge. See ADR-007 for the trust model.

@yuanchen8911 yuanchen8911 merged commit 90b1292 into NVIDIA:main Jun 10, 2026
209 of 211 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

nccl-all-reduce-bw training gate is a fixed absolute fabric-specific busbw value applied to SKU-agnostic recipes → false-fails EKS/H100 small SKUs

3 participants