Skip to content

fix(gpu): raise nvidia-cdi-refresh TimeoutStartSec for multi-GPU nodes (GB300) - #9899

Merged
Cameron Meissner (cameronmeissner) merged 1 commit into
mainfrom
xuxue/gpu-cdi-refresh-timeout
Oct 26, 2026
Merged

Cameron Meissner (cameronmeissner) merged 1 commit into
mainfrom
xuxue/gpu-cdi-refresh-timeout

Conversation

@xuexu6666

@xuexu6666 Xu Xue (xuexu6666) commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

Problem

GB200/GB300 managed-driver (--gpu-driver Install) nodes fail to join (CSE exit 84, kubelet never starts) after the aks-gpu-cuda-lts image was built with nvidia-container-toolkit 1.20.1 (aks-gpu #177, first in image tag 580.159.04-20261020182457).

Root cause

nvidia-cdi-refresh.service is Type=oneshot. Toolkit 1.19.1 left it at systemd's oneshot default of TimeoutStartSec=infinity. 1.20.1 ships a new drop-in /usr/lib/systemd/system/nvidia-cdi-refresh.service.d/10-container-engines.conf that orders the container engines after the unit and pins TimeoutStartSec=90s.

On Grace-Blackwell the unit's start is slow:

  • nvidia-smi -L precheck: ~28s (cold, before persistence is warm)
  • nvidia-ctk cdi generate: ~81s (enumerating the GPUs + driver libs/firmware over the arm64 Grace NVLink/nvml path)

Total ~109s > 90s → systemd SIGTERMs it. A timeout is result=timeout (SIGTERM), not an exit code, so the existing SuccessExitStatus=1 2 127 drop-in can't cover it. install.sh's blocking systemctl restart nvidia-cdi-refresh.service then returns non-zero → the aks-gpu install container exits non-zero → retried, but every retry now aborts at nvidia-installer (module already loaded, can't unload on a live GPU node) → retrycmd exhausts → CSE exit 84.

Blast radius

Grace-Blackwell arm64 only (GB200/GB300). x86 is unaffected — measured on a live 8× H200: nvidia-smi -L 0.11s, cdi generate <1s (and on 1.19.1 the unit was TimeoutStartSec=infinity).

Fix

Write TimeoutStartSec=300 to a separate, higher-sorted drop-in 90-aks-cdi-refresh-timeout.conf, arm64-gated (getCPUArch).

The 90- prefix is load-bearing: systemd merges drop-ins in lexical filename order, last wins. The toolkit's 10-container-engines.conf sets 90s, and a 10-aks-* name sorts before it (a < c) and loses — so the override must sort after it. (The existing 10-aks-tolerate-generate-failure.conf is left untouched for SuccessExitStatus; it doesn't conflict with ordering.)

Verified live on a GB300 node: a 10-aks-* timeout drop-in leaves TimeoutStartUSec=1min 30s; the 90- drop-in raises it to 5min. x86 writes no override (stays at the 90s default). Overridable via NVIDIA_CDI_REFRESH_TIMEOUT_START_SEC.

Scope is intentionally limited to the timeout. The components.json bump to the 1.20.1 image is the fleet-exposure event and must land with/after this fix.

Testing

  • ShellSpec cse_config_gpu_spec.sh: 79/79 pass — arm64 asserts the 90- drop-in exists with TimeoutStartSec=300 (and the 10- drop-in has no timeout); x86 asserts the 90- drop-in is not written.
  • shellcheck clean (no new findings).
  • No make generate/testdata churn — drop-ins are written at runtime, not rendered into customData.
  • Live-validated TimeoutStartUSec 90s → 5min on a GB300 node.

@xuexu6666
Xu Xue (xuexu6666) requested review from a team as code owners October 26, 2026 03:08
Copilot AI balanced review requested due to automatic review settings October 26, 2026 03:08
@github-actions

github-actions Bot commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

Windows Unit Test Results

  3 files   18 suites   1m 6s ⏱️
563 tests 563 ✅ 0 💤 0 ❌
585 runs  585 ✅ 0 💤 0 ❌

Results for commit 15ca828.

♻️ This comment has been updated with latest results.

Copilot AI 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.

🟢 Approval recommended

The narrow timeout change preserves existing failure handling, includes a focused regression assertion, and has no identified blocking issues.

No open issues 🎉

What changed in this PR

Raises the NVIDIA CDI refresh startup timeout to prevent slow GPU initialization on GB200/GB300 nodes from failing Linux node provisioning.

Changes:

  • Adds a 300-second default timeout, configurable through NVIDIA_CDI_REFRESH_TIMEOUT_START_SEC, while preserving existing exit-code handling.
  • Adds a ShellSpec assertion for the timeout written to the systemd drop-in.
File Description
spec/​parts/​linux/​cloud-init/​artifacts/​cse_config_gpu_spec.sh Verifies the drop-in includes TimeoutStartSec=300.
parts/​linux/​cloud-init/​artifacts/​cse_config_gpu.sh Writes the configurable timeout and documents its purpose.

Review effort: Balanced

@xuexu6666
Xu Xue (xuexu6666) force-pushed the xuxue/gpu-cdi-refresh-timeout branch from fbcd60b to 1aee110 Compare October 26, 2026 03:13
Copilot AI balanced review requested due to automatic review settings October 26, 2026 03:13

Copilot AI 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.

🟢 Approval recommended

The change is narrowly scoped, preserves x86 behavior, and includes focused regression coverage with no unresolved findings.

No open issues 🎉

Review effort: Balanced

…well (GB300)

nvidia-container-toolkit 1.20.1 (aks-gpu #177) regresses GB200/GB300
managed-driver provisioning. 1.19.1 left this Type=oneshot unit at systemd's
oneshot default of TimeoutStartSec=infinity; 1.20.1 ships
/usr/lib/systemd/system/nvidia-cdi-refresh.service.d/10-container-engines.conf
which orders the container engines after it AND pins TimeoutStartSec=90s. On
Grace-Blackwell the start is slow -- nvidia-ctk cdi generate ~81s over the arm64
Grace NVLink/nvml path plus a cold ~28s nvidia-smi -L precheck (>90s) -- so
systemd SIGTERMs it. A timeout is result=timeout (SIGTERM), not a
SuccessExitStatus code, so install.sh's `systemctl restart` still fails ->
CSE exit 84 -> kubelet never starts -> node never joins.

Write the TimeoutStartSec=300 override to a SEPARATE 90-aks-cdi-refresh-timeout
drop-in (arm64 only). The 90- prefix is load-bearing: systemd merges drop-ins
in lexical filename order (last wins), so the override must sort AFTER the
toolkit's 10-container-engines.conf -- a 10-aks-* name sorts before it and loses
(verified: TimeoutStartUSec stays 90s). Verified live on GB300 that the 90-
drop-in raises TimeoutStartUSec 90s -> 5min. x86 generates in <1s (measured: 8x
H200), so no override is written there. Overridable via
NVIDIA_CDI_REFRESH_TIMEOUT_START_SEC.
@xuexu6666
Xu Xue (xuexu6666) force-pushed the xuxue/gpu-cdi-refresh-timeout branch from 1aee110 to 15ca828 Compare October 26, 2026 03:36
Copilot AI balanced review requested due to automatic review settings October 26, 2026 03:36
@github-actions

Copy link
Copy Markdown
Contributor

Code Coverage

Package Line Rate Health
test 0% ❌
windows 27% ❌
staging_cse_windows Package 1 65% ➖
debug 0% ❌
provisioningscripts 2% ❌
parts_windows Package 1 73% ➖
Summary 38% (1652 / 6834) ❌

@github-actions

Copy link
Copy Markdown
Contributor

Code Coverage

Package Line Rate Health
github.com/Azure/agentbaker/aks-node-controller 73% ➖
github.com/Azure/agentbaker/aks-node-controller/common 100% ✔
github.com/Azure/agentbaker/aks-node-controller/helpers 68% ➖
github.com/Azure/agentbaker/aks-node-controller/parser 88% ✔
github.com/Azure/agentbaker/aks-node-controller/pkg/gpu 100% ✔
github.com/Azure/agentbaker/aks-node-controller/pkg/nodeconfigutils 89% ✔
github.com/Azure/agentbaker/aks-node-controller/utils 0% ❌
github.com/Azure/agentbaker/apiserver 24% ❌
github.com/Azure/agentbaker/cmd 0% ❌
github.com/Azure/agentbaker/cmd/starter 0% ❌
github.com/Azure/agentbaker/fuzz/api 0% ❌
github.com/Azure/agentbaker/hotfix/render-nodecustomdata 35% ❌
github.com/Azure/agentbaker/pkg/agent 78% ➖
github.com/Azure/agentbaker/pkg/agent/datamodel 77% ➖
github.com/Azure/agentbaker/pkg/agent/toggles 0% ❌
github.com/Azure/agentbaker/pkg/vhdbuilder/datamodel 87% ✔
Summary 75% (5980 / 7956) ➖

Copilot AI 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.

🟢 Approval recommended

The narrowly scoped override uses correct drop-in precedence, preserves existing behavior outside arm64, and includes targeted tests.

No open issues 🎉

Review effort: Balanced

@github-actions

Copy link
Copy Markdown
Contributor

Code Coverage

Package Line Rate Health
shellspec spec 29% ❌
Summary 29% (4595 / 16086) ❌

@xuexu6666

Copy link
Copy Markdown
Contributor Author

✅ Validated live on real GB300 (abe2e, toolkit 1.20.1 + this fix)

Ran the GB300 managed-DRA + compute-domain scenario in AgentBaker abe2e on a real GB300 rack (eastus2euap), with the exact toolkit that causes the regression (1.20.1) and this fix applied.

Result: 5/5 GB300 nodes healthy and Ready.

Check Result
nvidia-container-toolkit 1.20.1-1 (the regressing version)
nvidia-cdi-refresh TimeoutStartUSec 5min (fix in effect)
90-aks-cdi-refresh-timeout.conf present yes
CSE exit 84 0
nvidia-smi / driver R580 Open Kernel Module, 4× GB300/node
kubelet / k8s node 5/5 Ready, v1.35.8, kernel 6.14.0-1007-azure-nvidia
managed GPU DRA dra-driver-nvidia-gpu active; gpu.nvidia.com ResourceSlices on all 5 nodes; device-plugin off
compute-domain compute-domain-kubelet-plugin active; compute-domain.nvidia.com ResourceSlices on all 5 nodes

Measured cold cdi-refresh start on GB300: ~137s (service journal: Starting … 19:13:59 → Finished … 19:16:16). That's ~47s past the 90s default 1.20.1 pins, and well within the TimeoutStartSec=300 this PR sets (~2× margin). Warm, it's <1s (nvidia-smi -L 0.07s, nvidia-ctk cdi generate 0.23s) — the ~137s is entirely Grace-Blackwell GPU/nvml/NVLink cold-init on first boot.

Negative control: the same path on 1.20.1 without this fix is TimeoutStartUSec=90s → the ~137s start is SIGTERM'd (result=timeout) → install.sh's systemctl restart fails → CSE exit 84 → node never joins (the original repro).

So on real GB300, the regressing toolkit + this fix → managed driver + DRA + compute-domain all come up clean.

@cameronmeissner
Cameron Meissner (cameronmeissner) merged commit 3ffe873 into main Oct 26, 2026
40 of 42 checks passed
@cameronmeissner
Cameron Meissner (cameronmeissner) deleted the xuxue/gpu-cdi-refresh-timeout branch October 26, 2026 21:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants