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
func StartControllers(ctx context.Context, controllerCtx ControllerContext, controllerDescriptors map[string]*ControllerDescriptor,
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
// 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 {
controllerName := serviceAccountTokenControllerDescriptor.Name()
if !controllerCtx.IsControllerEnabled(serviceAccountTokenControllerDescriptor) {
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 {
check, err := StartController(ctx, controllerCtx, serviceAccountTokenControllerDescriptor, unsecuredMux)
if err != nil {
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())
}
var controllerChecks []healthz.HealthChecker
// 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
// 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,
// so we cannot rely on it yet to add the name
// - it allows distinguishing between log entries emitted by the controller
// 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() {
continue
}
disabledByFeatureGate := false
for _, featureGate := range controllerDesc.GetRequiredFeatureGates() {
check, err := StartController(ctx, controllerCtx, controllerDesc, unsecuredMux)
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) {
disabledByFeatureGate = true
break
logger.Info("Controller is disabled by a feature gate", "controller", controllerName, "requiredFeatureGates", controllerDescriptor.GetRequiredFeatureGates())
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)
continue
return nil, nil
}
if !controllerCtx.IsControllerEnabled(controllerDesc) {
if !controllerCtx.IsControllerEnabled(controllerDescriptor) {
logger.Info("Warning: controller is disabled", "controller", controllerName)
continue
return nil, nil
}
time.Sleep(wait.Jitter(controllerCtx.ComponentConfig.Generic.ControllerStartInterval.Duration, ControllerStartJitter))
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)
if err != nil {
logger.Error(err, "Error starting controller", "controller", controllerName)
return err
return nil, err
}
if !started {
logger.Info("Warning: skipping controller", "controller", controllerName)
continue
return nil, nil
}
check := controllerhealthz.NamedPingChecker(controllerName)
if ctrl != nil {
// 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)
}
healthzHandler.AddHealthChecker(controllerChecks...)
return nil
return check, nil
}
// serviceAccountTokenControllerStarter is special because it must run first to set up permissions for other controllers.