You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
We've noticed that with version 1.29.1 we no longer can issue multiple crictl stop commands for the same container. If there is a StopContainer operation active, any other StopContainer operation will timeout at the client side waiting for the server to take a lock that is hold by the initial stop container operation.
Context
In a scenario where you have one container that is unwilling to die gracefully over a long period of time (e.g. a big database that ignores SIGTERM for a long period of time while closing connections), the following regression happens:
Sending a crictl stop -t 300 <container>, will send a SIGTERM and after 300s send a SIGKILL. This command hangs as it should while we wait for the container to die gracefully or get forcefully terminated after 300s.
The container ignores SIGTERM, and won't die on its own. So we need to wait for the full timeout.
We decided that we don't want to wait for 300s, and we now want to issue crictl stop -t 0 <container> to immediately kill it.
Currently, the second command will not take effect, and crictl will get a context timeout from crio server.
This behavior was not present on version 1.27.1 and multiple stop container operations can be issued.
What did you expect to happen?
I'd expect to have the same behavior we did in 1.27; where the second crictl stop command goes through and manages to kill the container. The container runtime should honor all stopping requests, even if there is one currently waiting in a longer timeout, we should be able to stop a container forcefully even if we mistakenly or purposely tried with a longer timeout before.
I think this might be a regression introduced around the time of this refactor.
How can we reproduce it (as minimally and precisely as possible)?
To reproduce the issue, in a host running k8s with cri-o as container runtime:
This uses a busibox image to run a sleep command for 600 seconds. And has a terminationGracePeriodSeconds of 3600.
Check that the pod is running
$ kubectl get pods -n default sleepy-dummy
NAME READY STATUS RESTARTS AGE
sleepy-dummy 1/1 Running 0 14s
Attempt to delete the pod using kubectl. This will triger a StopContiainer call with a timeout o 3600; which will held the stop lock on crio server preventing any future stops to work.
$ kubectl delete pod -n infra-test sleepy-dummy
pod "sleepy-dummy" deleted
<hangs>
Attempt to stop the container using crictl stop.
$ crictl ps | grep sleepy
8c528df1cddbe ba5dc23f65d4cc4a4535bce55cf9e63b068eb02946e3422d3587e8ce803b6aab About a minute ago Running sleepy-dummy 0 05cfc9fc3bfed sleepy-dummy
$ sudo -i crictl stop 8c528df1cddbe
E0417 10:14:59.915882 798939 remote_runtime.go:366] "StopContainer from runtime service failed" err="rpc error: code = DeadlineExceeded desc = context deadline exceeded" containerID="8c528df1cddbe"
FATA[0002] stopping the container "8c528df1cddbe": rpc error: code = DeadlineExceeded desc = context deadline exceeded
Attempting to stop with explicit timeouts:
$ time sudo -i crictl -t 5s stop -t 0 8c528df1cddbe
E0417 10:15:20.765337 800099 remote_runtime.go:366] "StopContainer from runtime service failed" err="rpc error: code = DeadlineExceeded desc = context deadline exceeded" containerID="8c528df1cddbe"
FATA[0005] stopping the container "8c528df1cddbe": rpc error: code = DeadlineExceeded desc = context deadline exceeded
real 0m5.071s
user 0m0.049s
sys 0m0.031s
Note: the same can be achieved using crictl stop -t 3600 <container> on step 3.
Anything else we need to know?
I've run a goroutine dump of the state of my cri-o server during step 4 of the reproduction steps and confirmed that there is at least one goroutine in the method WaitOnStopTimeout while all the others cannot enter the stop main method.
This is the first crictl stop issued, with the high timeout, waiting in this timout channel if I'm not mistaken. It is holding the stopLock.
I've looked a bit at the tests you shared and it looks like the same scenario I'm describing. However, if I understand correctly, every crictl command in the tests is ran with 10m client-side timeout; which is high enough to don't have any of the crictl stop commands in the test to fail due to timeout (the first SIGKILL will come after 150s, which will unblock the rest of the stop commands).
If that is the case, I suspect reducing the client timeout (or increasing SIGTERM timeout) will cause the test to fail. That's my take as far as I understand.
What happened?
We've noticed that with version 1.29.1 we no longer can issue multiple
crictl stop
commands for the same container. If there is aStopContainer
operation active, any otherStopContainer
operation will timeout at the client side waiting for the server to take a lock that is hold by the initial stop container operation.Context
In a scenario where you have one container that is unwilling to die gracefully over a long period of time (e.g. a big database that ignores SIGTERM for a long period of time while closing connections), the following regression happens:
crictl stop -t 300 <container>
, will send a SIGTERM and after 300s send a SIGKILL. This command hangs as it should while we wait for the container to die gracefully or get forcefully terminated after 300s.crictl stop -t 0 <container>
to immediately kill it.Currently, the second command will not take effect, and
crictl
will get a context timeout fromcrio
server.The following logs show the symptoms :
This behavior was not present on version 1.27.1 and multiple stop container operations can be issued.
What did you expect to happen?
I'd expect to have the same behavior we did in 1.27; where the second
crictl stop
command goes through and manages to kill the container. The container runtime should honor all stopping requests, even if there is one currently waiting in a longer timeout, we should be able to stop a container forcefully even if we mistakenly or purposely tried with a longer timeout before.I think this might be a regression introduced around the time of this refactor.
How can we reproduce it (as minimally and precisely as possible)?
To reproduce the issue, in a host running k8s with cri-o as container runtime:
This uses a
busibox
image to run asleep
command for 600 seconds. And has a terminationGracePeriodSeconds of 3600.kubectl
. This will triger aStopContiainer
call with a timeout o 3600; which will held the stop lock on crio server preventing any future stops to work.crictl
stop.Attempting to stop with explicit timeouts:
Note: the same can be achieved using
crictl stop -t 3600 <container>
on step 3.Anything else we need to know?
I've run a goroutine dump of the state of my cri-o server during step 4 of the reproduction steps and confirmed that there is at least one goroutine in the method
WaitOnStopTimeout
while all the others cannot enter the stop main method.This is the first
crictl stop
issued, with the high timeout, waiting in this timout channel if I'm not mistaken. It is holding thestopLock
.Here is one of the following
crictl stops
calls, attempting to get the same lock forShouldBeStopped
function.CRI-O and Kubernetes version
OS version
Additional environment details (AWS, VirtualBox, physical, etc.)
The text was updated successfully, but these errors were encountered: