Skip to content

fix atelet deviceplugin wedge - #3323

Merged
Tim Hockin (thockin) merged 2 commits into
agent-substrate:mainfrom
BenTheElder:atelet-deviceplugin-wedge
Oct 29, 2026
Merged

Tim Hockin (thockin) merged 2 commits into
agent-substrate:mainfrom
BenTheElder:atelet-deviceplugin-wedge

Conversation

@BenTheElder

Copy link
Copy Markdown
Collaborator

Why is this needed? (Or link the issue. Open one first for features, API, install or CI changes.)

Fixes #3272

Since 1.37, kubelet wedges a device plugin resource if a second Register for the same socket arrives while it is still closing the first stream. The failed connect deregisters both clients by socket path:
https://github.com/kubernetes/kubernetes/blob/v1.37.0/pkg/kubelet/cm/devicemanager/plugin/v1beta1/handler.go#L82-L86

So when the first stream ends, kubelet never calls PluginDisconnected, and every later Register fails with "device plugin already connected" until kubelet restarts:
https://github.com/kubernetes/kubernetes/blob/v1.37.0/pkg/kubelet/cm/devicemanager/plugin/v1beta1/handler.go#L137-L140

atelet keeps one fsnotify watcher across registration retries, so a kubelet.sock Create that was queued while it retried made it stop and re-register right after registering. It now ignores the Create if kubelet.sock is still the socket it registered with.

A node that is already wedged still needs a kubelet restart.

AI use: I used Claude to trace this through the kubelet source and draft the fix, and reviewed it.

  • Tests pass
  • Docs updated

the replacement pod starts as soon as this one is terminating and registers
the same socket while we drain. kubelet 1.37 can then wedge the resource as
"already connected" until kubelet restarts.

Signed-off-by: Benjamin Elder <[email protected]>
re-registering right after registering can wedge the resource in kubelet the
same way as two overlapping atelet pods

Signed-off-by: Benjamin Elder <[email protected]>
@BenTheElder Benjamin Elder (BenTheElder) changed the title atelet deviceplugin wedge fix atelet deviceplugin wedge Oct 27, 2026
@BenTheElder Benjamin Elder (BenTheElder) added this to the M3 milestone Oct 27, 2026
@thockin Tim Hockin (thockin) added the prio/P0 Highest priority / required for next milestone label Oct 27, 2026
@BenTheElder Benjamin Elder (BenTheElder) added kind/bug Something isn't working / bugfixes area/node labels Oct 27, 2026
@thockin
Tim Hockin (thockin) added this pull request to the merge queue Oct 29, 2026
Merged via the queue into agent-substrate:main with commit 40bf20f Oct 29, 2026
8 of 9 checks passed
@BenTheElder
Benjamin Elder (BenTheElder) deleted the atelet-deviceplugin-wedge branch October 29, 2026 20:29
@SergeyKanzhelev

Copy link
Copy Markdown

Since 1.37, kubelet wedges a device plugin resource if a second Register for the same socket arrives while it is still closing the first stream. The failed connect deregisters both clients by socket path:
https://github.com/kubernetes/kubernetes/blob/v1.37.0/pkg/kubelet/cm/devicemanager/plugin/v1beta1/handler.go#L82-L86

It may be best to not reuse the socket and instead use random socket name. See kubernetes/kubernetes#139338

@BenTheElder

Copy link
Copy Markdown
Collaborator Author

Thanks, that makes sense. I'll switch atelet to a new socket per registration in a follow-up.

@BenTheElder

Copy link
Copy Markdown
Collaborator Author

follow-up: #3486

IIUC we can afford to defer it to 1.0.x, what we have now will work but random socket will be preferable.

[I vaguely remembered a thread about this but couldn't find it, Sergey gave us the pointer and advice, thank you!]

Eitan Yarmush (EItanya) pushed a commit to kagent-dev/substrate that referenced this pull request Nov 3, 2026
…ubstrate#3486)

Follow-up to agent-substrate#3323, as @SergeyKanzhelev suggested there. kubelet expects
a device plugin to switch to a new socket when it re-registers. Since
1.37 it rejects a Register for a socket it still has connected, and two
overlapping Registers for one socket can wedge the resource as "already
connected" until kubelet restarts:
kubernetes/kubernetes#139338

- the device plugin listens on a new `ate.dev-kvm-<random>.sock` for
each registration, and removes sockets left over from earlier atelets
- the device plugin stays up until atelet exits again. agent-substrate#3323 stopped it
on SIGTERM to avoid overlapping with the replacement pod, but the
DaemonSet only starts the replacement once the old pod is gone, so that
just left `ate.dev/kvm` unhealthy for the whole drain

<!-- e.g. "AI-assisted, I reviewed and tested it." No AI co-author
trailers. -->
AI use: I used Claude to draft this and reviewed it.

<!-- Breaking change? Describe what users must do on upgrade and ask for
the `breaking-change` label. -->

- [x] Tests pass
- [x] Docs updated

---------

Signed-off-by: Benjamin Elder <[email protected]>
(cherry picked from commit 38e9ef6)
Signed-off-by: Eitan Yarmush <[email protected]>
Yufan Su (yufan-su) pushed a commit to yufan-su/substrate that referenced this pull request Nov 3, 2026
…ubstrate#3486)

Follow-up to agent-substrate#3323, as @SergeyKanzhelev suggested there. kubelet expects
a device plugin to switch to a new socket when it re-registers. Since
1.37 it rejects a Register for a socket it still has connected, and two
overlapping Registers for one socket can wedge the resource as "already
connected" until kubelet restarts:
kubernetes/kubernetes#139338

- the device plugin listens on a new `ate.dev-kvm-<random>.sock` for
each registration, and removes sockets left over from earlier atelets
- the device plugin stays up until atelet exits again. agent-substrate#3323 stopped it
on SIGTERM to avoid overlapping with the replacement pod, but the
DaemonSet only starts the replacement once the old pod is gone, so that
just left `ate.dev/kvm` unhealthy for the whole drain

<!-- e.g. "AI-assisted, I reviewed and tested it." No AI co-author
trailers. -->
AI use: I used Claude to draft this and reviewed it.

<!-- Breaking change? Describe what users must do on upgrade and ask for
the `breaking-change` label. -->

- [x] Tests pass
- [x] Docs updated

---------

Signed-off-by: Benjamin Elder <[email protected]>
Dmitry Berkovich (dberkov) pushed a commit that referenced this pull request Nov 3, 2026
Follow-up to #3323, as @SergeyKanzhelev suggested there. kubelet expects
a device plugin to switch to a new socket when it re-registers. Since
1.37 it rejects a Register for a socket it still has connected, and two
overlapping Registers for one socket can wedge the resource as "already
connected" until kubelet restarts:
kubernetes/kubernetes#139338

- the device plugin listens on a new `ate.dev-kvm-<random>.sock` for
each registration, and removes sockets left over from earlier atelets
- the device plugin stays up until atelet exits again. #3323 stopped it
on SIGTERM to avoid overlapping with the replacement pod, but the
DaemonSet only starts the replacement once the old pod is gone, so that
just left `ate.dev/kvm` unhealthy for the whole drain

<!-- e.g. "AI-assisted, I reviewed and tested it." No AI co-author
trailers. -->
AI use: I used Claude to draft this and reviewed it.

<!-- Breaking change? Describe what users must do on upgrade and ask for
the `breaking-change` label. -->

- [x] Tests pass
- [x] Docs updated

---------

Signed-off-by: Benjamin Elder <[email protected]>
(cherry picked from commit 38e9ef6)
Signed-off-by: Eitan Yarmush <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/node kind/bug Something isn't working / bugfixes milestone-ack prio/P0 Highest priority / required for next milestone

Projects

None yet

Development

Successfully merging this pull request may close these issues.

atelet /dev/kvm device plugin permanently wedges ate.dev/kvm registration in Kubelet ("device plugin already connected" forever until kubelet restart)

4 participants