runc-shim: don't hold the service lock across runc create#13483
Conversation
There was a problem hiding this comment.
Pull request overview
This PR reduces lock contention in the runc v2 shim task service by avoiding holding the global service.mu (which guards the containers map) while executing runc create during Create(). This prevents unrelated task RPCs (e.g., State, Stats, Connect) from blocking behind a potentially slow container creation and timing out.
Changes:
- Move
runc.NewContainer()(which runsrunc create) outside of thes.mucritical section inCreate(). - Add an explanatory comment documenting why
s.mushould not be held acrossrunc create.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
4c55365 to
64f7673
Compare
|
/cherry-pick release/2.3 |
|
@AkihiroSuda: once the present PR merges, I will cherry-pick it on top of 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. |
64f7673 to
e29b724
Compare
|
can you show the code container is torn down in nerdctl ? @AkihiroSuda |
See: |
|
I add some sleep nerdctl run -d busybox sleep 1000 but I can't see container will be killed |
|
So far, the issue is only seen in Lima's CI: |
e29b724 to
dbcaa50
Compare
The task service guards its containers map with s.mu, and getContainer()
takes it on behalf of effectively every task RPC (State, Connect, Stats,
Wait, Pause, Kill, ...). Create() held s.mu for its whole duration,
including runc.NewContainer(), which runs the actual `runc create`.
`runc create` can be slow on a loaded host. While it runs, any concurrent
task RPC blocks on s.mu. The tasks service applies a 2s timeout to State
(io.containerd.timeout.task.state), so a concurrent State waits on s.mu,
exceeds the deadline, and the ttrpc call is abandoned -- the late shim
reply then shows up as:
ttrpc: received message on inactive stream stream=3
Since deadline errors are now surfaced to clients, this is treated as a
fatal failure and the just-created container is torn down right after
start (observed on Lima/vz: nginx -> Exited (1)).
Move runc.NewContainer() out of the s.mu critical section, mirroring the
runtime v1 shim lock optimization. s.mu is taken only once the container
exists, to guard the map and the remaining (fast) setup, so a slow create
no longer blocks concurrent State and other lookups.
preStart/handleStarted/cleanup only use s.lifecycleMu, so early-exit
handling is unchanged.
See lima-vm/lima#5030.
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Signed-off-by: Akihiro Suda <[email protected]>
|
/cherry-pick release/2.3 |
|
@AkihiroSuda: once the present PR merges, I will cherry-pick it on top of 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. |
mikebrow
left a comment
There was a problem hiding this comment.
concern over possible unforeseen timing changes
| handleStarted, cleanup := s.preStart(nil) | ||
| s.lifecycleMu.Unlock() | ||
| defer cleanup() | ||
|
|
There was a problem hiding this comment.
perhaps a mux for each r.ID, to hold lock for each, across the newcontainer + task create event + cgroup oom monitor + started tasks?
There was a problem hiding this comment.
Not sure. s.send doesn't seem to alter the struct s
There was a problem hiding this comment.
kk
FYI @fuweid ... might "enhance" the parallelism of sidecar/init/containers pls be on the lookout
There was a problem hiding this comment.
The lock behaviour was there for 7 years. To be honest, it's not easy-review one.
BTW, @AkihiroSuda could you please remove the AI-co-author next time? I would like to update project-check to check this. I am not saying we can't use AI. just want the sign-off one is real person. Thanks
There was a problem hiding this comment.
BTW, @AkihiroSuda could you please remove the AI-co-author next time? I would like to update project-check to check this. I am not saying we can't use AI. just want the sign-off one is real person. Thanks
I'm not sure. The sign-off was added by myself, not by AI.
(IIUC, Co-Authored-by does not count as a sign-off)
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Signed-off-by: Akihiro Suda <[email protected]>
We should have a solid policy anyway.
Could you open an issue or a PR against https://github.com/containerd/project/blob/main/CONTRIBUTING.md#sign-your-work ?
|
@AkihiroSuda: new pull request created: #13512 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. |
The task service guards its containers map with s.mu, and getContainer() takes it on behalf of effectively every task RPC (State, Connect, Stats, Wait, Pause, Kill, ...). Create() held s.mu for its whole duration, including runc.NewContainer(), which runs the actual
runc create.runc createcan be slow on a loaded host. While it runs, any concurrent task RPC blocks on s.mu. The tasks service applies a 2s timeout to State (io.containerd.timeout.task.state), so a concurrent State waits on s.mu, exceeds the deadline, and the ttrpc call is abandoned -- the late shim reply then shows up as:Since deadline errors are now surfaced to clients, this is treated as a fatal failure and the just-created container is torn down right after start (observed on Lima/vz: nginx -> Exited (1)).
Move runc.NewContainer() out of the s.mu critical section, mirroring the runtime v1 shim lock optimization. s.mu is taken only once the container exists, to guard the map and the remaining (fast) setup, so a slow create no longer blocks concurrent State and other lookups. preStart/handleStarted/cleanup only use s.lifecycleMu, so early-exit handling is unchanged.
See:
Integration tests (vz) (default.yaml)is failing after updating nerdctl to v2.3.1 lima-vm/lima#5030.Note: used Claude