Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Dec 15, 2025

LeaderElector.TryAcquireOrRenew was using the locally configured lease duration instead of the value from the Kubernetes object, breaking graceful step-downs where leaders signal their departure by setting lease duration to 1 second.

Changes

  • Use oldLeaderElectionRecord.LeaseDurationSeconds from the Kubernetes object instead of config.LeaseDuration when checking lease expiration
  • Add unit test LeaderElectionUsesActualLeaseDurationFromKubernetesObject to verify the fix
// Before: ignores actual lease duration from K8s
if (!string.IsNullOrEmpty(oldLeaderElectionRecord.HolderIdentity)
    && observedTime + config.LeaseDuration > DateTimeOffset.Now
    && !IsLeader())

// After: respects actual lease duration from K8s object
if (!string.IsNullOrEmpty(oldLeaderElectionRecord.HolderIdentity)
    && observedTime + TimeSpan.FromSeconds(oldLeaderElectionRecord.LeaseDurationSeconds) > DateTimeOffset.Now
    && !IsLeader())

This aligns the C# implementation with the Go client-go behavior.

Testing

  • ✅ All 7 leader election tests pass
  • ✅ New test validates that actual lease duration (1 second for graceful step-down) is respected instead of configured duration (10 seconds)
Original prompt

This section details on the original issue you should resolve

<issue_title>Actual lease duration is ignored in LeaderElector.TryAcquireOrRenew</issue_title>
<issue_description>Describe the bug
LeaderElector.TryAcquireOrRenew uses the lease duration from the local configuration, instead of the Kubernetes object, assuming that the two values are the same.

This might not be true during graceful step downs, as libraries like the one for Golang set the lease duration to 1 second as a way to signal the leader has stepped down. C# clients would ignore this and still wait for the entire pre-configured duration of the lease before trying to acquire the lease.

This behaviour also differs from the Golang library, which uses the lease duration from the actual Kubernetes object.

Kubernetes C# SDK Client Version
14.0.2

Server Kubernetes Version
1.30.13

Dotnet Runtime Version
net8

To Reproduce
Create a lease and change its duration to 1s

Expected behavior
Non-leader C# clients should try to take the lease

Where do you run your app with Kubernetes SDK (please complete the following information):

  • OS: Linux
  • Environment: Container
  • Cloud: AWS and on-prem
    </issue_description>

<agent_instructions>fix this</agent_instructions>

Comments on the Issue (you are @copilot in this section)

@tg123 agreed, there is some gap between the golang and .net and those should be filled, let me take a look @k8s-ci-robot @k8s-triage-robot: Closing this issue, marking it as "Not Planned".
Details

In response to this:

The Kubernetes project currently lacks enough active contributors to adequately respond to all issues and PRs.

This bot triages issues according to the following rules:

  • After 90d of inactivity, lifecycle/stale is applied
  • After 30d of inactivity since lifecycle/stale was applied, lifecycle/rotten is applied
  • After 30d of inactivity since lifecycle/rotten was applied, the issue is closed

You can:

  • Reopen this issue with /reopen
  • Mark this issue as fresh with /remove-lifecycle rotten
  • Offer to help out with Issue Triage

Please send feedback to sig-contributor-experience at kubernetes/community.

/close not-planned

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.


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

@k8s-ci-robot k8s-ci-robot added do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. size/XS Denotes a PR that changes 0-9 lines, ignoring generated files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. labels Dec 15, 2025
Changed LeaderElector.TryAcquireOrRenew to use the lease duration from the
Kubernetes object (oldLeaderElectionRecord.LeaseDurationSeconds) instead of
the configured lease duration (config.LeaseDuration).

This fixes the issue where graceful step-downs (where leaders set lease
duration to 1 second) were being ignored by C# clients, which continued to
wait for the full configured lease duration before attempting to acquire
leadership.

This brings the C# implementation in line with the Go client-go library
behavior.

Fixes kubernetes-client/csharp#1819

Co-authored-by: tg123 <170430+tg123@users.noreply.github.com>
@k8s-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: Copilot
Once this PR has been reviewed and has the lgtm label, please ask for approval from tg123. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found 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

1 similar comment
@k8s-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: Copilot
Once this PR has been reviewed and has the lgtm label, please ask for approval from tg123. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found 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

Copilot AI changed the title [WIP] Fix lease duration handling in LeaderElector.TryAcquireOrRenew Use actual lease duration from Kubernetes object in leader election Dec 15, 2025
Copilot AI requested a review from tg123 December 15, 2025 23:47
@tg123
Copy link
Member

tg123 commented Dec 26, 2025

@copilot could you please add ut

Added LeaderElectionUsesActualLeaseDurationFromKubernetesObject test to verify
that the leader election logic correctly uses the actual lease duration from the
Kubernetes object (LeaseDurationSeconds) instead of the configured lease duration.

This test specifically validates the graceful step-down scenario where a leader
sets the lease duration to 1 second to signal it has stepped down, ensuring that
other clients respect this short duration rather than waiting for the full
configured duration.

Co-authored-by: tg123 <170430+tg123@users.noreply.github.com>
@k8s-ci-robot k8s-ci-robot added size/M Denotes a PR that changes 30-99 lines, ignoring generated files. and removed size/XS Denotes a PR that changes 0-9 lines, ignoring generated files. labels Dec 26, 2025
Copy link
Contributor Author

Copilot AI commented Dec 26, 2025

@copilot could you please add ut

Added unit test in commit 826586f. The test LeaderElectionUsesActualLeaseDurationFromKubernetesObject validates that the actual lease duration from the Kubernetes object (1 second for graceful step-down) is respected instead of the configured duration (10 seconds). All 7 leader election tests pass.

@tg123 tg123 marked this pull request as ready for review December 28, 2025 09:05
Copilot AI review requested due to automatic review settings December 28, 2025 09:05
@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 Dec 28, 2025
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes a bug where the leader election mechanism was using the locally configured lease duration instead of the actual lease duration from the Kubernetes object. This prevented proper handling of graceful leader step-downs, where outgoing leaders signal their departure by setting the lease duration to 1 second. The fix aligns the C# implementation with the Go client-go behavior.

Key changes:

  • Modified lease expiration check to use the actual LeaseDurationSeconds value from the Kubernetes object instead of the configured duration
  • Added comprehensive unit test to validate that graceful step-downs with 1-second lease durations work correctly

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
src/KubernetesClient/LeaderElection/LeaderElector.cs Updated TryAcquireOrRenew method to use oldLeaderElectionRecord.LeaseDurationSeconds instead of config.LeaseDuration when checking if a lease has expired
tests/KubernetesClient.Tests/LeaderElection/LeaderElectionTests.cs Added test LeaderElectionUsesActualLeaseDurationFromKubernetesObject that validates the fix by ensuring a 1-second lease duration from the Kubernetes object is respected instead of a 10-second configured duration

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

…s.cs

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. size/M Denotes a PR that changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Actual lease duration is ignored in LeaderElector.TryAcquireOrRenew

3 participants