fix(e2e): don't fail scriptless phase 3 on VHD-sourced GPU env skew - #9244
fix(e2e): don't fail scriptless phase 3 on VHD-sourced GPU env skew#9244Ganeshkumar Ashokavardhanan (ganeshkumarashok) wants to merge 1 commit into
Conversation
ValidateScriptlessPhase3 compares the env vars produced by two paths that
have different sources of truth:
- provision-config reads /opt/azure/components.json, which is baked into
the VHD by vhdbuilder/packer/install-dependencies.sh
- nbc-cmd is generated from the AgentBaker source under test
These only agree when the VHD was built from the same source. E2E
deliberately does not do that: config.SIGVersionTagValue defaults to
"refs/heads/main", so a PR's code always runs against the newest VHD built
from main.
The consequence is that any PR bumping a GPU driver version in
parts/common/components.json fails phase 3 with exactly:
env var differences (2): differs: GPU_DRIVER_VERSION; differs: GPU_IMAGE_SHA
and cannot be fixed before merge, because the matching VHD can only be built
after merge. This is a deadlock, not a regression in the change under test.
It was hit by the aks-gpu-grid 570.237 bump (GPU E2E build 176997071), where
the node otherwise provisioned cleanly (CSE exit code 0, nvidia-modprobe
started, aks-gpu-grid:570.237-20260817204535 pulled and run) and
Test_Ubuntu2404_GPUA10 passed on the same driver. No GPU driver bump had
landed since phase 3 was enabled in #8453, so this is the first PR to hit it.
Differences confined to GPU_DRIVER_VERSION/GPU_IMAGE_SHA are now tolerated
and logged. Any other differing var still fails, and the "no differences"
marker is still required to be absent before any tolerance applies. If the
marker is missing and no diff entries can be parsed, that now fails
explicitly instead of being silently accepted.
Production behaviour is unchanged: aks-node-controller still reports the
full diff, including these vars, as a guest agent event for Kusto.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: e525ff6d-7072-4f71-92b9-4d5a87808b20
Windows Unit Test Results 3 files 12 suites 47s ⏱️ Results for commit c466e61. |
There was a problem hiding this comment.
Pull request overview
Adjusts the scriptless phase 3 E2E env-var comparison so GPU driver/image metadata that is intentionally VHD-sourced (from /opt/azure/components.json) no longer deadlocks GPU driver bump PRs, while keeping strict failures for any other unexpected env drift.
Changes:
- Adds parsing for
compareEnvsdiff markers and tolerates diffs confined toGPU_DRIVER_VERSIONandGPU_IMAGE_SHA. - Tightens the failure mode when the “no differences found” marker is absent but no diff entries can be parsed (explicit fail).
- Adds unit tests covering diff parsing, de-duplication, noise handling, and the real GPU-bump log line.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| e2e/validators.go | Parses env-compare diff entries and tolerates VHD-sourced GPU env skew while still failing on any other diffs. |
| e2e/validators_envcompare_test.go | Adds focused tests to validate parsing and ensure GPU-bump diffs are tolerated end-to-end. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
CI status: the two red checks are pre-existing infra flakes, not caused by this changeThis PR changes only
|
|
| line | step |
|---|---|
| 418-424 | DialSSHOverBastion(...) ← fixed budget: 5 attempts x 30s timeout + 4 x 10s backoff = 190s |
| 425-427 | create-operation error check |
| 429-432 | // Wait for VM to be in "Running" power state before proceedingwaitForVMRunningState(...) ← waits up to 3 min |
So we SSH into a VM whose power state we haven't yet waited for, and the hard-coded 190s dial budget expires before the patient waitForVMRunningState on the next line ever runs.
This scenario uses Standard_NC48ads_A100_v4 (2x A100, 48 vCPU). Boot on that SKU routinely exceeds 190s from VMSS-create, so the dial exhausts and the test hard-fails. failed to get reader: context deadline exceeded is exactly the signature of the bastion websocket opening while the target's sshd is not yet listening.
Note the scenario already declares WaitForSSHAfterReboot: 5 * time.Minute — but that only applies to RebootVMAndWaitForSSH (validators.go:328), not to this initial dial. The author's "this VM is slow" intent isn't honored on first connect.
Not a regression from #9165 or this PR
git blame shows the dial was inserted at these lines on 2026-01-20, placed above the pre-existing waitForVMRunningState (2025-11-07). #9165 fixed a different bastion fault (403 / EnableIPConnect on the shared bastion). This one is latent and only bites the slowest SKUs, which is why it looks intermittent — suli's runs show MIG_MultiGPU passing and MIG_Mixed failing, i.e. right at the margin.
Suggested fix (separate PR)
Reorder so waitForVMRunningState precedes the dial, and drive DialSSHOverBastion from a deadline rather than a fixed attempt count so slow GPU SKUs get a realistic budget.
Retrying this PR's GPU gate won't clear it — the fix has to land separately. Recommend not blocking this PR on that test.
Problem
Any PR that bumps a GPU driver version in
parts/common/components.jsoncurrently cannot passAgentbaker GPU E2E, and cannot be fixed before merge.ValidateScriptlessPhase3requires zero env var differences between two paths that have different sources of truth:GPU_DRIVER_VERSIONprovision-config/opt/azure/components.json, baked into the VHD byvhdbuilder/packer/install-dependencies.shnbc-cmdThese only agree when the VHD was built from that same source. E2E deliberately does not do that —
e2e/config/config.go:So a PR's code always runs against the newest VHD built from
main. A PR that changes a GPU driver version therefore always produces:The matching VHD can only be built after merge, so this is a deadlock rather than a regression in the change under test.
Evidence
Hit by the aks-gpu-grid 570.237 bump (#9229), GPU E2E build 176997071, scenario
Test_Ubuntu2204_GPUA10— failed identically on the initial run and both re-runs.The node was otherwise completely healthy:
mcr.microsoft.com/aks/aks-gpu-grid:570.237-20260817204535nvidia-modprobeenabled and started successfullyTest_Ubuntu2404_GPUA10passed on the very same new driver (it does not run the phase 3 comparison)No GPU driver bump had landed since phase 3 was enabled in #8453 (2026-06-11), which is why this is the first PR to hit it.
Fix
Tolerate differences confined to the VHD-sourced GPU vars, and log them. Everything else still fails:
Production behaviour is unchanged.
aks-node-controller'scompareEnvsstill computes and reports the full diff — including these vars — as a guest agent event for Kusto.I deliberately did not add these vars to
isExpectedDiffCSEVarinaks-node-controller/app.go, since that would suppress the production observability signal. The artificial condition belongs to E2E, so the tolerance belongs in E2E.Tests
New
e2e/validators_envcompare_test.go, built around the exact log line from build 176997071:differs,only-in-pc,only-in-nbc)All pass, and
go vet ./...is clean ine2e/.Follow-up
Unblocks #9229 (aks-gpu-grid 570.237 bump), which will be rebased on this once merged.