fix(server): refresh the device cache on every watch tick - #130
Conversation
|
@pescn: The label(s) DetailsIn response to this:
Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (3)
Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review. 📝 WalkthroughWalkthroughThe server now refreshes device state on every timer tick, fingerprints device UUIDs and health states, republishes changed device lists, bounds update delivery, and preserves registration progress when no ListAndWatch consumer is connected. Tests cover recovery, late discovery, steady state, and shutdown behavior. ChangesDevice state republishing
Estimated code review effort: 3 (Moderate) | ~25 minutes Merge Risk: ⚪ Minimal · up to This localized change refreshes device state and republishes updates when needed; no actionable merge-blocking risk remains after normal checks and review. Sequence Diagram(s)sequenceDiagram
participant watchAndRegister
participant AscendManager
participant ListAndWatch
participant NodeRegistration
watchAndRegister->>AscendManager: UpdateDevice on each timer tick
AscendManager-->>watchAndRegister: Current device state
watchAndRegister->>ListAndWatch: Publish when fingerprint changes
watchAndRegister->>NodeRegistration: Register current device state
Possibly related PRs
Suggested labels: Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
watchAndRegister refreshed the cached device view only while GetUnHealthIDs() reported at least one unhealthy device. When a device was unhealthy as the plugin started and recovered shortly afterwards, that condition was already false on the next iteration, so the cache kept the startup snapshot forever and no further ListAndWatch response was ever sent. kubelet therefore stayed on the device list it received at startup. On a node that booted while the driver was still initialising, every device stayed Unhealthy, the node advertised no allocatable devices, and Pods failed admission with "Allocate failed due to no healthy devices present" even though npu-smi reported all devices healthy. The same condition kept a partially enumerated device list from ever growing. Only restarting the Pod, which calls UpdateDevice() again in Start(), recovered the node. Refresh the cache on every iteration and publish a ListAndWatch update whenever the device set changes, in either direction. A fingerprint over the published device UUIDs and their health keeps the steady state free of redundant updates. The send is bounded so that a missing ListAndWatch consumer cannot stall the loop, which would also stop the HAMi node registration that follows it, since healthCh is unbuffered. Signed-off-by: 韩翔宇 <admin@pescn.cn>
8e4a50f to
8d6bf6e
Compare
|
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: archlitchi, pescn The full list of commands accepted by this bot can be found here. The pull request process is described here DetailsNeeds approval from an approver in each of these files:
Approvers can indicate their approval by writing |
What type of PR is this?
Bug fix. This repository has no
kind/*labels, so the/kindcommand cannot be used here. Theenhancementlabel currently on this PR was applied automatically and is not accurate; please relabel it tobug.What this PR does / why we need it:
watchAndRegisterrefreshed the cached device view only whileGetUnHealthIDs()reported at least one unhealthy device:When a device is unhealthy while the plugin starts — a node that boots faster than the Ascend driver initialises — and recovers shortly afterwards, that condition is already false on the next iteration. The cache keeps the startup snapshot forever, and because
ListAndWatchonly sends again when it receives onhealthCh, kubelet also keeps the startup device list.The node then advertises no allocatable devices and Pods fail admission with
Allocate failed due to no healthy devices present, whilenpu-smireports every device healthy.registerHAMi()keeps publishing the same stale snapshot tohami.io/node-register-<commonWord>, so the scheduler sees the stale health too. Only restarting the Pod recovers the node. The same condition keeps a partially enumerated device list from ever growing.This PR:
watchAndRegister;ListAndWatchupdate whenever the device set changes, in either direction, using a fingerprint over the published device UUIDs and their health so the steady state stays free of redundant updates;healthChsend, so that a missingListAndWatchconsumer cannot stall the loop and thereby also stop the HAMi node registration that follows it (healthChis unbuffered);Which issue(s) this PR fixes:
Fixes #129
Special notes for your reviewer:
The change is limited to the device-cache refresh loop. Device allocation, scheduling, resource accounting, vNPU handling, and both slicing modes are untouched;
go.mod/go.sumare unchanged.ListAndWatchitself is not modified, so this does not overlap with fix(server): stop ListAndWatch on stream closure #126 (stream-closure handling); the two are complementary — that PR fixes the consumer side of the stream lifecycle, this one fixes the producer side never producing.healthUpdateSendTimeoutis a package-level variable rather than a constant only so the regression test can shorten it.Each of the four new tests fails on
mainand passes with this change:mainTestWatchAndRegister_RepublishesRecoveredDevicesexpected kubelet to receive an updated device list, got 1 response(s)TestWatchAndRegister_PublishesLateDiscoveredDevicesexpected 16 devices in the last response, got 8TestWatchAndRegister_SteadyStateDoesNotResendexpected the device cache to be refreshed at least onceTestWatchAndRegister_ContinuesWithoutListAndWatchConsumerHealth:falseVerification performed on macOS/arm64 (
go1.26.6):make test— all packages passgo vet ./internal/...— cleangolangci-lint v2.1.0 run ./internal/...—0 issuesgo test -race -count=5 ./internal/server/ -run TestWatchAndRegister— cleanField context: the failure was observed on a two-node RKE2 v1.35.5 cluster with 4 × Ascend 910B4-1 per node running
v1.4.0, and the observable signature is a disagreement betweenhami.io/node-register-<commonWord>and the device series exported by the plugin's own dcmi collector on:9395(the latter reads the hardware live and stays correct during the failure).Does this PR introduce a user-facing change?:
No.
Summary by CodeRabbit