move start controller pre- and post- checks/actions out of StartControllers

into StartController function

the function is reused by ServiceAccountTokenController
This commit is contained in:
Filip Křepinský 2023-09-18 23:16:15 +02:00
parent b768967280
commit 44cac26667

View File

@ -623,20 +623,18 @@ func CreateControllerContext(logger klog.Logger, s *config.CompletedConfig, root
// StartControllers starts a set of controllers with a specified ControllerContext // StartControllers starts a set of controllers with a specified ControllerContext
func StartControllers(ctx context.Context, controllerCtx ControllerContext, controllerDescriptors map[string]*ControllerDescriptor, func StartControllers(ctx context.Context, controllerCtx ControllerContext, controllerDescriptors map[string]*ControllerDescriptor,
unsecuredMux *mux.PathRecorderMux, healthzHandler *controllerhealthz.MutableHealthzHandler) error { unsecuredMux *mux.PathRecorderMux, healthzHandler *controllerhealthz.MutableHealthzHandler) error {
logger := klog.FromContext(ctx) var controllerChecks []healthz.HealthChecker
// Always start the SA token controller first using a full-power client, since it needs to mint tokens for the rest // Always start the SA token controller first using a full-power client, since it needs to mint tokens for the rest
// If this fails, just return here and fail since other controllers won't be able to get credentials. // If this fails, just return here and fail since other controllers won't be able to get credentials.
if serviceAccountTokenControllerDescriptor, ok := controllerDescriptors[names.ServiceAccountTokenController]; ok { if serviceAccountTokenControllerDescriptor, ok := controllerDescriptors[names.ServiceAccountTokenController]; ok {
controllerName := serviceAccountTokenControllerDescriptor.Name() check, err := StartController(ctx, controllerCtx, serviceAccountTokenControllerDescriptor, unsecuredMux)
if !controllerCtx.IsControllerEnabled(serviceAccountTokenControllerDescriptor) { if err != nil {
logger.Info("Warning: controller is disabled", "controller", controllerName)
} else {
logger.V(1).Info("Starting controller", "controller", controllerName)
initFunc := serviceAccountTokenControllerDescriptor.GetInitFunc()
if _, _, err := initFunc(klog.NewContext(ctx, klog.LoggerWithName(logger, controllerName)), controllerCtx, controllerName); err != nil {
return err return err
} }
if check != nil {
// HealthChecker should be present when controller has started
controllerChecks = append(controllerChecks, check)
} }
} }
@ -646,58 +644,74 @@ func StartControllers(ctx context.Context, controllerCtx ControllerContext, cont
controllerCtx.Cloud.Initialize(controllerCtx.ClientBuilder, ctx.Done()) controllerCtx.Cloud.Initialize(controllerCtx.ClientBuilder, ctx.Done())
} }
var controllerChecks []healthz.HealthChecker
// Each controller is passed a context where the logger has the name of // Each controller is passed a context where the logger has the name of
// the controller set through WithName. That name then becomes the prefix of // the controller set through WithName. That name then becomes the prefix of
// of all log messages emitted by that controller. // of all log messages emitted by that controller.
// //
// In this loop, an explicit "controller" key is used instead, for two reasons: // In StartController, an explicit "controller" key is used instead, for two reasons:
// - while contextual logging is alpha, klog.LoggerWithName is still a no-op, // - while contextual logging is alpha, klog.LoggerWithName is still a no-op,
// so we cannot rely on it yet to add the name // so we cannot rely on it yet to add the name
// - it allows distinguishing between log entries emitted by the controller // - it allows distinguishing between log entries emitted by the controller
// and those emitted for it - this is a bit debatable and could be revised. // and those emitted for it - this is a bit debatable and could be revised.
for controllerName, controllerDesc := range controllerDescriptors { for _, controllerDesc := range controllerDescriptors {
if controllerDesc.RequiresSpecialHandling() { if controllerDesc.RequiresSpecialHandling() {
continue continue
} }
disabledByFeatureGate := false check, err := StartController(ctx, controllerCtx, controllerDesc, unsecuredMux)
for _, featureGate := range controllerDesc.GetRequiredFeatureGates() { if err != nil {
return err
}
if check != nil {
// HealthChecker should be present when controller has started
controllerChecks = append(controllerChecks, check)
}
}
healthzHandler.AddHealthChecker(controllerChecks...)
return nil
}
// StartController starts a controller with a specified ControllerContext
// and performs required pre- and post- checks/actions
func StartController(ctx context.Context, controllerCtx ControllerContext, controllerDescriptor *ControllerDescriptor,
unsecuredMux *mux.PathRecorderMux) (healthz.HealthChecker, error) {
logger := klog.FromContext(ctx)
controllerName := controllerDescriptor.Name()
for _, featureGate := range controllerDescriptor.GetRequiredFeatureGates() {
if !utilfeature.DefaultFeatureGate.Enabled(featureGate) { if !utilfeature.DefaultFeatureGate.Enabled(featureGate) {
disabledByFeatureGate = true logger.Info("Controller is disabled by a feature gate", "controller", controllerName, "requiredFeatureGates", controllerDescriptor.GetRequiredFeatureGates())
break return nil, nil
} }
} }
if disabledByFeatureGate {
logger.Info("Controller is disabled by a feature gate", "controller", controllerName, "requiredFeatureGates", controllerDesc.GetRequiredFeatureGates())
continue
}
if controllerDesc.IsCloudProviderController() && controllerCtx.LoopMode != IncludeCloudLoops { if controllerDescriptor.IsCloudProviderController() && controllerCtx.LoopMode != IncludeCloudLoops {
logger.Info("Skipping a cloud provider controller", "controller", controllerName, "loopMode", controllerCtx.LoopMode) logger.Info("Skipping a cloud provider controller", "controller", controllerName, "loopMode", controllerCtx.LoopMode)
continue return nil, nil
} }
if !controllerCtx.IsControllerEnabled(controllerDesc) { if !controllerCtx.IsControllerEnabled(controllerDescriptor) {
logger.Info("Warning: controller is disabled", "controller", controllerName) logger.Info("Warning: controller is disabled", "controller", controllerName)
continue return nil, nil
} }
time.Sleep(wait.Jitter(controllerCtx.ComponentConfig.Generic.ControllerStartInterval.Duration, ControllerStartJitter)) time.Sleep(wait.Jitter(controllerCtx.ComponentConfig.Generic.ControllerStartInterval.Duration, ControllerStartJitter))
logger.V(1).Info("Starting controller", "controller", controllerName) logger.V(1).Info("Starting controller", "controller", controllerName)
initFunc := controllerDesc.GetInitFunc() initFunc := controllerDescriptor.GetInitFunc()
ctrl, started, err := initFunc(klog.NewContext(ctx, klog.LoggerWithName(logger, controllerName)), controllerCtx, controllerName) ctrl, started, err := initFunc(klog.NewContext(ctx, klog.LoggerWithName(logger, controllerName)), controllerCtx, controllerName)
if err != nil { if err != nil {
logger.Error(err, "Error starting controller", "controller", controllerName) logger.Error(err, "Error starting controller", "controller", controllerName)
return err return nil, err
} }
if !started { if !started {
logger.Info("Warning: skipping controller", "controller", controllerName) logger.Info("Warning: skipping controller", "controller", controllerName)
continue return nil, nil
} }
check := controllerhealthz.NamedPingChecker(controllerName) check := controllerhealthz.NamedPingChecker(controllerName)
if ctrl != nil { if ctrl != nil {
// check if the controller supports and requests a debugHandler // check if the controller supports and requests a debugHandler
@ -715,14 +729,9 @@ func StartControllers(ctx context.Context, controllerCtx ControllerContext, cont
} }
} }
} }
controllerChecks = append(controllerChecks, check)
logger.Info("Started controller", "controller", controllerName) logger.Info("Started controller", "controller", controllerName)
} return check, nil
healthzHandler.AddHealthChecker(controllerChecks...)
return nil
} }
// serviceAccountTokenControllerStarter is special because it must run first to set up permissions for other controllers. // serviceAccountTokenControllerStarter is special because it must run first to set up permissions for other controllers.