@@ -351,6 +351,16 @@ func (cm *controllerManager) Start(ctx context.Context) (err error) {
351351 // Initialize the internal context.
352352 cm .internalCtx , cm .internalCancel = context .WithCancel (ctx )
353353
354+ // Leader elector must be created before defer that contains engageStopProcedure function
355+ // https://github.com/kubernetes-sigs/controller-runtime/issues/2873
356+ var leaderElector * leaderelection.LeaderElector
357+ if cm .resourceLock != nil {
358+ leaderElector , err = cm .initLeaderElector ()
359+ if err != nil {
360+ return fmt .Errorf ("failed during initialization leader election process: %w" , err )
361+ }
362+ }
363+
354364 // This chan indicates that stop is complete, in other words all runnables have returned or timeout on stop request
355365 stopComplete := make (chan struct {})
356366 defer close (stopComplete )
@@ -433,19 +443,22 @@ func (cm *controllerManager) Start(ctx context.Context) (err error) {
433443 {
434444 ctx , cancel := context .WithCancel (context .Background ())
435445 cm .leaderElectionCancel = cancel
436- go func () {
437- if cm .resourceLock != nil {
438- if err := cm .startLeaderElection (ctx ); err != nil {
439- cm .errChan <- err
440- }
441- } else {
446+ if leaderElector != nil {
447+ // Start the leader elector process
448+ go func () {
449+ leaderElector .Run (ctx )
450+ <- ctx .Done ()
451+ close (cm .leaderElectionStopped )
452+ }()
453+ } else {
454+ go func () {
442455 // Treat not having leader election enabled the same as being elected.
443456 if err := cm .startLeaderElectionRunnables (); err != nil {
444457 cm .errChan <- err
445458 }
446459 close (cm .elected )
447- }
448- }()
460+ }()
461+ }
449462 }
450463
451464 ready = true
@@ -564,12 +577,8 @@ func (cm *controllerManager) engageStopProcedure(stopComplete <-chan struct{}) e
564577 return nil
565578}
566579
567- func (cm * controllerManager ) startLeaderElectionRunnables () error {
568- return cm .runnables .LeaderElection .Start (cm .internalCtx )
569- }
570-
571- func (cm * controllerManager ) startLeaderElection (ctx context.Context ) (err error ) {
572- l , err := leaderelection .NewLeaderElector (leaderelection.LeaderElectionConfig {
580+ func (cm * controllerManager ) initLeaderElector () (* leaderelection.LeaderElector , error ) {
581+ leaderElector , err := leaderelection .NewLeaderElector (leaderelection.LeaderElectionConfig {
573582 Lock : cm .resourceLock ,
574583 LeaseDuration : cm .leaseDuration ,
575584 RenewDeadline : cm .renewDeadline ,
@@ -599,16 +608,14 @@ func (cm *controllerManager) startLeaderElection(ctx context.Context) (err error
599608 Name : cm .leaderElectionID ,
600609 })
601610 if err != nil {
602- return err
611+ return nil , err
603612 }
604613
605- // Start the leader elector process
606- go func () {
607- l .Run (ctx )
608- <- ctx .Done ()
609- close (cm .leaderElectionStopped )
610- }()
611- return nil
614+ return leaderElector , nil
615+ }
616+
617+ func (cm * controllerManager ) startLeaderElectionRunnables () error {
618+ return cm .runnables .LeaderElection .Start (cm .internalCtx )
612619}
613620
614621func (cm * controllerManager ) Elected () <- chan struct {} {
0 commit comments