Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

wcow: support graceful termination of servercore containers #1416

Merged
merged 5 commits into from
Jan 9, 2023

Conversation

kiashok
Copy link
Contributor

@kiashok kiashok commented Jun 3, 2022

Graceful termination was already supported for nanoserver containers,
but those based on servercore still use a 5 second timeout which is
controlled by Windows. The reason behind this behavior is due to the
different implementation of SrvEndTask() in Servercore image which is
as follows:
(1) Deliver CTRL_SHUTDOWN_EVENT to the appropriate process
(2) Wait for 'WaitToKillServiceTimeout' amount of time (5 seconds by default) and kill the process before returning back to the caller.
This causes the containers with servercore base images to be killed in 5 seconds immaterial of the timeout specified with the container stop command.

We fix this by instead sending the termination signal for WCOW on a
background goroutine, and then returning immediately without waiting
for 'WaitToKillServiceTimeout' to expire.

In the future, if the underlying issue in Windows is fixed, this change could be reverted.

@kiashok kiashok requested a review from a team as a code owner June 3, 2022 09:05
@katiewasnothere
Copy link
Contributor

Tried to capture the time elapsed since the container exited using container stats but this is not supported for a container that has already existed.

Could you clarify what the problem with this is? I would think getting stats on an exited container (so long as it's not cleaned up) would be supported.

Tried to capture the elapsed time before and after container was stopped with a timeout but even without this fix, I see that containerStopWithTimeout() in test/cri-containerd waits for the entire timeout period even if the container exits before the specified timeout has elapsed.

I wonder if this is a bug in our cri? Do you know if that's the case?

In Hcsshim, we override value of reg key 'WaitToKillServiceTimeout' from 5 seconds to 30 minutes

Did you mean 30 seconds? Do we know if this will impact container users if they rely on this 5 second timeout?

@kiashok
Copy link
Contributor Author

kiashok commented Jun 8, 2022

Tried to capture the time elapsed since the container exited using container stats but this is not supported for a container that has already existed.

Could you clarify what the problem with this is? I would think getting stats on an exited container (so long as it's not cleaned up) would be supported.

I am using the StopContainerWithTimeout() function to stop the container with timeout in the cri test. This function currently kills the container after the timeout has passed and trying to get status after that results in the following error :
=== RUN Test_Gracefultermination_WCOW_Hypervisor_Servercore
error getting container container stats after stop: rpc error: code = Unknown desc = unexpected metrics response: []
stopcontainer_test.go:68: error getting container container stats after stop: rpc error: code = Unknown desc = unexpected metrics response: []

Tried to capture the elapsed time before and after container was stopped with a timeout but even without this fix, I see that containerStopWithTimeout() in test/cri-containerd waits for the entire timeout period even if the container exits before the specified timeout has elapsed.

I wonder if this is a bug in our cri? Do you know if that's the case?

I am not sure of this but it probably is something with the implementation as capturing the time right before and after the StopContainerWithTimeout() function with a timeout of 't' always returns a diff of 't' seconds even without my fix (but when I run it manually crictl.exe stop -t of any value kills the container in 5 seconds on servercore base images).

In Hcsshim, we override value of reg key 'WaitToKillServiceTimeout' from 5 seconds to 30 minutes

Did you mean 30 seconds? Do we know if this will impact container users if they rely on this 5 second timeout?

There are a lot of complaints saying we are not supporting timeout >5 seconds so am not sure if too many folks rely on the 5 second timer. I can double check with Brandon about this. The idea was to make behavior similar to nanoserver and linux which honor graceful timeout. Maybe adding release notes about this fix would help any customer upgrading to the latest package whenever its released?

@kiashok kiashok force-pushed the gracefultermFix_Hcsshim branch 2 times, most recently from 8be7adb to 3d06063 Compare July 11, 2022 18:35
@kevpar
Copy link
Member

kevpar commented Jul 27, 2022

A few notes on Git commit style:

  • The commit title should be fairly short (a lot of places recommend 50 characters max, but I think going a bit over this is still fine).
  • The commit title should be written using imperative mood.
  • If it is helpful, the title can be prefixed with a brief descriptor indicating the scope of the change (e.g. internal/foo: fix bug bar).
  • The commit title should be followed by a blank line, and then a mutli-line commit body with more details on the change. It's good to describe here what changed and why the change is important, follow-up work that may be needed, link to more info on the change, etc. The commit body should also not use super long lines when it can be avoided. Personally I try to keep my lines to 72 characters max.

Taken together, you might consider a commit description like the following:

wcow: Support graceful termination of servercore containers

Graceful termination was already supported for nanoserver containers,
but those based on servercore still use a 5 second timeout which is
controlled by Windows. The reason behind this behavior is <reason>.

We fix this by instead sending the termination signal for WCOW on a
background goroutine, and then returning. <more details on fix>.

In the future, if the underlying issue is fixed in Windows, this change
could be reverted.

There's a lot of guidance on the internet for how to write a good Git commit. One guide I like is here. Note that here we are not super prescriptive on the exact line length to use. :)

@kevpar
Copy link
Member

kevpar commented Jul 27, 2022

In Hcsshim, we override value of reg key 'WaitToKillServiceTimeout' from 5 seconds to 30 minutes

Did you mean 30 seconds? Do we know if this will impact container users if they rely on this 5 second timeout?

This is probably worth explicitly calling out in the PR/commit description. If a customer (for whatever reason) explicitly depended on this WaitToKillServiceTimeout value, this would be a breaking change for them. For instance, if a customer sent a termination signal between apps in their container, they would observe a difference in behavior now.

@kevpar
Copy link
Member

kevpar commented Jul 27, 2022

In Hcsshim, we override value of reg key 'WaitToKillServiceTimeout' from 5 seconds to 30 minutes

Did you mean 30 seconds? Do we know if this will impact container users if they rely on this 5 second timeout?

This is probably worth explicitly calling out in the PR/commit description. If a customer (for whatever reason) explicitly depended on this WaitToKillServiceTimeout value, this would be a breaking change for them. For instance, if a customer sent a termination signal between apps in their container, they would observe a difference in behavior now.

Actually, @jsturtevant or @marosset interested in your opinions on if this will be a problem for customers. This change will fix graceful termination for servercore containers, but could have negative impact if a customer is relying on the default termination timeout in servercore.

cmd/containerd-shim-runhcs-v1/exec_hcs.go Show resolved Hide resolved
cmd/containerd-shim-runhcs-v1/exec_hcs.go Outdated Show resolved Hide resolved
test/cri-containerd/stopcontainer_test.go Outdated Show resolved Hide resolved
test/cri-containerd/main_test.go Show resolved Hide resolved
test/cri-containerd/stopcontainer_test.go Outdated Show resolved Hide resolved
cmd/containerd-shim-runhcs-v1/exec_hcs.go Outdated Show resolved Hide resolved
cmd/containerd-shim-runhcs-v1/exec_hcs.go Outdated Show resolved Hide resolved
internal/hcsoci/hcsdoc_wcow.go Outdated Show resolved Hide resolved
@marosset
Copy link
Member

In Hcsshim, we override value of reg key 'WaitToKillServiceTimeout' from 5 seconds to 30 minutes

Did you mean 30 seconds? Do we know if this will impact container users if they rely on this 5 second timeout?

This is probably worth explicitly calling out in the PR/commit description. If a customer (for whatever reason) explicitly depended on this WaitToKillServiceTimeout value, this would be a breaking change for them. For instance, if a customer sent a termination signal between apps in their container, they would observe a difference in behavior now.

Actually, @jsturtevant or @marosset interested in your opinions on if this will be a problem for customers. This change will fix graceful termination for servercore containers, but could have negative impact if a customer is relying on the default termination timeout in servercore.

IMO there are a lot of downsides w/ relying on the default termination timeout in servercore (especially for K8s scenarios) and users are unhappy with current solution.
I agree we should call this out as a breaking change but think it might be more important to label this as a breaking change in containerd when we update decencies there.

@kiashok
Copy link
Contributor Author

kiashok commented Jul 28, 2022

In Hcsshim, we override value of reg key 'WaitToKillServiceTimeout' from 5 seconds to 30 minutes

Did you mean 30 seconds? Do we know if this will impact container users if they rely on this 5 second timeout?

This is probably worth explicitly calling out in the PR/commit description. If a customer (for whatever reason) explicitly depended on this WaitToKillServiceTimeout value, this would be a breaking change for them. For instance, if a customer sent a termination signal between apps in their container, they would observe a difference in behavior now.

Actually, @jsturtevant or @marosset interested in your opinions on if this will be a problem for customers. This change will fix graceful termination for servercore containers, but could have negative impact if a customer is relying on the default termination timeout in servercore.

IMO there are a lot of downsides w/ relying on the default termination timeout in servercore (especially for K8s scenarios) and users are unhappy with current solution. I agree we should call this out as a breaking change but think it might be more important to label this as a breaking change in containerd when we update decencies there.

I am not sure I understand why this is a breaking change. Currently, when crictl.exe stop is specified, the target pid is directly killed (that is SIGKILL is the only signal sent). The WaitToKillServiceTimeout reg key is used only when crictl.exe stop -t is specified. Currently no matter what value of 't' is specified, it is always killed in 5 seconds. This fix is only going to help honor the time specified. Am I missing something here?

@kiashok
Copy link
Contributor Author

kiashok commented Jul 28, 2022

wcow: Support graceful termination of servercore containers

A few notes on Git commit style:

  • The commit title should be fairly short (a lot of places recommend 50 characters max, but I think going a bit over this is still fine).
  • The commit title should be written using imperative mood.
  • If it is helpful, the title can be prefixed with a brief descriptor indicating the scope of the change (e.g. internal/foo: fix bug bar).
  • The commit title should be followed by a blank line, and then a mutli-line commit body with more details on the change. It's good to describe here what changed and why the change is important, follow-up work that may be needed, link to more info on the change, etc. The commit body should also not use super long lines when it can be avoided. Personally I try to keep my lines to 72 characters max.

Taken together, you might consider a commit description like the following:

wcow: Support graceful termination of servercore containers

Graceful termination was already supported for nanoserver containers,
but those based on servercore still use a 5 second timeout which is
controlled by Windows. The reason behind this behavior is <reason>.

We fix this by instead sending the termination signal for WCOW on a
background goroutine, and then returning. <more details on fix>.

In the future, if the underlying issue is fixed in Windows, this change
could be reverted.

There's a lot of guidance on the internet for how to write a good Git commit. One guide I like is here. Note that here we are not super prescriptive on the exact line length to use. :)

A few notes on Git commit style:

  • The commit title should be fairly short (a lot of places recommend 50 characters max, but I think going a bit over this is still fine).
  • The commit title should be written using imperative mood.
  • If it is helpful, the title can be prefixed with a brief descriptor indicating the scope of the change (e.g. internal/foo: fix bug bar).
  • The commit title should be followed by a blank line, and then a mutli-line commit body with more details on the change. It's good to describe here what changed and why the change is important, follow-up work that may be needed, link to more info on the change, etc. The commit body should also not use super long lines when it can be avoided. Personally I try to keep my lines to 72 characters max.

Taken together, you might consider a commit description like the following:

wcow: Support graceful termination of servercore containers

Graceful termination was already supported for nanoserver containers,
but those based on servercore still use a 5 second timeout which is
controlled by Windows. The reason behind this behavior is <reason>.

We fix this by instead sending the termination signal for WCOW on a
background goroutine, and then returning. <more details on fix>.

In the future, if the underlying issue is fixed in Windows, this change
could be reverted.

There's a lot of guidance on the internet for how to write a good Git commit. One guide I like is here. Note that here we are not super prescriptive on the exact line length to use. :)

Sure I'll keep this in mind, thanks Kevin :) Also, do we follow a template for the PR description section? Does that section look ok?

@kiashok kiashok changed the title This commit includes the changes to enable graceful termination of WC… wcow: support graceful termination of servercore containers Jul 28, 2022
@marosset
Copy link
Member

In Hcsshim, we override value of reg key 'WaitToKillServiceTimeout' from 5 seconds to 30 minutes

Did you mean 30 seconds? Do we know if this will impact container users if they rely on this 5 second timeout?

This is probably worth explicitly calling out in the PR/commit description. If a customer (for whatever reason) explicitly depended on this WaitToKillServiceTimeout value, this would be a breaking change for them. For instance, if a customer sent a termination signal between apps in their container, they would observe a difference in behavior now.

Actually, @jsturtevant or @marosset interested in your opinions on if this will be a problem for customers. This change will fix graceful termination for servercore containers, but could have negative impact if a customer is relying on the default termination timeout in servercore.

IMO there are a lot of downsides w/ relying on the default termination timeout in servercore (especially for K8s scenarios) and users are unhappy with current solution. I agree we should call this out as a breaking change but think it might be more important to label this as a breaking change in containerd when we update decencies there.

In Kubernetes it is a very common p

In Hcsshim, we override value of reg key 'WaitToKillServiceTimeout' from 5 seconds to 30 minutes

Did you mean 30 seconds? Do we know if this will impact container users if they rely on this 5 second timeout?

This is probably worth explicitly calling out in the PR/commit description. If a customer (for whatever reason) explicitly depended on this WaitToKillServiceTimeout value, this would be a breaking change for them. For instance, if a customer sent a termination signal between apps in their container, they would observe a difference in behavior now.

Actually, @jsturtevant or @marosset interested in your opinions on if this will be a problem for customers. This change will fix graceful termination for servercore containers, but could have negative impact if a customer is relying on the default termination timeout in servercore.

IMO there are a lot of downsides w/ relying on the default termination timeout in servercore (especially for K8s scenarios) and users are unhappy with current solution. I agree we should call this out as a breaking change but think it might be more important to label this as a breaking change in containerd when we update decencies there.

I am not sure I understand why this is a breaking change. Currently, when _crictl.exe stop _ is specified, the target pid is directly killed (that is SIGKILL is the only signal sent). The WaitToKillServiceTimeout reg key is used only when crictl.exe stop **-t ** is specified. Currently no matter what value of 't' is specified, it is always killed in 5 seconds. This fix is only going to help honor the time specified. Am I missing something here?

In Kubernetes it is common for pods to be stopped with a termination grace period.
When this happens a shutdown signal is sent to the containers and that after a configurable timeout a kill signal is sent.
This is commonly used during scale-down operations, and it gives and containers that are selected for scale-down a chance to complete any in-progress operations and the configurable timeouts are controlled are set by Kubernetes and can be changed at any time.
My understanding is that the currently shutdown behavior for servercore based containers is that it must be set at container build time. This does not provide the flexibility cluster operators expect.
I think it would be a breaking change because shutdown logic would no longer be honoring registry keys which previously affected shutdown duration/behaviour.

@kiashok
Copy link
Contributor Author

kiashok commented Jul 29, 2022

In Hcsshim, we override value of reg key 'WaitToKillServiceTimeout' from 5 seconds to 30 minutes

Did you mean 30 seconds? Do we know if this will impact container users if they rely on this 5 second timeout?

This is probably worth explicitly calling out in the PR/commit description. If a customer (for whatever reason) explicitly depended on this WaitToKillServiceTimeout value, this would be a breaking change for them. For instance, if a customer sent a termination signal between apps in their container, they would observe a difference in behavior now.

Actually, @jsturtevant or @marosset interested in your opinions on if this will be a problem for customers. This change will fix graceful termination for servercore containers, but could have negative impact if a customer is relying on the default termination timeout in servercore.

IMO there are a lot of downsides w/ relying on the default termination timeout in servercore (especially for K8s scenarios) and users are unhappy with current solution. I agree we should call this out as a breaking change but think it might be more important to label this as a breaking change in containerd when we update decencies there.

I am not sure I understand why this is a breaking change. Currently, when _crictl.exe stop _ is specified, the target pid is directly killed (that is SIGKILL is the only signal sent). The WaitToKillServiceTimeout reg key is used only when crictl.exe stop **-t ** is specified. Currently no matter what value of 't' is specified, it is always killed in 5 seconds. This fix is only going to help honor the time specified. Am I missing something here?

Discussed this with Kevin today and I understand how this could be a breaking change. I will make sure to call this out specifically.

@kiashok kiashok force-pushed the gracefultermFix_Hcsshim branch 4 times, most recently from 546f0b0 to 2bc36c2 Compare September 12, 2022 21:02
internal/hcs/process.go Outdated Show resolved Hide resolved
internal/hcs/process.go Outdated Show resolved Hide resolved
internal/hcs/process.go Outdated Show resolved Hide resolved
Kirtana Ashok added 4 commits December 7, 2022 14:19
…OW containers

Signed-off-by: Kirtana Ashok <Kirtana.Ashok@microsoft.com>
Signed-off-by: Kirtana Ashok <Kirtana.Ashok@microsoft.com>
Signed-off-by: Kirtana Ashok <Kirtana.Ashok@microsoft.com>
Fixed lint errors caused by spelling mistakes in hcsdoc_wcow.go and stopcontainer_test.go

Signed-off-by: Kirtana Ashok <Kirtana.Ashok@microsoft.com>
@kiashok kiashok force-pushed the gracefultermFix_Hcsshim branch 2 times, most recently from 0634782 to 23d8608 Compare December 12, 2022 19:06
fmt.Println("Waiting for OS signal...")

signalChannel := make(chan os.Signal)
wait := make(chan int, 1)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you are just using a channel to wait on once, you can do chan struct{}, and close(wait) instead of sending to the channel. If you want to send/receive multiple times, you can still do chan struct{} and use wait <- struct{}{} to send. This is probably a little more efficient than sending an int.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a big deal to change it here if you don't want to, just letting you know.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure will keep this in mind

Signed-off-by: Kirtana Ashok <Kirtana.Ashok@microsoft.com>

Signed-off-by: Kirtana Ashok <Kirtana.Ashok@microsoft.com>
Copy link
Member

@kevpar kevpar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@kevpar
Copy link
Member

kevpar commented Dec 13, 2022

I've signed off on this PR. If there's any additional testing we can do before merging that would be ideal, though. Maybe you can run the upstream containerd integration tests with an updated shim binary?

@kiashok
Copy link
Contributor Author

kiashok commented Dec 15, 2022

I've signed off on this PR. If there's any additional testing we can do before merging that would be ideal, though. Maybe you can run the upstream containerd integration tests with an updated shim binary?

Sure will do

Copy link
Contributor

@katiewasnothere katiewasnothere left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A small question, otherwise LGTM

@kiashok kiashok merged commit 5cfbc2a into microsoft:main Jan 9, 2023
kiashok added a commit to kiashok/hcsshim that referenced this pull request Feb 1, 2023
…t#1416)

* This commit includes the changes to enable graceful termination of WCOW containers

Signed-off-by: Kirtana Ashok <Kirtana.Ashok@microsoft.com>

* Added regression tests for nanoserver and servercore base images

Signed-off-by: Kirtana Ashok <Kirtana.Ashok@microsoft.com>

* Worked on Kevin's review comments

Signed-off-by: Kirtana Ashok <Kirtana.Ashok@microsoft.com>

* Fixed lint failures

Fixed lint errors caused by spelling mistakes in hcsdoc_wcow.go and stopcontainer_test.go

Signed-off-by: Kirtana Ashok <Kirtana.Ashok@microsoft.com>

* Addresses Kevin's review comments

Signed-off-by: Kirtana Ashok <Kirtana.Ashok@microsoft.com>

Signed-off-by: Kirtana Ashok <Kirtana.Ashok@microsoft.com>

Signed-off-by: Kirtana Ashok <Kirtana.Ashok@microsoft.com>
Co-authored-by: Kirtana Ashok <Kirtana.Ashok@microsoft.com>
(cherry picked from commit 5cfbc2a)
Signed-off-by: Kirtana Ashok <Kirtana.Ashok@microsoft.com>
kiashok added a commit to kiashok/hcsshim that referenced this pull request Feb 21, 2023
…t#1416)

* This commit includes the changes to enable graceful termination of WCOW containers

Signed-off-by: Kirtana Ashok <Kirtana.Ashok@microsoft.com>

Signed-off-by: Kirtana Ashok <Kirtana.Ashok@microsoft.com>
Co-authored-by: Kirtana Ashok <Kirtana.Ashok@microsoft.com>
(cherry picked from commit 5cfbc2a)
Signed-off-by: Kirtana Ashok <Kirtana.Ashok@microsoft.com>
kiashok added a commit to kiashok/hcsshim that referenced this pull request Feb 21, 2023
…t#1416)

* This commit includes the changes to enable graceful termination of WCOW containers

Signed-off-by: Kirtana Ashok <Kirtana.Ashok@microsoft.com>

Signed-off-by: Kirtana Ashok <Kirtana.Ashok@microsoft.com>
Co-authored-by: Kirtana Ashok <Kirtana.Ashok@microsoft.com>
(cherry picked from commit 5cfbc2a)
Signed-off-by: Kirtana Ashok <Kirtana.Ashok@microsoft.com>
kiashok added a commit that referenced this pull request Feb 21, 2023
…1640)

* This commit includes the changes to enable graceful termination of WCOW containers

(cherry picked from commit 5cfbc2a)

Signed-off-by: Kirtana Ashok <Kirtana.Ashok@microsoft.com>
Co-authored-by: Kirtana Ashok <Kirtana.Ashok@microsoft.com>
princepereira pushed a commit to princepereira/hcsshim that referenced this pull request Aug 29, 2024
…t#1416)

* This commit includes the changes to enable graceful termination of WCOW containers

Signed-off-by: Kirtana Ashok <Kirtana.Ashok@microsoft.com>

* Added regression tests for nanoserver and servercore base images

Signed-off-by: Kirtana Ashok <Kirtana.Ashok@microsoft.com>

* Worked on Kevin's review comments

Signed-off-by: Kirtana Ashok <Kirtana.Ashok@microsoft.com>

* Fixed lint failures

Fixed lint errors caused by spelling mistakes in hcsdoc_wcow.go and stopcontainer_test.go

Signed-off-by: Kirtana Ashok <Kirtana.Ashok@microsoft.com>

* Addresses Kevin's review comments

Signed-off-by: Kirtana Ashok <Kirtana.Ashok@microsoft.com>

Signed-off-by: Kirtana Ashok <Kirtana.Ashok@microsoft.com>

Signed-off-by: Kirtana Ashok <Kirtana.Ashok@microsoft.com>
Co-authored-by: Kirtana Ashok <Kirtana.Ashok@microsoft.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants