mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-13 22:05:59 +00:00
include ServiceAccountTokenController in the NewControllerDescriptors to make it more generic
- pass a map of controllerDescriptors instead of a function
This commit is contained in:
parent
27a77e0ef3
commit
a85779b4df
@ -226,14 +226,14 @@ func Run(ctx context.Context, c *config.CompletedConfig) error {
|
|||||||
|
|
||||||
saTokenControllerDescriptor := newServiceAccountTokenControllerDescriptor(rootClientBuilder)
|
saTokenControllerDescriptor := newServiceAccountTokenControllerDescriptor(rootClientBuilder)
|
||||||
|
|
||||||
run := func(ctx context.Context, startSATokenControllerDescriptor *ControllerDescriptor, controllerDescriptorsFunc ControllerDescriptorsFunc) {
|
run := func(ctx context.Context, controllerDescriptors map[string]*ControllerDescriptor) {
|
||||||
controllerContext, err := CreateControllerContext(logger, c, rootClientBuilder, clientBuilder, ctx.Done())
|
controllerContext, err := CreateControllerContext(logger, c, rootClientBuilder, clientBuilder, ctx.Done())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error(err, "Error building controller context")
|
logger.Error(err, "Error building controller context")
|
||||||
klog.FlushAndExit(klog.ExitFlushTimeout, 1)
|
klog.FlushAndExit(klog.ExitFlushTimeout, 1)
|
||||||
}
|
}
|
||||||
controllerDescriptors := controllerDescriptorsFunc()
|
|
||||||
if err := StartControllers(ctx, controllerContext, startSATokenControllerDescriptor, controllerDescriptors, unsecuredMux, healthzHandler); err != nil {
|
if err := StartControllers(ctx, controllerContext, controllerDescriptors, unsecuredMux, healthzHandler); err != nil {
|
||||||
logger.Error(err, "Error starting controllers")
|
logger.Error(err, "Error starting controllers")
|
||||||
klog.FlushAndExit(klog.ExitFlushTimeout, 1)
|
klog.FlushAndExit(klog.ExitFlushTimeout, 1)
|
||||||
}
|
}
|
||||||
@ -247,7 +247,9 @@ func Run(ctx context.Context, c *config.CompletedConfig) error {
|
|||||||
|
|
||||||
// No leader election, run directly
|
// No leader election, run directly
|
||||||
if !c.ComponentConfig.Generic.LeaderElection.LeaderElect {
|
if !c.ComponentConfig.Generic.LeaderElection.LeaderElect {
|
||||||
run(ctx, saTokenControllerDescriptor, NewControllerDescriptors)
|
controllerDescriptors := NewControllerDescriptors()
|
||||||
|
controllerDescriptors[names.ServiceAccountTokenController] = saTokenControllerDescriptor
|
||||||
|
run(ctx, controllerDescriptors)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -286,14 +288,15 @@ func Run(ctx context.Context, c *config.CompletedConfig) error {
|
|||||||
c.ComponentConfig.Generic.LeaderElection.ResourceName,
|
c.ComponentConfig.Generic.LeaderElection.ResourceName,
|
||||||
leaderelection.LeaderCallbacks{
|
leaderelection.LeaderCallbacks{
|
||||||
OnStartedLeading: func(ctx context.Context) {
|
OnStartedLeading: func(ctx context.Context) {
|
||||||
initializersFunc := NewControllerDescriptors
|
controllerDescriptors := NewControllerDescriptors()
|
||||||
if leaderMigrator != nil {
|
if leaderMigrator != nil {
|
||||||
// If leader migration is enabled, we should start only non-migrated controllers
|
// If leader migration is enabled, we should start only non-migrated controllers
|
||||||
// for the main lock.
|
// for the main lock.
|
||||||
initializersFunc = createFilteredControllerDescriptorsFunc(leaderMigrator.FilterFunc, leadermigration.ControllerNonMigrated)
|
controllerDescriptors = filteredControllerDescriptors(controllerDescriptors, leaderMigrator.FilterFunc, leadermigration.ControllerNonMigrated)
|
||||||
logger.Info("leader migration: starting main controllers.")
|
logger.Info("leader migration: starting main controllers.")
|
||||||
}
|
}
|
||||||
run(ctx, saTokenControllerDescriptor, initializersFunc)
|
controllerDescriptors[names.ServiceAccountTokenController] = saTokenControllerDescriptor
|
||||||
|
run(ctx, controllerDescriptors)
|
||||||
},
|
},
|
||||||
OnStoppedLeading: func() {
|
OnStoppedLeading: func() {
|
||||||
logger.Error(nil, "leaderelection lost")
|
logger.Error(nil, "leaderelection lost")
|
||||||
@ -316,8 +319,11 @@ func Run(ctx context.Context, c *config.CompletedConfig) error {
|
|||||||
leaderelection.LeaderCallbacks{
|
leaderelection.LeaderCallbacks{
|
||||||
OnStartedLeading: func(ctx context.Context) {
|
OnStartedLeading: func(ctx context.Context) {
|
||||||
logger.Info("leader migration: starting migrated controllers.")
|
logger.Info("leader migration: starting migrated controllers.")
|
||||||
|
controllerDescriptors := NewControllerDescriptors()
|
||||||
|
controllerDescriptors = filteredControllerDescriptors(controllerDescriptors, leaderMigrator.FilterFunc, leadermigration.ControllerMigrated)
|
||||||
// DO NOT start saTokenController under migration lock
|
// DO NOT start saTokenController under migration lock
|
||||||
run(ctx, nil, createFilteredControllerDescriptorsFunc(leaderMigrator.FilterFunc, leadermigration.ControllerMigrated))
|
delete(controllerDescriptors, names.ServiceAccountTokenController)
|
||||||
|
run(ctx, controllerDescriptors)
|
||||||
},
|
},
|
||||||
OnStoppedLeading: func() {
|
OnStoppedLeading: func() {
|
||||||
logger.Error(nil, "migration leaderelection lost")
|
logger.Error(nil, "migration leaderelection lost")
|
||||||
@ -398,6 +404,7 @@ type ControllerDescriptor struct {
|
|||||||
requiredFeatureGates []featuregate.Feature
|
requiredFeatureGates []featuregate.Feature
|
||||||
isDisabledByDefault bool
|
isDisabledByDefault bool
|
||||||
isCloudProviderController bool
|
isCloudProviderController bool
|
||||||
|
requiresSpecialHandling bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ControllerDescriptor) Name() string {
|
func (r *ControllerDescriptor) Name() string {
|
||||||
@ -420,25 +427,14 @@ func (r *ControllerDescriptor) IsCloudProviderController() bool {
|
|||||||
return r.isCloudProviderController
|
return r.isCloudProviderController
|
||||||
}
|
}
|
||||||
|
|
||||||
// ControllerDescriptorsFunc is used to create a collection of controller descriptors
|
// RequiresSpecialHandling should return true only in a special non-generic controllers like ServiceAccountTokenController
|
||||||
// given the loopMode.
|
func (r *ControllerDescriptor) RequiresSpecialHandling() bool {
|
||||||
type ControllerDescriptorsFunc func() (initializers map[string]*ControllerDescriptor)
|
return r.requiresSpecialHandling
|
||||||
|
}
|
||||||
var _ ControllerDescriptorsFunc = NewControllerDescriptors
|
|
||||||
|
|
||||||
// KnownControllers returns all known controllers's name
|
// KnownControllers returns all known controllers's name
|
||||||
func KnownControllers() []string {
|
func KnownControllers() []string {
|
||||||
ret := sets.StringKeySet(NewControllerDescriptors())
|
return sets.StringKeySet(NewControllerDescriptors()).List()
|
||||||
|
|
||||||
// add "special" controllers that aren't initialized normally. These controllers cannot be initialized
|
|
||||||
// using a normal function. The only known special case is the SA token controller which *must* be started
|
|
||||||
// first to ensure that the SA tokens for future controllers will exist. Think very carefully before adding
|
|
||||||
// to this list.
|
|
||||||
ret.Insert(
|
|
||||||
newServiceAccountTokenControllerDescriptor(nil).Name(),
|
|
||||||
)
|
|
||||||
|
|
||||||
return ret.List()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func ControllersDisabledByDefault() []string {
|
func ControllersDisabledByDefault() []string {
|
||||||
@ -479,6 +475,14 @@ func NewControllerDescriptors() map[string]*ControllerDescriptor {
|
|||||||
controllers[name] = controllerDesc
|
controllers[name] = controllerDesc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// First add "special" controllers that aren't initialized normally. These controllers cannot be initialized
|
||||||
|
// in the main controller loop initialization, so we add them here only for the metadata and duplication detection.
|
||||||
|
// app.ControllerDescriptor#RequiresSpecialHandling should return true for such controllers
|
||||||
|
// The only known special case is the ServiceAccountTokenController which *must* be started
|
||||||
|
// first to ensure that the SA tokens for future controllers will exist. Think very carefully before adding new
|
||||||
|
// special controllers.
|
||||||
|
register(newServiceAccountTokenControllerDescriptor(nil))
|
||||||
|
|
||||||
register(newEndpointsControllerDescriptor())
|
register(newEndpointsControllerDescriptor())
|
||||||
register(newEndpointSliceControllerDescriptor())
|
register(newEndpointSliceControllerDescriptor())
|
||||||
register(newEndpointSliceMirroringControllerDescriptor())
|
register(newEndpointSliceMirroringControllerDescriptor())
|
||||||
@ -584,18 +588,20 @@ 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, startSATokenControllerDescriptor *ControllerDescriptor, 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)
|
logger := klog.FromContext(ctx)
|
||||||
|
|
||||||
// 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 startSATokenControllerDescriptor != nil {
|
if serviceAccountTokenControllerDescriptor, ok := controllerDescriptors[names.ServiceAccountTokenController]; ok {
|
||||||
if !controllerCtx.IsControllerEnabled(startSATokenControllerDescriptor) {
|
controllerName := serviceAccountTokenControllerDescriptor.Name()
|
||||||
logger.Info("Warning: controller is disabled", "controller", startSATokenControllerDescriptor.Name())
|
if !controllerCtx.IsControllerEnabled(serviceAccountTokenControllerDescriptor) {
|
||||||
|
logger.Info("Warning: controller is disabled", "controller", controllerName)
|
||||||
} else {
|
} else {
|
||||||
initFunc := startSATokenControllerDescriptor.GetInitFunc()
|
logger.V(1).Info("Starting controller", "controller", controllerName)
|
||||||
if _, _, err := initFunc(ctx, controllerCtx, startSATokenControllerDescriptor.Name()); err != nil {
|
initFunc := serviceAccountTokenControllerDescriptor.GetInitFunc()
|
||||||
|
if _, _, err := initFunc(klog.NewContext(ctx, klog.LoggerWithName(logger, controllerName)), controllerCtx, controllerName); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -619,6 +625,10 @@ func StartControllers(ctx context.Context, controllerCtx ControllerContext, star
|
|||||||
// - 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 controllerName, controllerDesc := range controllerDescriptors {
|
||||||
|
if controllerDesc.RequiresSpecialHandling() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
disabledByFeatureGate := false
|
disabledByFeatureGate := false
|
||||||
for _, featureGate := range controllerDesc.GetRequiredFeatureGates() {
|
for _, featureGate := range controllerDesc.GetRequiredFeatureGates() {
|
||||||
if !utilfeature.DefaultFeatureGate.Enabled(featureGate) {
|
if !utilfeature.DefaultFeatureGate.Enabled(featureGate) {
|
||||||
@ -683,14 +693,15 @@ func StartControllers(ctx context.Context, controllerCtx ControllerContext, star
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 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.
|
||||||
// It cannot use the "normal" client builder, so it tracks its own. It must also avoid being included in the "normal"
|
// It cannot use the "normal" client builder, so it tracks its own.
|
||||||
// ControllerDescriptor map so that it can always run first.
|
|
||||||
func newServiceAccountTokenControllerDescriptor(rootClientBuilder clientbuilder.ControllerClientBuilder) *ControllerDescriptor {
|
func newServiceAccountTokenControllerDescriptor(rootClientBuilder clientbuilder.ControllerClientBuilder) *ControllerDescriptor {
|
||||||
return &ControllerDescriptor{
|
return &ControllerDescriptor{
|
||||||
name: names.ServiceAccountTokenController,
|
name: names.ServiceAccountTokenController,
|
||||||
initFunc: func(ctx context.Context, controllerContext ControllerContext, controllerName string) (controller.Interface, bool, error) {
|
initFunc: func(ctx context.Context, controllerContext ControllerContext, controllerName string) (controller.Interface, bool, error) {
|
||||||
return startServiceAccountTokenController(ctx, controllerContext, controllerName, rootClientBuilder)
|
return startServiceAccountTokenController(ctx, controllerContext, controllerName, rootClientBuilder)
|
||||||
},
|
},
|
||||||
|
// will make sure it runs first before other controllers
|
||||||
|
requiresSpecialHandling: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -803,16 +814,13 @@ func leaderElectAndRun(ctx context.Context, c *config.CompletedConfig, lockIdent
|
|||||||
panic("unreachable")
|
panic("unreachable")
|
||||||
}
|
}
|
||||||
|
|
||||||
// createFilteredControllerDescriptorsFunc creates a controllerDescriptorsFunc that returns all controllerDescriptors
|
// filteredControllerDescriptors returns all controllerDescriptors after filtering through filterFunc.
|
||||||
// with expected as the result after filtering through filterFunc.
|
func filteredControllerDescriptors(controllerDescriptors map[string]*ControllerDescriptor, filterFunc leadermigration.FilterFunc, expected leadermigration.FilterResult) map[string]*ControllerDescriptor {
|
||||||
func createFilteredControllerDescriptorsFunc(filterFunc leadermigration.FilterFunc, expected leadermigration.FilterResult) ControllerDescriptorsFunc {
|
resultControllers := make(map[string]*ControllerDescriptor)
|
||||||
return func() map[string]*ControllerDescriptor {
|
for name, controllerDesc := range controllerDescriptors {
|
||||||
controllerDescriptors := make(map[string]*ControllerDescriptor)
|
|
||||||
for name, controllerDesc := range NewControllerDescriptors() {
|
|
||||||
if filterFunc(name) == expected {
|
if filterFunc(name) == expected {
|
||||||
controllerDescriptors[name] = controllerDesc
|
resultControllers[name] = controllerDesc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return controllerDescriptors
|
return resultControllers
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user