Skip to main content

LeaderElection

Struct LeaderElection 

Source
pub struct LeaderElection { /* private fields */ }
Expand description

Lease-based leader election, allowing multiple replicas of a controller to run while ensuring that only one of them is reconciling at a time.

This uses a coordination.k8s.io/v1 Lease object, following the same protocol (and using the same default timings) as the Kubernetes client-go leaderelection package: the leader repeatedly renews the lease, and other candidates take the lease over if the leader fails to renew it for lease_duration. Expiry is determined by observing the lease go unchanged for lease_duration, rather than by comparing timestamps in the lease against the local clock, so it is robust to clock skew between candidates. Note that this protocol is cooperative: it guarantees mutual exclusion only among candidates that respect the lease.

The controller’s service account needs get, create, and update permissions on leases in the coordination.k8s.io API group for this to work.

The identity must be non-empty and unique among the candidates for a given lease; the pod name (available in the HOSTNAME environment variable, or via the downward API) is a good choice. Beware that candidates for the same lease which share an identity will each mistake the other’s renewals for their own and all act as leader simultaneously, so never create multiple LeaderElections in the same process with the same lease name and identity. To have one lease guard several controllers in a process, share a single LeaderElection via with_lease instead.

Implementations§

Source§

impl LeaderElection

Source

pub fn new( client: Client, namespace: &str, lease_name: &str, identity: &str, ) -> Self

Creates a leader election configuration for the Lease named lease_name in the given namespace, identifying this instance of the controller as identity. The timings default to the client-go defaults: a lease duration of 15 seconds, a renew deadline of 10 seconds, and a retry period of 2 seconds.

Source

pub fn with_lease_duration(self, lease_duration: Duration) -> Self

Sets how long a non-leader must wait after the last observed change to the lease before forcibly taking it over. Larger values slow down failover; smaller values increase the risk that a leader which is still running (but partitioned from the API server) has not yet stopped reconciling when the new leader starts. Must be greater than the renew deadline.

Source

pub fn with_renew_deadline(self, renew_deadline: Duration) -> Self

Sets how long the leader will keep trying to renew the lease before giving up leadership. Must be less than the lease duration (so that a leader which cannot reach the API server gives up before another candidate can take the lease over) and greater than the retry period.

Source

pub fn with_retry_period(self, retry_period: Duration) -> Self

Sets how often candidates poll the lease while waiting to acquire it, and how often the leader renews it.

Source

pub async fn with_lease<F: Future>(&self, fut: F) -> Option<F::Output>

Wait until this instance holds the lease, then run fut while renewing the lease in the background.

If leadership is lost (because the lease could not be renewed in time, or was taken over by another candidate), fut is dropped, cancelling its work, and this method returns None. The caller should then promptly either exit the process (letting Kubernetes restart it) or rejoin the election by calling this method again. Note that dropping fut cancels it cooperatively: work it has spawned as separate tasks, or blocking code, is not cancelled. If fut does such things, prefer exiting the process so that no work outlives the lease.

If fut completes on its own, the lease is voluntarily released (handing leadership over immediately rather than making the other candidates wait for it to expire) and its output is returned.

To run a Controller under a lease, pass its run future; to have one lease guard several controllers (rather than electing a separate leader per controller), pass a future that runs all of them, for instance:

leader_election
    .with_lease(futures::future::join(controller_a.run(), controller_b.run()))
    .await;

During graceful shutdown (for instance, on receiving a termination signal), drop the future returned by this method to stop its work, then call release on a clone of this LeaderElection to hand leadership over immediately rather than making the other replicas wait for the lease to expire.

Panics if the configured timings are inconsistent or the identity is empty.

Source

pub async fn release(&self)

Voluntarily release the lease if we hold it, allowing another candidate to take it over immediately rather than waiting for it to expire. Call this during graceful shutdown, after the controller has stopped reconciling (for instance, after the future returned by with_lease has been dropped in response to a termination signal). This is best-effort: errors are logged and ignored, since the lease will expire on its own regardless.

Trait Implementations§

Source§

impl Clone for LeaderElection

Source§

fn clone(&self) -> LeaderElection

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DynClone for T
where T: Clone,

Source§

fn __clone_box(&self, _: Private) -> *mut ()

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ServiceExt for T

Source§

fn map_response_body<F>(self, f: F) -> MapResponseBody<Self, F>
where Self: Sized,

Apply a transformation to the response body. Read more
Source§

fn decompression(self) -> Decompression<Self>
where Self: Sized,

Decompress response bodies. Read more
Source§

fn trace_for_http(self) -> Trace<Self, SharedClassifier<ServerErrorsAsFailures>>
where Self: Sized,

High level tracing that classifies responses using HTTP status codes. Read more
Source§

fn trace_for_grpc(self) -> Trace<Self, SharedClassifier<GrpcErrorsAsFailures>>
where Self: Sized,

High level tracing that classifies responses using gRPC headers. Read more
Source§

fn follow_redirects(self) -> FollowRedirect<Self>
where Self: Sized,

Follow redirect resposes using the Standard policy. Read more
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more