leaderelection

package
v0.2.0-alpha.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 5, 2026 License: Apache-2.0 Imports: 10 Imported by: 0

README

pkg/k8s/leaderelection

Pure leader election library wrapping k8s.io/client-go/tools/leaderelection.

Overview

Provides a clean interface for leader election using Kubernetes Lease resources. This is a pure library with no dependencies on the event bus or controller coordination logic.

Usage

import (
    "context"
    "log/slog"
    "time"

    "k8s.io/client-go/kubernetes"
    "gitlab.com/haproxy-haptic/haptic/pkg/k8s/leaderelection"
)

config := &leaderelection.Config{
    Enabled:         true, // New() returns an error if this is false
    Identity:        "pod-1",
    LeaseName:       "my-app-leader",
    LeaseNamespace:  "default",
    LeaseDuration:   15 * time.Second,
    RenewDeadline:   10 * time.Second,
    RetryPeriod:     2 * time.Second,
    ReleaseOnCancel: true,
}

callbacks := leaderelection.Callbacks{
    OnStartedLeading: func(ctx context.Context) {
        // ctx is cancelled the moment leadership is lost — derive any
        // long-running work from it so it stops naturally.
        log.Println("Became leader")
    },
    OnStoppedLeading: func() {
        log.Println("Lost leadership")
    },
    OnNewLeader: func(identity string) {
        log.Printf("New leader: %s", identity)
    },
}

elector, err := leaderelection.New(config, clientset, callbacks, logger)
if err != nil {
    panic(err)
}

// Start blocks until the parent context is cancelled or the lease loop
// errors, so run it on its own goroutine.
ctx := context.Background()
go func() {
    if err := elector.Start(ctx); err != nil {
        log.Printf("leader election ended: %v", err)
    }
}()

API

Config

Configuration for leader election:

  • Enabled: Whether leader election is active
  • Identity: Unique identifier (usually pod name)
  • LeaseName: Name of Lease resource
  • LeaseNamespace: Namespace of Lease resource
  • LeaseDuration: How long non-leaders wait before forcing acquisition
  • RenewDeadline: How long leader retries before giving up
  • RetryPeriod: Wait duration between retry attempts
  • ReleaseOnCancel: Release leadership when context cancelled
Callbacks

Event callbacks:

  • OnStartedLeading(ctx): Called when becoming leader
  • OnStoppedLeading(): Called when losing leadership
  • OnNewLeader(identity): Called when new leader observed
Elector

Main leader election type:

  • New(*Config, kubernetes.Interface, Callbacks, *slog.Logger) (*Elector, error) — validates inputs and returns an unstarted elector. Returns an error when Config.Enabled is false, when Identity, LeaseName, or LeaseNamespace is empty, or when the clientset is nil.
  • Start(ctx) error — runs the lease loop and blocks until ctx is cancelled, the underlying client errors, or an acquired lease is lost. Run on a goroutine. Leadership state is observed through the Callbacks (OnStartedLeading / OnStoppedLeading / OnNewLeader); there are no snapshot accessors.
  • Lost-lease semantics: client-go's LeaderElector.Run returns permanently after a lost lease (it does not re-enter the acquire loop), so Start returns nil with the caller's context still alive. Callers that need re-election must restart Start themselves — the controller does this by reinitializing (pkg/controller/leader.go, superviseElection).

Thread Safety

All public methods are thread-safe and can be called concurrently.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Callbacks

type Callbacks struct {
	// OnStartedLeading is called when the instance becomes the leader
	OnStartedLeading func(ctx context.Context)

	// OnStoppedLeading is called when the instance stops being the leader
	OnStoppedLeading func()

	// OnNewLeader is called when a new leader is observed (may be self or another instance)
	OnNewLeader func(identity string)
}

Callbacks contains callback functions for leader election events.

type Config

type Config struct {
	// Enabled determines if leader election is active
	Enabled bool

	// Identity is the unique identifier of this instance (usually pod name)
	Identity string

	// LeaseName is the name of the Lease resource
	LeaseName string

	// LeaseNamespace is the namespace of the Lease resource
	LeaseNamespace string

	// LeaseDuration is the duration that non-leader candidates will wait to force acquire leadership
	LeaseDuration time.Duration

	// RenewDeadline is the duration that the acting leader will retry refreshing leadership before giving up
	RenewDeadline time.Duration

	// RetryPeriod is the duration the LeaderElector clients should wait between tries of actions
	RetryPeriod time.Duration

	// ReleaseOnCancel should be true to release leadership when the context is cancelled
	ReleaseOnCancel bool
}

Config contains configuration for leader election.

type Elector

type Elector struct {
	// contains filtered or unexported fields
}

Elector manages leader election using Kubernetes Lease resources.

This is a pure component that wraps k8s.io/client-go/tools/leaderelection with a clean interface. It has no dependencies on the event bus or controller coordination logic.

func New

func New(
	config *Config,
	clientset kubernetes.Interface,
	callbacks Callbacks,
	logger *slog.Logger,
) (*Elector, error)

New creates a new leader elector.

The elector is not started until Start() is called.

func (*Elector) Start

func (e *Elector) Start(ctx context.Context) error

Start starts the leader election loop.

This function blocks until the context is cancelled or an error occurs. It should be run in a goroutine.

Lost-lease semantics: client-go's LeaderElector.Run returns permanently when an acquired lease is lost (renewal missed its deadline), after invoking OnStoppedLeading — it does NOT re-enter the acquire loop. In that case Start returns nil while the caller's context is still alive. Callers that need leadership to ever be re-acquired must treat that return as abnormal and restart election themselves (the controller does this by failing the iteration and reinitializing — see pkg/controller/leader.go's superviseElection).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL