@@ -623,20 +623,18 @@ func CreateControllerContext(logger klog.Logger, s *config.CompletedConfig, root
623623// StartControllers starts a set of controllers with a specified ControllerContext
624624func StartControllers (ctx context.Context , controllerCtx ControllerContext , controllerDescriptors map [string ]* ControllerDescriptor ,
625625unsecuredMux * mux.PathRecorderMux , healthzHandler * controllerhealthz.MutableHealthzHandler ) error {
626- logger := klog . FromContext ( ctx )
626+ var controllerChecks []healthz. HealthChecker
627627
628628// Always start the SA token controller first using a full-power client, since it needs to mint tokens for the rest
629629// If this fails, just return here and fail since other controllers won't be able to get credentials.
630630if serviceAccountTokenControllerDescriptor , ok := controllerDescriptors [names .ServiceAccountTokenController ]; ok {
631- controllerName := serviceAccountTokenControllerDescriptor .Name ()
632- if ! controllerCtx .IsControllerEnabled (serviceAccountTokenControllerDescriptor ) {
633- logger .Info ("Warning: controller is disabled" , "controller" , controllerName )
634- } else {
635- logger .V (1 ).Info ("Starting controller" , "controller" , controllerName )
636- initFunc := serviceAccountTokenControllerDescriptor .GetInitFunc ()
637- if _ , _ , err := initFunc (klog .NewContext (ctx , klog .LoggerWithName (logger , controllerName )), controllerCtx , controllerName ); err != nil {
638- return err
639- }
631+ check , err := StartController (ctx , controllerCtx , serviceAccountTokenControllerDescriptor , unsecuredMux )
632+ if err != nil {
633+ return err
634+ }
635+ if check != nil {
636+ // HealthChecker should be present when controller has started
637+ controllerChecks = append (controllerChecks , check )
640638}
641639}
642640
@@ -646,83 +644,94 @@ func StartControllers(ctx context.Context, controllerCtx ControllerContext, cont
646644controllerCtx .Cloud .Initialize (controllerCtx .ClientBuilder , ctx .Done ())
647645}
648646
649- var controllerChecks []healthz.HealthChecker
650-
651647// Each controller is passed a context where the logger has the name of
652648// the controller set through WithName. That name then becomes the prefix of
653649// of all log messages emitted by that controller.
654650//
655- // In this loop , an explicit "controller" key is used instead, for two reasons:
651+ // In StartController , an explicit "controller" key is used instead, for two reasons:
656652// - while contextual logging is alpha, klog.LoggerWithName is still a no-op,
657653// so we cannot rely on it yet to add the name
658654// - it allows distinguishing between log entries emitted by the controller
659655// and those emitted for it - this is a bit debatable and could be revised.
660- for controllerName , controllerDesc := range controllerDescriptors {
656+ for _ , controllerDesc := range controllerDescriptors {
661657if controllerDesc .RequiresSpecialHandling () {
662658continue
663659}
664660
665- disabledByFeatureGate := false
666- for _ , featureGate := range controllerDesc .GetRequiredFeatureGates () {
667- if ! utilfeature .DefaultFeatureGate .Enabled (featureGate ) {
668- disabledByFeatureGate = true
669- break
670- }
661+ check , err := StartController (ctx , controllerCtx , controllerDesc , unsecuredMux )
662+ if err != nil {
663+ return err
671664}
672- if disabledByFeatureGate {
673- logger . Info ( "Controller is disabled by a feature gate" , " controller" , controllerName , "requiredFeatureGates" , controllerDesc . GetRequiredFeatureGates ())
674- continue
665+ if check != nil {
666+ // HealthChecker should be present when controller has started
667+ controllerChecks = append ( controllerChecks , check )
675668}
669+ }
676670
677- if controllerDesc .IsCloudProviderController () && controllerCtx .LoopMode != IncludeCloudLoops {
678- logger .Info ("Skipping a cloud provider controller" , "controller" , controllerName , "loopMode" , controllerCtx .LoopMode )
679- continue
680- }
671+ healthzHandler .AddHealthChecker (controllerChecks ... )
681672
682- if ! controllerCtx .IsControllerEnabled (controllerDesc ) {
683- logger .Info ("Warning: controller is disabled" , "controller" , controllerName )
684- continue
673+ return nil
674+ }
675+
676+ // StartController starts a controller with a specified ControllerContext
677+ // and performs required pre- and post- checks/actions
678+ func StartController (ctx context.Context , controllerCtx ControllerContext , controllerDescriptor * ControllerDescriptor ,
679+ unsecuredMux * mux.PathRecorderMux ) (healthz.HealthChecker , error ) {
680+ logger := klog .FromContext (ctx )
681+ controllerName := controllerDescriptor .Name ()
682+
683+ for _ , featureGate := range controllerDescriptor .GetRequiredFeatureGates () {
684+ if ! utilfeature .DefaultFeatureGate .Enabled (featureGate ) {
685+ logger .Info ("Controller is disabled by a feature gate" , "controller" , controllerName , "requiredFeatureGates" , controllerDescriptor .GetRequiredFeatureGates ())
686+ return nil , nil
685687}
688+ }
686689
687- time .Sleep (wait .Jitter (controllerCtx .ComponentConfig .Generic .ControllerStartInterval .Duration , ControllerStartJitter ))
690+ if controllerDescriptor .IsCloudProviderController () && controllerCtx .LoopMode != IncludeCloudLoops {
691+ logger .Info ("Skipping a cloud provider controller" , "controller" , controllerName , "loopMode" , controllerCtx .LoopMode )
692+ return nil , nil
693+ }
688694
689- logger .V (1 ).Info ("Starting controller" , "controller" , controllerName )
695+ if ! controllerCtx .IsControllerEnabled (controllerDescriptor ) {
696+ logger .Info ("Warning: controller is disabled" , "controller" , controllerName )
697+ return nil , nil
698+ }
690699
691- initFunc := controllerDesc .GetInitFunc ()
692- ctrl , started , err := initFunc (klog .NewContext (ctx , klog .LoggerWithName (logger , controllerName )), controllerCtx , controllerName )
693- if err != nil {
694- logger .Error (err , "Error starting controller" , "controller" , controllerName )
695- return err
696- }
697- if ! started {
698- logger .Info ("Warning: skipping controller" , "controller" , controllerName )
699- continue
700- }
701- check := controllerhealthz .NamedPingChecker (controllerName )
702- if ctrl != nil {
703- // check if the controller supports and requests a debugHandler
704- // and it needs the unsecuredMux to mount the handler onto.
705- if debuggable , ok := ctrl .(controller.Debuggable ); ok && unsecuredMux != nil {
706- if debugHandler := debuggable .DebuggingHandler (); debugHandler != nil {
707- basePath := "/debug/controllers/" + controllerName
708- unsecuredMux .UnlistedHandle (basePath , http .StripPrefix (basePath , debugHandler ))
709- unsecuredMux .UnlistedHandlePrefix (basePath + "/" , http .StripPrefix (basePath , debugHandler ))
710- }
700+ time .Sleep (wait .Jitter (controllerCtx .ComponentConfig .Generic .ControllerStartInterval .Duration , ControllerStartJitter ))
701+
702+ logger .V (1 ).Info ("Starting controller" , "controller" , controllerName )
703+
704+ initFunc := controllerDescriptor .GetInitFunc ()
705+ ctrl , started , err := initFunc (klog .NewContext (ctx , klog .LoggerWithName (logger , controllerName )), controllerCtx , controllerName )
706+ if err != nil {
707+ logger .Error (err , "Error starting controller" , "controller" , controllerName )
708+ return nil , err
709+ }
710+ if ! started {
711+ logger .Info ("Warning: skipping controller" , "controller" , controllerName )
712+ return nil , nil
713+ }
714+
715+ check := controllerhealthz .NamedPingChecker (controllerName )
716+ if ctrl != nil {
717+ // check if the controller supports and requests a debugHandler
718+ // and it needs the unsecuredMux to mount the handler onto.
719+ if debuggable , ok := ctrl .(controller.Debuggable ); ok && unsecuredMux != nil {
720+ if debugHandler := debuggable .DebuggingHandler (); debugHandler != nil {
721+ basePath := "/debug/controllers/" + controllerName
722+ unsecuredMux .UnlistedHandle (basePath , http .StripPrefix (basePath , debugHandler ))
723+ unsecuredMux .UnlistedHandlePrefix (basePath + "/" , http .StripPrefix (basePath , debugHandler ))
711724}
712- if healthCheckable , ok := ctrl .(controller. HealthCheckable ); ok {
713- if realCheck := healthCheckable . HealthChecker ( ); realCheck != nil {
714- check = controllerhealthz . NamedHealthChecker ( controllerName , realCheck )
715- }
725+ }
726+ if healthCheckable , ok := ctrl .(controller. HealthCheckable ); ok {
727+ if realCheck := healthCheckable . HealthChecker (); realCheck != nil {
728+ check = controllerhealthz . NamedHealthChecker ( controllerName , realCheck )
716729}
717730}
718- controllerChecks = append (controllerChecks , check )
719-
720- logger .Info ("Started controller" , "controller" , controllerName )
721731}
722732
723- healthzHandler .AddHealthChecker (controllerChecks ... )
724-
725- return nil
733+ logger .Info ("Started controller" , "controller" , controllerName )
734+ return check , nil
726735}
727736
728737// serviceAccountTokenControllerStarter is special because it must run first to set up permissions for other controllers.
0 commit comments