feat(node-agent): advertise the RDMA extended resource from a simulator - #734
Draft
giuliocalzo wants to merge 4 commits into
Draft
feat(node-agent): advertise the RDMA extended resource from a simulator#734giuliocalzo wants to merge 4 commits into
giuliocalzo wants to merge 4 commits into
Conversation
giuliocalzo
force-pushed
the
feat/node-agent-rdma-plugin
branch
from
August 25, 2026 16:13
da7d63e to
6470627
Compare
Member
|
@giuliocalzo let's consider whether Mokka Control Plane is the right place for this functionality. The Control Plane has access to K8s by definition, so it seems like a better place. I would like to keep node agent K8s agnostic as much as possible. Let me know what do you think? |
Collaborator
Author
@roma-glushko this feature is core one, very likely of |
giuliocalzo
force-pushed
the
feat/node-agent-rdma-plugin
branch
3 times, most recently
from
August 26, 2026 09:42
c79f639 to
6e57a63
Compare
6 tasks
giuliocalzo
force-pushed
the
feat/node-agent-rdma-plugin
branch
4 times, most recently
from
August 26, 2026 12:46
0feed7b to
5ff1c28
Compare
Real InfiniBand nodes carry rdma/ib in their capacity, published by the Network Operator's k8s-rdma-shared-dev-plugin. A workload gated on that resource therefore stays Pending on a mock node however complete its IB surface is. That plugin cannot run here: it is a Go binary, so the LD_PRELOAD sysfs redirect never sees its syscalls, and it discovers HCAs through netdevs the mock does not render. A node-agent simulator stands in for it and publishes the resource itself — the bridge role pcibus.Apply's NFD feature file plays for PCI presence. Profiles declare it under infiniband.rdma_resource; all five IB-enabled profiles ship rdma/ib = 64. Upstream that count is rdmaHcaMax, a pod-sharing limit rather than a device count, so a 4-GPU GB300 compute tray reports 64 while carrying 4 HCAs. Apply patches .status.capacity and Revoke withdraws the key, since kubelet never removes capacity it does not own. Renaming or removing the block withdraws the previous key rather than stranding it, and a node already reporting the right value costs one GET instead of a write, so re-running Apply on every reconcile is cheap. Each Apply logs what the node ended up advertising, write-free runs included: reconciles fire only on config change, so silence would be indistinguishable from a simulator that never ran. The node-agent container gains NODE_NAME, without which the compiled State carries no node identity and there is nothing to patch. Validation lives in Stage rather than in chart helpers, so it also covers gpu.customConfig and the Control Plane source that will replace the file source. MEP-0003's simulator and InfiniBand surface tables gain the package, with a note on why a node resource with no other publisher is owned by a simulator while node labels stay delegated to NFD and GFD. Signed-off-by: Giulio Calzolari <gcalzolari@nvidia.com>
Registering the rdmaplugin simulator builds a full client-go clientset, which widens govulncheck's reachable call graph until the vulnerable x/text normalization symbols become reachable through rest.Request.Stream (GO-2026-5970, unbounded loop on invalid input). Signed-off-by: Giulio Calzolari <gcalzolari@nvidia.com>
The workflow asked the action for `latest` while `make tools` pins v2.12.2, so the two agreed only until a release changed a linter's mind. v2.13.1 no longer reports the deprecated grpc.DialContext calls in pkg/gpu/allocwatch, which made the //nolint:staticcheck directives guarding them unused and failed nolintlint on every PR — code that lints clean locally. Signed-off-by: Giulio Calzolari <gcalzolari@nvidia.com>
Signed-off-by: Giulio Calzolari <gcalzolari@nvidia.com>
giuliocalzo
force-pushed
the
feat/node-agent-rdma-plugin
branch
from
August 26, 2026 13:07
5ff1c28 to
7e9baa6
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
Mock InfiniBand nodes did not report
rdma/ib, so a workload gated on that resource stayedPendinghowever complete the node's IB surface was. On real hardware the Network Operator's k8s-rdma-shared-dev-plugin advertises it; that plugin cannot run against the mock, because it is a Go binary whose syscalls theLD_PRELOADsysfs redirect never sees, and it discovers HCAs through netdevs the mock does not render.A new node-agent simulator,
internal/agent/rdmaplugin, stands in for it — the bridge rolepcibus.Apply's NFD feature file plays for PCI presence:infiniband.rdma_resource; all five IB-enabled profiles shiprdma/ib = 64. Upstream that count isrdmaHcaMax, a pod-sharing limit rather than a device count, so a 4-GPU GB300 compute tray reports 64 while carrying 4 HCAs.Applypatches.status.capacityandRevokewithdraws the key, because kubelet never removes capacity it does not own. The simulator is anApplieronly — no daemon, no re-assertion ticker — so the resource is republished on the next reconcile rather than on a clock of its own.Applycheap.NODE_NAME, without which the compiledStatecarries no node identity and there is nothing to patch. This also fixesstate.Node.NodeNamebeing empty for every simulator in that container, same as feat(node-agent): Node Agent CDI Simulator #728.Stage, so it also coversgpu.customConfigand the Control Plane source that will replace the file source.MEP-0003's simulator and InfiniBand surface tables gain the package, plus a note on why a node resource with no other publisher is owned by a simulator while node labels stay delegated to NFD and GFD. Happy to drop those edits if @roma-glushko would rather fold this into
ibhca.Known limitations
LD_PRELOADshims, not/dev/infinibandchar devices.patchonnodes/status, which the chart's ClusterRole now grants.terminationGracePeriodSeconds: 2is belownodeAgent.shutdownTimeout: 30s.Revokeis one GET plus one PATCH so it normally lands well inside 2s, but a SIGKILL at the grace boundary would leave a stalerdma/ibkey on the node. Left alone here since raising it affects every container and slows rollouts.Test plan
make test— green outside the sandbox;pkg/gpu/allocwatchandpkg/network/mockib/daemonfail inside it only because unix-socketbindis blockedmake lint-fix— 0 issuesmake helm-tests— 175 tests, 15 snapshots, snapshots refreshed for the newNODE_NAMEenv and the profile blocksinternal/agent/rdmapluginunit tests drive a fake node API that applies the patches it receives, so they assert on resulting capacity: advertise, no-op when already correct, update on count change, withdraw on rename/removal, revoke idempotently, tolerate a deleted node, republish after an external removal, and reject an unqualified name, a non-positive count or an emptyNODE_NAMEinternal/agent/sourcesweeps every chart profile, so an IB profile that forgets the block fails CIkubectl get node -o jsonpath='{.status.capacity}'showsrdma/ib: 64and is gone afterhelm uninstall