Skip to content

Restart external-attacher faster by releasing leader election lease on sigterm#633

Merged
k8s-ci-robot merged 2 commits intokubernetes-csi:masterfrom
rhrmo:restart-CSI-sidecars-faster
Aug 12, 2025
Merged

Restart external-attacher faster by releasing leader election lease on sigterm#633
k8s-ci-robot merged 2 commits intokubernetes-csi:masterfrom
rhrmo:restart-CSI-sidecars-faster

Conversation

@rhrmo
Copy link
Copy Markdown
Contributor

@rhrmo rhrmo commented Mar 6, 2025

What type of PR is this?
/kind bug

What this PR does / why we need it:
This PR makes external-attacher restart faster when it is terminating because of sigterm. This is accomplished by releasing leader election lease on sigterm and then it does not have to wait for lease to expire but it proceeds with restart right away. This is the first PR of series of PRs that fix #609

Which issue(s) this PR fixes:

Fixes #

Special notes for your reviewer:
This PR is the first of the series of PRs that fix #609 and I want to use it to agree on a solution - if you have any suggestions, or find anything wrong, please add a comment and let me know.
I had to import newer version of csi-lib-utils library, so that it would contain changes from kubernetes-csi/csi-lib-utils#191 (go get github.com/kubernetes-csi/csi-lib-utils@f77445f75e9c4954062cdddcef4863adab21947b), so before merging this we would also need to have new version of csi-lib-utils released.

Does this PR introduce a user-facing change?:

NONE

@k8s-ci-robot k8s-ci-robot added release-note-none Denotes a PR that doesn't merit a release note. do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. kind/bug Categorizes issue or PR as related to a bug. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. labels Mar 6, 2025
@k8s-ci-robot
Copy link
Copy Markdown
Contributor

Hi @rhrmo. Thanks for your PR.

I'm waiting for a kubernetes-csi member to verify that this patch is reasonable to test. If it is, they should reply with /ok-to-test on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work. Regular contributors should join the org to skip this step.

Once the patch is verified, the new status will be reflected by the ok-to-test label.

I understand the commands that are listed here.

Details

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.

@k8s-ci-robot k8s-ci-robot added the size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. label Mar 6, 2025
@jsafrane
Copy link
Copy Markdown
Contributor

jsafrane commented Mar 7, 2025

/ok-to-test

@k8s-ci-robot k8s-ci-robot added ok-to-test Indicates a non-member PR verified by an org member that is safe to test. and removed needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. labels Mar 7, 2025
@jsafrane
Copy link
Copy Markdown
Contributor

I tested in on a cluster.

What's great is that when the attacher gets SIGTERM, it exits immediately (this PR does not change that) + release its lease, so a newly started attacher starts immediately. This is taken when SIGTERM was received in the middle of ControllerPublish:

I0310 15:57:31.102801  133591 connection.go:264] "GRPC call" VolumeAttachment="csi-043731379aa11361179f9e22a17f1fda8d2b0716696126267433bf49892e92b2" method="/csi.v1.Controller/ControllerPublishVolume" request="{\"node_id\":\"192.168.124.90\",\"volume_capability\":{\"access_mode\":{\"mode\":\"SINGLE_NODE_MULTI_WRITER\"},\"mount\":{}},\"volume_context\":{\"storage.kubernetes.io/csiProvisionerIdentity\":\"1741618771172-2394-hostpath.csi.k8s.io\"},\"volume_id\":\"5a4de638-fdc0-11ef-b375-5ed7a0a04918\"}"

[waiting for ControllerPublishVolumeResponse]
^C

I0310 15:57:32.373544  133591 main.go:292] Received SIGTERM or SIGINT signal, shutting down controller.
I0310 15:57:32.373594  133591 controller.go:151] "Shutting CSI attacher"
I0310 15:57:32.373682  133591 reflector.go:319] Stopping reflector *v1.CSINode (10m0s) from k8s.io/client-go/informers/factory.go:160
I0310 15:57:32.373719  133591 reflector.go:319] Stopping reflector *v1.PersistentVolume (10m0s) from k8s.io/client-go/informers/factory.go:160
I0310 15:57:32.373748  133591 reflector.go:319] Stopping reflector *v1.VolumeAttachment (10m0s) from k8s.io/client-go/informers/factory.go:160
I0310 15:57:32.373719  133591 connection.go:270] "GRPC response" VolumeAttachment="csi-043731379aa11361179f9e22a17f1fda8d2b0716696126267433bf49892e92b2" response="{}" err="rpc error: code = Canceled desc = context canceled"
I0310 15:57:32.373761  133591 csi_handler.go:611] "Saving attach error" VolumeAttachment="csi-043731379aa11361179f9e22a17f1fda8d2b0716696126267433bf49892e92b2"
I0310 15:57:32.374421  133591 csi_handler.go:267] "Failed to save attach error to VolumeAttachment" VolumeAttachment="csi-043731379aa11361179f9e22a17f1fda8d2b0716696126267433bf49892e92b2" err="client rate limiter Wait returned an error: context canceled"
I0310 15:57:32.374448  133591 csi_handler.go:243] "Error processing" VolumeAttachment="csi-043731379aa11361179f9e22a17f1fda8d2b0716696126267433bf49892e92b2" err="failed to attach: rpc error: code = Canceled desc = context canceled"
E0310 15:57:32.376055  133591 event.go:464] "Unable to record event (will not retry!)" err="broadcaster already stopped"
E0310 15:57:32.376066  133591 leader_election.go:198] "Stopped leading"

What's not so great is that the CSI driver does not know about any of this. It got ControllerPublishVolume, it is still attaching the volume and eventually it may succeed. But at the same time, another external-attacher might get the lease very quickly and call the same ControllerPublishVolume in parallel.

This could happen also today, however, before this PR, the new attacher would need to wait for the old attacher lease to expire (15 seconds in the default config). Which could give the old CSI driver enough time either complete the attachment or die (because it's unlikely that the attacher got SIGTERM and the CSI driver in the same Pod did not).

@k8s-ci-robot k8s-ci-robot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Mar 14, 2025
Comment thread cmd/csi-attacher/main.go Outdated
@msau42
Copy link
Copy Markdown
Collaborator

msau42 commented Mar 14, 2025

What's not so great is that the CSI driver does not know about any of this. It got ControllerPublishVolume, it is still attaching the volume and eventually it may succeed. But at the same time, another external-attacher might get the lease very quickly and call the same ControllerPublishVolume in parallel.

Instead of shutting down immediately on a sigterm, can we wait until all ongoing requests are finished? It would probably require changes to our reconciler.

@jsafrane
Copy link
Copy Markdown
Contributor

Instead of shutting down immediately on a sigterm, can we wait until all ongoing requests are finished? It would probably require changes to our reconciler.

We would need two contexts then and it might get messy which context should be used when.

@rhrmo can you explore this idea? I think the only place that should unblock when a signal is received would be here (to call ShutDown on all workqueues, which will then wait for existing work to finish):

And here to finish periodic reconcile:

go wait.UntilWithContext(ctx, func(ctx context.Context) {

Maybe you find other places. But it will be different in each sidecar.

@rhrmo
Copy link
Copy Markdown
Contributor Author

rhrmo commented Mar 14, 2025

Sure thing!

Comment thread cmd/csi-attacher/main.go Outdated
@rhrmo rhrmo force-pushed the restart-CSI-sidecars-faster branch from f60ce7f to e45a1ac Compare April 23, 2025 09:36
@k8s-ci-robot k8s-ci-robot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Apr 23, 2025
@rhrmo rhrmo force-pushed the restart-CSI-sidecars-faster branch 2 times, most recently from 166b06c to ff3a93f Compare April 24, 2025 12:41
@k8s-ci-robot k8s-ci-robot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label May 8, 2025
@jsafrane
Copy link
Copy Markdown
Contributor

What's not so great is that the CSI driver does not know about any of this. It got ControllerPublishVolume, it is still attaching the volume and eventually it may succeed. But at the same time, another external-attacher might get the lease very quickly and call the same ControllerPublishVolume in parallel.

Instead of shutting down immediately on a sigterm, can we wait until all ongoing requests are finished? It would probably require changes to our reconciler.

I can see there is a code that waits for workers to finish before exiting, still, they should finish with a lot of context canceled errors, because it's the main context that gets cancelled.

@rhrmo rhrmo force-pushed the restart-CSI-sidecars-faster branch from ff3a93f to 241758b Compare June 25, 2025 12:56
@k8s-ci-robot k8s-ci-robot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Jun 25, 2025
@rhrmo rhrmo force-pushed the restart-CSI-sidecars-faster branch 2 times, most recently from 16eaf56 to 9ab7f74 Compare July 3, 2025 13:17
@rhrmo rhrmo force-pushed the restart-CSI-sidecars-faster branch 3 times, most recently from e431b7f to f718411 Compare July 3, 2025 13:22
@rhrmo rhrmo changed the title [WIP] Restart external-attacher faster by releasing leader election lease on sigterm Restart external-attacher faster by releasing leader election lease on sigterm Jul 3, 2025
@k8s-ci-robot k8s-ci-robot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Jul 3, 2025
Comment thread cmd/csi-attacher/main.go Outdated
@rhrmo rhrmo force-pushed the restart-CSI-sidecars-faster branch from f718411 to e8b0aac Compare July 11, 2025 12:04
@rhrmo
Copy link
Copy Markdown
Contributor Author

rhrmo commented Jul 11, 2025

/retest-required

Comment thread pkg/controller/controller.go Outdated
Comment thread cmd/csi-attacher/main.go Outdated
@rhrmo rhrmo force-pushed the restart-CSI-sidecars-faster branch 2 times, most recently from a978bb8 to 2112285 Compare July 15, 2025 11:14
Comment thread cmd/csi-attacher/main.go Outdated
Comment on lines +325 to +332
if utilfeature.DefaultFeatureGate.Enabled(features.ReleaseLeaderElectionOnExit) {
var wg sync.WaitGroup
stopCh := shutdownHandler
factory.Start(stopCh)
ctrl.Run(controllerCtx, int(*workerThreads), &wg)
if signalReceived {
wg.Wait()
terminate()
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Just adding few comments for my future self:

Suggested change
if utilfeature.DefaultFeatureGate.Enabled(features.ReleaseLeaderElectionOnExit) {
var wg sync.WaitGroup
stopCh := shutdownHandler
factory.Start(stopCh)
ctrl.Run(controllerCtx, int(*workerThreads), &wg)
if signalReceived {
wg.Wait()
terminate()
}
if utilfeature.DefaultFeatureGate.Enabled(features.ReleaseLeaderElectionOnExit) {
var wg sync.WaitGroup
stopCh := shutdownHandler
factory.Start(stopCh)
ctrl.Run(controllerCtx, int(*workerThreads), &wg)
if signalReceived {
// Wait for the controllers to finish
wg.Wait()
// Finish the overall context and release leader election.
terminate()
}

Comment thread cmd/csi-attacher/main.go
@rhrmo rhrmo force-pushed the restart-CSI-sidecars-faster branch from 2112285 to 0f82cdb Compare July 31, 2025 11:53
Comment thread cmd/csi-attacher/main.go Outdated
stopCh := shutdownHandler
factory.Start(stopCh)
ctrl.Run(controllerCtx, int(*workerThreads), &wg)
if signalReceived {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Can Run() above finish without a signal received? Assuming it could, what would be the right handling? IMO releasing the leader election + exit (i.e. terminate()) would be correct in all cases where Run() finishes.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I.e. IMO we could remove the whole variable signalReceived

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I think Run() should be able to finish without signal but I am not entirely sure now that you ask, I will test it. I agree with releasing the leader election + exit after Run() finishes.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I removed the whole signalReceived variable, testing Run() is bit tricky though because it waits for the context to be cancelled before it returns, by trying to call return at it's end instead <-ctx.Done() it finished without any issues.

@k8s-ci-robot k8s-ci-robot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Aug 1, 2025
@rhrmo rhrmo force-pushed the restart-CSI-sidecars-faster branch from 0f82cdb to 7d82cda Compare August 8, 2025 07:51
@rhrmo rhrmo force-pushed the restart-CSI-sidecars-faster branch from 7d82cda to 40429ec Compare August 8, 2025 10:50
@k8s-ci-robot k8s-ci-robot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Aug 8, 2025
@rhrmo rhrmo force-pushed the restart-CSI-sidecars-faster branch from 40429ec to 7aaec36 Compare August 12, 2025 07:02
@jsafrane
Copy link
Copy Markdown
Contributor

/lgtm

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Aug 12, 2025
@jsafrane
Copy link
Copy Markdown
Contributor

/approve

@k8s-ci-robot
Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: jsafrane, rhrmo

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@k8s-ci-robot k8s-ci-robot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Aug 12, 2025
@k8s-ci-robot k8s-ci-robot merged commit f7f1804 into kubernetes-csi:master Aug 12, 2025
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. kind/bug Categorizes issue or PR as related to a bug. lgtm "Looks good to me", indicates that a PR is ready to be merged. ok-to-test Indicates a non-member PR verified by an org member that is safe to test. release-note-none Denotes a PR that doesn't merit a release note. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Release lease on SIGTERM

6 participants