Wait for MPS daemon readiness before advertising shared resources - #1946
Open
jonathan-meiri wants to merge 1 commit into
Open
Wait for MPS daemon readiness before advertising shared resources#1946jonathan-meiri wants to merge 1 commit into
jonathan-meiri wants to merge 1 commit into
Conversation
jonathan-meiri
force-pushed
the
mps-wait-for-ready
branch
2 times, most recently
from
August 6, 2026 13:13
6966a94 to
bfcb598
Compare
|
Thanks for the contribution. We will review this soon. |
The device plugin's waitForDaemon only ran a single AssertHealthy check
before serving and registering the resource with kubelet. AssertHealthy
issues get_default_active_thread_percentage, which only proves the MPS
control pipe is responsive — and the pipe becomes responsive at
Daemon.Start (mpsControlBin -d) before the per-device pinned memory
limits and active thread percentage are applied. A pod scheduled in
that window starts against MPS with the daemon defaults (no pinned
memory limit, 100% threads) rather than the configured limits,
silently bypassing the intended isolation.
The MPS control daemon already creates a node-global .ready file, but
only after every daemon's full initialization completes. Nothing
consumed it (the two TODOs in waitForDaemon noted exactly this), so the
readiness signal was unused.
Gate readiness on that file:
- Add Root.ReadyFilePath so the marker path has a single definition,
and use it in the MPS control daemon for both create and remove
instead of the hardcoded "/mps/.ready".
- Add Daemon.Ready, which reports whether the .ready file exists.
- Rewrite waitForDaemon to poll checkDaemonReady (Ready AND
AssertHealthy) every 5s up to a 5m bound, replacing the single
unconditional AssertHealthy. On timeout the caller fails and is
retried by the plugin manager, so the bound is per-attempt.
This closes both TODOs and ensures shared MPS resources are not
advertised until the daemon is fully configured.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: runatom-ai <258621014+runatom-ai@users.noreply.github.com>
Signed-off-by: Jonathan Meiri <33288957+Meiri28@users.noreply.github.com>
jonathan-meiri
force-pushed
the
mps-wait-for-ready
branch
from
August 12, 2026 17:03
bfcb598 to
827e00b
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The device plugin can advertise MPS-shared resources to kubelet before the MPS daemon has finished configuring per-device memory limits and thread percentages. A pod scheduled in that window runs against MPS with the daemon defaults (no pinned memory limit, 100% threads) instead of the configured limits — silently bypassing the intended isolation.
This gates readiness on the MPS daemon's
.readyfile, closing the two existing TODOs inwaitForDaemon.Contributed by @Meiri28 on behalf of @runatom-ai.
The race
internal/plugin/server.go:Start()callsplugin.mps.waitForDaemon()beforeServe()+Register(). PreviouslywaitForDaemonran a singleAssertHealthy():AssertHealthy()issuesget_default_active_thread_percentage, which only proves the control pipe is responsive. InDaemon.Start()the ordering is:mpsControlBin -dstarts → pipe becomes responsive (AssertHealthypasses here).readyfile created (after all daemons'Start()return)If the single check lands between (1) and (4), the plugin registers as ready while the configured MPS limits are not yet in place.
The MPS control daemon already creates a node-global
.readyfile only after full initialization, but nothing consumed it — the two TODOs noted exactly this gap. Both components share the same/mpshostPath mount, so the file is visible to the device plugin.Changes
mps/root.go: addRoot.ReadyFilePath()so the marker path has a single definition.mps-control-daemon/main.go: create/remove.readyviaReadyFilePath()instead of the hardcoded/mps/.ready, keeping writer and reader in sync.mps/daemon.go: addDaemon.Ready(), reporting whether the.readyfile exists.internal/plugin/mps.go: rewritewaitForDaemonto pollcheckDaemonReady(Ready()andAssertHealthy()) every 5s up to a 5m bound. On timeout the caller fails and is retried by the plugin manager, so the bound is per-attempt.Test plan
go test ./...— full suite passes; newTestReadyFilePathandTestDaemonReadycover the readiness primitive (readiness reflects.readyfile existence).make build,make check-modules, gofmt — clean.Commits are DCO-signed.