k8s.io/kubernetes@v1.31.0-alpha.0.0.20240520171757-56147500dadc/cmd/kube-controller-manager/app/controllermanager.go (about) 1 /* 2 Copyright 2014 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 // Package app implements a server that runs a set of active 18 // components. This includes replication controllers, service endpoints and 19 // nodes. 20 package app 21 22 import ( 23 "context" 24 "fmt" 25 "k8s.io/apimachinery/pkg/runtime/schema" 26 "math/rand" 27 "net/http" 28 "os" 29 "sort" 30 "time" 31 32 "github.com/spf13/cobra" 33 34 "k8s.io/apimachinery/pkg/api/meta" 35 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 36 utilruntime "k8s.io/apimachinery/pkg/util/runtime" 37 "k8s.io/apimachinery/pkg/util/sets" 38 "k8s.io/apimachinery/pkg/util/uuid" 39 "k8s.io/apimachinery/pkg/util/wait" 40 "k8s.io/apiserver/pkg/server/healthz" 41 "k8s.io/apiserver/pkg/server/mux" 42 utilfeature "k8s.io/apiserver/pkg/util/feature" 43 cacheddiscovery "k8s.io/client-go/discovery/cached/memory" 44 "k8s.io/client-go/informers" 45 v1core "k8s.io/client-go/kubernetes/typed/core/v1" 46 "k8s.io/client-go/metadata" 47 "k8s.io/client-go/metadata/metadatainformer" 48 restclient "k8s.io/client-go/rest" 49 "k8s.io/client-go/restmapper" 50 "k8s.io/client-go/tools/leaderelection" 51 "k8s.io/client-go/tools/leaderelection/resourcelock" 52 certutil "k8s.io/client-go/util/cert" 53 "k8s.io/client-go/util/keyutil" 54 cloudprovider "k8s.io/cloud-provider" 55 cliflag "k8s.io/component-base/cli/flag" 56 "k8s.io/component-base/cli/globalflag" 57 "k8s.io/component-base/configz" 58 "k8s.io/component-base/featuregate" 59 "k8s.io/component-base/logs" 60 logsapi "k8s.io/component-base/logs/api/v1" 61 metricsfeatures "k8s.io/component-base/metrics/features" 62 controllersmetrics "k8s.io/component-base/metrics/prometheus/controllers" 63 "k8s.io/component-base/metrics/prometheus/slis" 64 "k8s.io/component-base/term" 65 "k8s.io/component-base/version" 66 "k8s.io/component-base/version/verflag" 67 genericcontrollermanager "k8s.io/controller-manager/app" 68 "k8s.io/controller-manager/controller" 69 "k8s.io/controller-manager/pkg/clientbuilder" 70 controllerhealthz "k8s.io/controller-manager/pkg/healthz" 71 "k8s.io/controller-manager/pkg/informerfactory" 72 "k8s.io/controller-manager/pkg/leadermigration" 73 "k8s.io/klog/v2" 74 "k8s.io/kubernetes/cmd/kube-controller-manager/app/config" 75 "k8s.io/kubernetes/cmd/kube-controller-manager/app/options" 76 "k8s.io/kubernetes/cmd/kube-controller-manager/names" 77 kubectrlmgrconfig "k8s.io/kubernetes/pkg/controller/apis/config" 78 garbagecollector "k8s.io/kubernetes/pkg/controller/garbagecollector" 79 serviceaccountcontroller "k8s.io/kubernetes/pkg/controller/serviceaccount" 80 "k8s.io/kubernetes/pkg/serviceaccount" 81 ) 82 83 func init() { 84 utilruntime.Must(logsapi.AddFeatureGates(utilfeature.DefaultMutableFeatureGate)) 85 utilruntime.Must(metricsfeatures.AddFeatureGates(utilfeature.DefaultMutableFeatureGate)) 86 } 87 88 const ( 89 // ControllerStartJitter is the Jitter used when starting controller managers 90 ControllerStartJitter = 1.0 91 // ConfigzName is the name used for register kube-controller manager /configz, same with GroupName. 92 ConfigzName = "kubecontrollermanager.config.k8s.io" 93 ) 94 95 // ControllerLoopMode is the kube-controller-manager's mode of running controller loops that are cloud provider dependent 96 type ControllerLoopMode int 97 98 const ( 99 // IncludeCloudLoops means the kube-controller-manager include the controller loops that are cloud provider dependent 100 IncludeCloudLoops ControllerLoopMode = iota 101 // ExternalLoops means the kube-controller-manager exclude the controller loops that are cloud provider dependent 102 ExternalLoops 103 ) 104 105 // NewControllerManagerCommand creates a *cobra.Command object with default parameters 106 func NewControllerManagerCommand() *cobra.Command { 107 s, err := options.NewKubeControllerManagerOptions() 108 if err != nil { 109 klog.Background().Error(err, "Unable to initialize command options") 110 klog.FlushAndExit(klog.ExitFlushTimeout, 1) 111 } 112 113 cmd := &cobra.Command{ 114 Use: "kube-controller-manager", 115 Long: `The Kubernetes controller manager is a daemon that embeds 116 the core control loops shipped with Kubernetes. In applications of robotics and 117 automation, a control loop is a non-terminating loop that regulates the state of 118 the system. In Kubernetes, a controller is a control loop that watches the shared 119 state of the cluster through the apiserver and makes changes attempting to move the 120 current state towards the desired state. Examples of controllers that ship with 121 Kubernetes today are the replication controller, endpoints controller, namespace 122 controller, and serviceaccounts controller.`, 123 PersistentPreRunE: func(*cobra.Command, []string) error { 124 // silence client-go warnings. 125 // kube-controller-manager generically watches APIs (including deprecated ones), 126 // and CI ensures it works properly against matching kube-apiserver versions. 127 restclient.SetDefaultWarningHandler(restclient.NoWarnings{}) 128 return nil 129 }, 130 RunE: func(cmd *cobra.Command, args []string) error { 131 verflag.PrintAndExitIfRequested() 132 133 // Activate logging as soon as possible, after that 134 // show flags with the final logging configuration. 135 if err := logsapi.ValidateAndApply(s.Logs, utilfeature.DefaultFeatureGate); err != nil { 136 return err 137 } 138 cliflag.PrintFlags(cmd.Flags()) 139 140 c, err := s.Config(KnownControllers(), ControllersDisabledByDefault(), ControllerAliases()) 141 if err != nil { 142 return err 143 } 144 // add feature enablement metrics 145 utilfeature.DefaultMutableFeatureGate.AddMetrics() 146 return Run(context.Background(), c.Complete()) 147 }, 148 Args: func(cmd *cobra.Command, args []string) error { 149 for _, arg := range args { 150 if len(arg) > 0 { 151 return fmt.Errorf("%q does not take any arguments, got %q", cmd.CommandPath(), args) 152 } 153 } 154 return nil 155 }, 156 } 157 158 fs := cmd.Flags() 159 namedFlagSets := s.Flags(KnownControllers(), ControllersDisabledByDefault(), ControllerAliases()) 160 verflag.AddFlags(namedFlagSets.FlagSet("global")) 161 globalflag.AddGlobalFlags(namedFlagSets.FlagSet("global"), cmd.Name(), logs.SkipLoggingConfigurationFlags()) 162 for _, f := range namedFlagSets.FlagSets { 163 fs.AddFlagSet(f) 164 } 165 166 cols, _, _ := term.TerminalSize(cmd.OutOrStdout()) 167 cliflag.SetUsageAndHelpFunc(cmd, namedFlagSets, cols) 168 169 return cmd 170 } 171 172 // ResyncPeriod returns a function which generates a duration each time it is 173 // invoked; this is so that multiple controllers don't get into lock-step and all 174 // hammer the apiserver with list requests simultaneously. 175 func ResyncPeriod(c *config.CompletedConfig) func() time.Duration { 176 return func() time.Duration { 177 factor := rand.Float64() + 1 178 return time.Duration(float64(c.ComponentConfig.Generic.MinResyncPeriod.Nanoseconds()) * factor) 179 } 180 } 181 182 // Run runs the KubeControllerManagerOptions. 183 func Run(ctx context.Context, c *config.CompletedConfig) error { 184 logger := klog.FromContext(ctx) 185 stopCh := ctx.Done() 186 187 // To help debugging, immediately log version 188 logger.Info("Starting", "version", version.Get()) 189 190 logger.Info("Golang settings", "GOGC", os.Getenv("GOGC"), "GOMAXPROCS", os.Getenv("GOMAXPROCS"), "GOTRACEBACK", os.Getenv("GOTRACEBACK")) 191 192 // Start events processing pipeline. 193 c.EventBroadcaster.StartStructuredLogging(0) 194 c.EventBroadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: c.Client.CoreV1().Events("")}) 195 defer c.EventBroadcaster.Shutdown() 196 197 if cfgz, err := configz.New(ConfigzName); err == nil { 198 cfgz.Set(c.ComponentConfig) 199 } else { 200 logger.Error(err, "Unable to register configz") 201 } 202 203 // Setup any healthz checks we will want to use. 204 var checks []healthz.HealthChecker 205 var electionChecker *leaderelection.HealthzAdaptor 206 if c.ComponentConfig.Generic.LeaderElection.LeaderElect { 207 electionChecker = leaderelection.NewLeaderHealthzAdaptor(time.Second * 20) 208 checks = append(checks, electionChecker) 209 } 210 healthzHandler := controllerhealthz.NewMutableHealthzHandler(checks...) 211 212 // Start the controller manager HTTP server 213 // unsecuredMux is the handler for these controller *after* authn/authz filters have been applied 214 var unsecuredMux *mux.PathRecorderMux 215 if c.SecureServing != nil { 216 unsecuredMux = genericcontrollermanager.NewBaseHandler(&c.ComponentConfig.Generic.Debugging, healthzHandler) 217 slis.SLIMetricsWithReset{}.Install(unsecuredMux) 218 219 handler := genericcontrollermanager.BuildHandlerChain(unsecuredMux, &c.Authorization, &c.Authentication) 220 // TODO: handle stoppedCh and listenerStoppedCh returned by c.SecureServing.Serve 221 if _, _, err := c.SecureServing.Serve(handler, 0, stopCh); err != nil { 222 return err 223 } 224 } 225 226 clientBuilder, rootClientBuilder := createClientBuilders(logger, c) 227 228 saTokenControllerDescriptor := newServiceAccountTokenControllerDescriptor(rootClientBuilder) 229 230 run := func(ctx context.Context, controllerDescriptors map[string]*ControllerDescriptor) { 231 controllerContext, err := CreateControllerContext(ctx, c, rootClientBuilder, clientBuilder) 232 if err != nil { 233 logger.Error(err, "Error building controller context") 234 klog.FlushAndExit(klog.ExitFlushTimeout, 1) 235 } 236 237 if err := StartControllers(ctx, controllerContext, controllerDescriptors, unsecuredMux, healthzHandler); err != nil { 238 logger.Error(err, "Error starting controllers") 239 klog.FlushAndExit(klog.ExitFlushTimeout, 1) 240 } 241 242 controllerContext.InformerFactory.Start(stopCh) 243 controllerContext.ObjectOrMetadataInformerFactory.Start(stopCh) 244 close(controllerContext.InformersStarted) 245 246 <-ctx.Done() 247 } 248 249 // No leader election, run directly 250 if !c.ComponentConfig.Generic.LeaderElection.LeaderElect { 251 controllerDescriptors := NewControllerDescriptors() 252 controllerDescriptors[names.ServiceAccountTokenController] = saTokenControllerDescriptor 253 run(ctx, controllerDescriptors) 254 return nil 255 } 256 257 id, err := os.Hostname() 258 if err != nil { 259 return err 260 } 261 262 // add a uniquifier so that two processes on the same host don't accidentally both become active 263 id = id + "_" + string(uuid.NewUUID()) 264 265 // leaderMigrator will be non-nil if and only if Leader Migration is enabled. 266 var leaderMigrator *leadermigration.LeaderMigrator = nil 267 268 // If leader migration is enabled, create the LeaderMigrator and prepare for migration 269 if leadermigration.Enabled(&c.ComponentConfig.Generic) { 270 logger.Info("starting leader migration") 271 272 leaderMigrator = leadermigration.NewLeaderMigrator(&c.ComponentConfig.Generic.LeaderMigration, 273 "kube-controller-manager") 274 275 // startSATokenControllerInit is the original InitFunc. 276 startSATokenControllerInit := saTokenControllerDescriptor.GetInitFunc() 277 278 // Wrap saTokenControllerDescriptor to signal readiness for migration after starting 279 // the controller. 280 saTokenControllerDescriptor.initFunc = func(ctx context.Context, controllerContext ControllerContext, controllerName string) (controller.Interface, bool, error) { 281 defer close(leaderMigrator.MigrationReady) 282 return startSATokenControllerInit(ctx, controllerContext, controllerName) 283 } 284 } 285 286 // Start the main lock 287 go leaderElectAndRun(ctx, c, id, electionChecker, 288 c.ComponentConfig.Generic.LeaderElection.ResourceLock, 289 c.ComponentConfig.Generic.LeaderElection.ResourceName, 290 leaderelection.LeaderCallbacks{ 291 OnStartedLeading: func(ctx context.Context) { 292 controllerDescriptors := NewControllerDescriptors() 293 if leaderMigrator != nil { 294 // If leader migration is enabled, we should start only non-migrated controllers 295 // for the main lock. 296 controllerDescriptors = filteredControllerDescriptors(controllerDescriptors, leaderMigrator.FilterFunc, leadermigration.ControllerNonMigrated) 297 logger.Info("leader migration: starting main controllers.") 298 } 299 controllerDescriptors[names.ServiceAccountTokenController] = saTokenControllerDescriptor 300 run(ctx, controllerDescriptors) 301 }, 302 OnStoppedLeading: func() { 303 logger.Error(nil, "leaderelection lost") 304 klog.FlushAndExit(klog.ExitFlushTimeout, 1) 305 }, 306 }) 307 308 // If Leader Migration is enabled, proceed to attempt the migration lock. 309 if leaderMigrator != nil { 310 // Wait for Service Account Token Controller to start before acquiring the migration lock. 311 // At this point, the main lock must have already been acquired, or the KCM process already exited. 312 // We wait for the main lock before acquiring the migration lock to prevent the situation 313 // where KCM instance A holds the main lock while KCM instance B holds the migration lock. 314 <-leaderMigrator.MigrationReady 315 316 // Start the migration lock. 317 go leaderElectAndRun(ctx, c, id, electionChecker, 318 c.ComponentConfig.Generic.LeaderMigration.ResourceLock, 319 c.ComponentConfig.Generic.LeaderMigration.LeaderName, 320 leaderelection.LeaderCallbacks{ 321 OnStartedLeading: func(ctx context.Context) { 322 logger.Info("leader migration: starting migrated controllers.") 323 controllerDescriptors := NewControllerDescriptors() 324 controllerDescriptors = filteredControllerDescriptors(controllerDescriptors, leaderMigrator.FilterFunc, leadermigration.ControllerMigrated) 325 // DO NOT start saTokenController under migration lock 326 delete(controllerDescriptors, names.ServiceAccountTokenController) 327 run(ctx, controllerDescriptors) 328 }, 329 OnStoppedLeading: func() { 330 logger.Error(nil, "migration leaderelection lost") 331 klog.FlushAndExit(klog.ExitFlushTimeout, 1) 332 }, 333 }) 334 } 335 336 <-stopCh 337 return nil 338 } 339 340 // ControllerContext defines the context object for controller 341 type ControllerContext struct { 342 // ClientBuilder will provide a client for this controller to use 343 ClientBuilder clientbuilder.ControllerClientBuilder 344 345 // InformerFactory gives access to informers for the controller. 346 InformerFactory informers.SharedInformerFactory 347 348 // ObjectOrMetadataInformerFactory gives access to informers for typed resources 349 // and dynamic resources by their metadata. All generic controllers currently use 350 // object metadata - if a future controller needs access to the full object this 351 // would become GenericInformerFactory and take a dynamic client. 352 ObjectOrMetadataInformerFactory informerfactory.InformerFactory 353 354 // ComponentConfig provides access to init options for a given controller 355 ComponentConfig kubectrlmgrconfig.KubeControllerManagerConfiguration 356 357 // DeferredDiscoveryRESTMapper is a RESTMapper that will defer 358 // initialization of the RESTMapper until the first mapping is 359 // requested. 360 RESTMapper *restmapper.DeferredDiscoveryRESTMapper 361 362 // Cloud is the cloud provider interface for the controllers to use. 363 // It must be initialized and ready to use. 364 Cloud cloudprovider.Interface 365 366 // Control for which control loops to be run 367 // IncludeCloudLoops is for a kube-controller-manager running all loops 368 // ExternalLoops is for a kube-controller-manager running with a cloud-controller-manager 369 LoopMode ControllerLoopMode 370 371 // InformersStarted is closed after all of the controllers have been initialized and are running. After this point it is safe, 372 // for an individual controller to start the shared informers. Before it is closed, they should not. 373 InformersStarted chan struct{} 374 375 // ResyncPeriod generates a duration each time it is invoked; this is so that 376 // multiple controllers don't get into lock-step and all hammer the apiserver 377 // with list requests simultaneously. 378 ResyncPeriod func() time.Duration 379 380 // ControllerManagerMetrics provides a proxy to set controller manager specific metrics. 381 ControllerManagerMetrics *controllersmetrics.ControllerManagerMetrics 382 383 // GraphBuilder gives an access to dependencyGraphBuilder which keeps tracks of resources in the cluster 384 GraphBuilder *garbagecollector.GraphBuilder 385 } 386 387 // IsControllerEnabled checks if the context's controllers enabled or not 388 func (c ControllerContext) IsControllerEnabled(controllerDescriptor *ControllerDescriptor) bool { 389 controllersDisabledByDefault := sets.NewString() 390 if controllerDescriptor.IsDisabledByDefault() { 391 controllersDisabledByDefault.Insert(controllerDescriptor.Name()) 392 } 393 return genericcontrollermanager.IsControllerEnabled(controllerDescriptor.Name(), controllersDisabledByDefault, c.ComponentConfig.Generic.Controllers) 394 } 395 396 // InitFunc is used to launch a particular controller. It returns a controller 397 // that can optionally implement other interfaces so that the controller manager 398 // can support the requested features. 399 // The returned controller may be nil, which will be considered an anonymous controller 400 // that requests no additional features from the controller manager. 401 // Any error returned will cause the controller process to `Fatal` 402 // The bool indicates whether the controller was enabled. 403 type InitFunc func(ctx context.Context, controllerContext ControllerContext, controllerName string) (controller controller.Interface, enabled bool, err error) 404 405 type ControllerDescriptor struct { 406 name string 407 initFunc InitFunc 408 requiredFeatureGates []featuregate.Feature 409 aliases []string 410 isDisabledByDefault bool 411 isCloudProviderController bool 412 requiresSpecialHandling bool 413 } 414 415 func (r *ControllerDescriptor) Name() string { 416 return r.name 417 } 418 419 func (r *ControllerDescriptor) GetInitFunc() InitFunc { 420 return r.initFunc 421 } 422 423 func (r *ControllerDescriptor) GetRequiredFeatureGates() []featuregate.Feature { 424 return append([]featuregate.Feature(nil), r.requiredFeatureGates...) 425 } 426 427 // GetAliases returns aliases to ensure backwards compatibility and should never be removed! 428 // Only addition of new aliases is allowed, and only when a canonical name is changed (please see CHANGE POLICY of controller names) 429 func (r *ControllerDescriptor) GetAliases() []string { 430 return append([]string(nil), r.aliases...) 431 } 432 433 func (r *ControllerDescriptor) IsDisabledByDefault() bool { 434 return r.isDisabledByDefault 435 } 436 437 func (r *ControllerDescriptor) IsCloudProviderController() bool { 438 return r.isCloudProviderController 439 } 440 441 // RequiresSpecialHandling should return true only in a special non-generic controllers like ServiceAccountTokenController 442 func (r *ControllerDescriptor) RequiresSpecialHandling() bool { 443 return r.requiresSpecialHandling 444 } 445 446 // KnownControllers returns all known controllers's name 447 func KnownControllers() []string { 448 return sets.StringKeySet(NewControllerDescriptors()).List() 449 } 450 451 // ControllerAliases returns a mapping of aliases to canonical controller names 452 func ControllerAliases() map[string]string { 453 aliases := map[string]string{} 454 for name, c := range NewControllerDescriptors() { 455 for _, alias := range c.GetAliases() { 456 aliases[alias] = name 457 } 458 } 459 return aliases 460 } 461 462 func ControllersDisabledByDefault() []string { 463 var controllersDisabledByDefault []string 464 465 for name, c := range NewControllerDescriptors() { 466 if c.IsDisabledByDefault() { 467 controllersDisabledByDefault = append(controllersDisabledByDefault, name) 468 } 469 } 470 471 sort.Strings(controllersDisabledByDefault) 472 473 return controllersDisabledByDefault 474 } 475 476 // NewControllerDescriptors is a public map of named controller groups (you can start more than one in an init func) 477 // paired to their ControllerDescriptor wrapper object that includes InitFunc. 478 // This allows for structured downstream composition and subdivision. 479 func NewControllerDescriptors() map[string]*ControllerDescriptor { 480 controllers := map[string]*ControllerDescriptor{} 481 aliases := sets.NewString() 482 483 // All the controllers must fulfil common constraints, or else we will explode. 484 register := func(controllerDesc *ControllerDescriptor) { 485 if controllerDesc == nil { 486 panic("received nil controller for a registration") 487 } 488 name := controllerDesc.Name() 489 if len(name) == 0 { 490 panic("received controller without a name for a registration") 491 } 492 if _, found := controllers[name]; found { 493 panic(fmt.Sprintf("controller name %q was registered twice", name)) 494 } 495 if controllerDesc.GetInitFunc() == nil { 496 panic(fmt.Sprintf("controller %q does not have an init function", name)) 497 } 498 499 for _, alias := range controllerDesc.GetAliases() { 500 if aliases.Has(alias) { 501 panic(fmt.Sprintf("controller %q has a duplicate alias %q", name, alias)) 502 } 503 aliases.Insert(alias) 504 } 505 506 controllers[name] = controllerDesc 507 } 508 509 // First add "special" controllers that aren't initialized normally. These controllers cannot be initialized 510 // in the main controller loop initialization, so we add them here only for the metadata and duplication detection. 511 // app.ControllerDescriptor#RequiresSpecialHandling should return true for such controllers 512 // The only known special case is the ServiceAccountTokenController which *must* be started 513 // first to ensure that the SA tokens for future controllers will exist. Think very carefully before adding new 514 // special controllers. 515 register(newServiceAccountTokenControllerDescriptor(nil)) 516 517 register(newEndpointsControllerDescriptor()) 518 register(newEndpointSliceControllerDescriptor()) 519 register(newEndpointSliceMirroringControllerDescriptor()) 520 register(newReplicationControllerDescriptor()) 521 register(newPodGarbageCollectorControllerDescriptor()) 522 register(newResourceQuotaControllerDescriptor()) 523 register(newNamespaceControllerDescriptor()) 524 register(newServiceAccountControllerDescriptor()) 525 register(newGarbageCollectorControllerDescriptor()) 526 register(newDaemonSetControllerDescriptor()) 527 register(newJobControllerDescriptor()) 528 register(newDeploymentControllerDescriptor()) 529 register(newReplicaSetControllerDescriptor()) 530 register(newHorizontalPodAutoscalerControllerDescriptor()) 531 register(newDisruptionControllerDescriptor()) 532 register(newStatefulSetControllerDescriptor()) 533 register(newCronJobControllerDescriptor()) 534 register(newCertificateSigningRequestSigningControllerDescriptor()) 535 register(newCertificateSigningRequestApprovingControllerDescriptor()) 536 register(newCertificateSigningRequestCleanerControllerDescriptor()) 537 register(newTTLControllerDescriptor()) 538 register(newBootstrapSignerControllerDescriptor()) 539 register(newTokenCleanerControllerDescriptor()) 540 register(newNodeIpamControllerDescriptor()) 541 register(newNodeLifecycleControllerDescriptor()) 542 543 register(newServiceLBControllerDescriptor()) // cloud provider controller 544 register(newNodeRouteControllerDescriptor()) // cloud provider controller 545 register(newCloudNodeLifecycleControllerDescriptor()) // cloud provider controller 546 // TODO: persistent volume controllers into the IncludeCloudLoops only set as a cloud provider controller. 547 548 register(newPersistentVolumeBinderControllerDescriptor()) 549 register(newPersistentVolumeAttachDetachControllerDescriptor()) 550 register(newPersistentVolumeExpanderControllerDescriptor()) 551 register(newClusterRoleAggregrationControllerDescriptor()) 552 register(newPersistentVolumeClaimProtectionControllerDescriptor()) 553 register(newPersistentVolumeProtectionControllerDescriptor()) 554 register(newTTLAfterFinishedControllerDescriptor()) 555 register(newRootCACertificatePublisherControllerDescriptor()) 556 register(newEphemeralVolumeControllerDescriptor()) 557 558 // feature gated 559 register(newStorageVersionGarbageCollectorControllerDescriptor()) 560 register(newResourceClaimControllerDescriptor()) 561 register(newLegacyServiceAccountTokenCleanerControllerDescriptor()) 562 register(newValidatingAdmissionPolicyStatusControllerDescriptor()) 563 register(newTaintEvictionControllerDescriptor()) 564 register(newServiceCIDRsControllerDescriptor()) 565 register(newStorageVersionMigratorControllerDescriptor()) 566 567 for _, alias := range aliases.UnsortedList() { 568 if _, ok := controllers[alias]; ok { 569 panic(fmt.Sprintf("alias %q conflicts with a controller name", alias)) 570 } 571 } 572 573 return controllers 574 } 575 576 // CreateControllerContext creates a context struct containing references to resources needed by the 577 // controllers such as the cloud provider and clientBuilder. rootClientBuilder is only used for 578 // the shared-informers client and token controller. 579 func CreateControllerContext(ctx context.Context, s *config.CompletedConfig, rootClientBuilder, clientBuilder clientbuilder.ControllerClientBuilder) (ControllerContext, error) { 580 // Informer transform to trim ManagedFields for memory efficiency. 581 trim := func(obj interface{}) (interface{}, error) { 582 if accessor, err := meta.Accessor(obj); err == nil { 583 if accessor.GetManagedFields() != nil { 584 accessor.SetManagedFields(nil) 585 } 586 } 587 return obj, nil 588 } 589 590 versionedClient := rootClientBuilder.ClientOrDie("shared-informers") 591 sharedInformers := informers.NewSharedInformerFactoryWithOptions(versionedClient, ResyncPeriod(s)(), informers.WithTransform(trim)) 592 593 metadataClient := metadata.NewForConfigOrDie(rootClientBuilder.ConfigOrDie("metadata-informers")) 594 metadataInformers := metadatainformer.NewSharedInformerFactoryWithOptions(metadataClient, ResyncPeriod(s)(), metadatainformer.WithTransform(trim)) 595 596 // If apiserver is not running we should wait for some time and fail only then. This is particularly 597 // important when we start apiserver and controller manager at the same time. 598 if err := genericcontrollermanager.WaitForAPIServer(versionedClient, 10*time.Second); err != nil { 599 return ControllerContext{}, fmt.Errorf("failed to wait for apiserver being healthy: %v", err) 600 } 601 602 // Use a discovery client capable of being refreshed. 603 discoveryClient := rootClientBuilder.DiscoveryClientOrDie("controller-discovery") 604 cachedClient := cacheddiscovery.NewMemCacheClient(discoveryClient) 605 restMapper := restmapper.NewDeferredDiscoveryRESTMapper(cachedClient) 606 go wait.Until(func() { 607 restMapper.Reset() 608 }, 30*time.Second, ctx.Done()) 609 610 cloud, loopMode, err := createCloudProvider(klog.FromContext(ctx), s.ComponentConfig.KubeCloudShared.CloudProvider.Name, s.ComponentConfig.KubeCloudShared.ExternalCloudVolumePlugin, 611 s.ComponentConfig.KubeCloudShared.CloudProvider.CloudConfigFile, s.ComponentConfig.KubeCloudShared.AllowUntaggedCloud, sharedInformers) 612 if err != nil { 613 return ControllerContext{}, err 614 } 615 616 controllerContext := ControllerContext{ 617 ClientBuilder: clientBuilder, 618 InformerFactory: sharedInformers, 619 ObjectOrMetadataInformerFactory: informerfactory.NewInformerFactory(sharedInformers, metadataInformers), 620 ComponentConfig: s.ComponentConfig, 621 RESTMapper: restMapper, 622 Cloud: cloud, 623 LoopMode: loopMode, 624 InformersStarted: make(chan struct{}), 625 ResyncPeriod: ResyncPeriod(s), 626 ControllerManagerMetrics: controllersmetrics.NewControllerManagerMetrics("kube-controller-manager"), 627 } 628 629 if controllerContext.ComponentConfig.GarbageCollectorController.EnableGarbageCollector && 630 controllerContext.IsControllerEnabled(NewControllerDescriptors()[names.GarbageCollectorController]) { 631 ignoredResources := make(map[schema.GroupResource]struct{}) 632 for _, r := range controllerContext.ComponentConfig.GarbageCollectorController.GCIgnoredResources { 633 ignoredResources[schema.GroupResource{Group: r.Group, Resource: r.Resource}] = struct{}{} 634 } 635 636 controllerContext.GraphBuilder = garbagecollector.NewDependencyGraphBuilder( 637 ctx, 638 metadataClient, 639 controllerContext.RESTMapper, 640 ignoredResources, 641 controllerContext.ObjectOrMetadataInformerFactory, 642 controllerContext.InformersStarted, 643 ) 644 } 645 646 controllersmetrics.Register() 647 return controllerContext, nil 648 } 649 650 // StartControllers starts a set of controllers with a specified ControllerContext 651 func StartControllers(ctx context.Context, controllerCtx ControllerContext, controllerDescriptors map[string]*ControllerDescriptor, 652 unsecuredMux *mux.PathRecorderMux, healthzHandler *controllerhealthz.MutableHealthzHandler) error { 653 var controllerChecks []healthz.HealthChecker 654 655 // Always start the SA token controller first using a full-power client, since it needs to mint tokens for the rest 656 // If this fails, just return here and fail since other controllers won't be able to get credentials. 657 if serviceAccountTokenControllerDescriptor, ok := controllerDescriptors[names.ServiceAccountTokenController]; ok { 658 check, err := StartController(ctx, controllerCtx, serviceAccountTokenControllerDescriptor, unsecuredMux) 659 if err != nil { 660 return err 661 } 662 if check != nil { 663 // HealthChecker should be present when controller has started 664 controllerChecks = append(controllerChecks, check) 665 } 666 } 667 668 // Initialize the cloud provider with a reference to the clientBuilder only after token controller 669 // has started in case the cloud provider uses the client builder. 670 if controllerCtx.Cloud != nil { 671 controllerCtx.Cloud.Initialize(controllerCtx.ClientBuilder, ctx.Done()) 672 } 673 674 // Each controller is passed a context where the logger has the name of 675 // the controller set through WithName. That name then becomes the prefix of 676 // of all log messages emitted by that controller. 677 // 678 // In StartController, an explicit "controller" key is used instead, for two reasons: 679 // - while contextual logging is alpha, klog.LoggerWithName is still a no-op, 680 // so we cannot rely on it yet to add the name 681 // - it allows distinguishing between log entries emitted by the controller 682 // and those emitted for it - this is a bit debatable and could be revised. 683 for _, controllerDesc := range controllerDescriptors { 684 if controllerDesc.RequiresSpecialHandling() { 685 continue 686 } 687 688 check, err := StartController(ctx, controllerCtx, controllerDesc, unsecuredMux) 689 if err != nil { 690 return err 691 } 692 if check != nil { 693 // HealthChecker should be present when controller has started 694 controllerChecks = append(controllerChecks, check) 695 } 696 } 697 698 healthzHandler.AddHealthChecker(controllerChecks...) 699 700 return nil 701 } 702 703 // StartController starts a controller with a specified ControllerContext 704 // and performs required pre- and post- checks/actions 705 func StartController(ctx context.Context, controllerCtx ControllerContext, controllerDescriptor *ControllerDescriptor, 706 unsecuredMux *mux.PathRecorderMux) (healthz.HealthChecker, error) { 707 logger := klog.FromContext(ctx) 708 controllerName := controllerDescriptor.Name() 709 710 for _, featureGate := range controllerDescriptor.GetRequiredFeatureGates() { 711 if !utilfeature.DefaultFeatureGate.Enabled(featureGate) { 712 logger.Info("Controller is disabled by a feature gate", "controller", controllerName, "requiredFeatureGates", controllerDescriptor.GetRequiredFeatureGates()) 713 return nil, nil 714 } 715 } 716 717 if controllerDescriptor.IsCloudProviderController() && controllerCtx.LoopMode != IncludeCloudLoops { 718 logger.Info("Skipping a cloud provider controller", "controller", controllerName, "loopMode", controllerCtx.LoopMode) 719 return nil, nil 720 } 721 722 if !controllerCtx.IsControllerEnabled(controllerDescriptor) { 723 logger.Info("Warning: controller is disabled", "controller", controllerName) 724 return nil, nil 725 } 726 727 time.Sleep(wait.Jitter(controllerCtx.ComponentConfig.Generic.ControllerStartInterval.Duration, ControllerStartJitter)) 728 729 logger.V(1).Info("Starting controller", "controller", controllerName) 730 731 initFunc := controllerDescriptor.GetInitFunc() 732 ctrl, started, err := initFunc(klog.NewContext(ctx, klog.LoggerWithName(logger, controllerName)), controllerCtx, controllerName) 733 if err != nil { 734 logger.Error(err, "Error starting controller", "controller", controllerName) 735 return nil, err 736 } 737 if !started { 738 logger.Info("Warning: skipping controller", "controller", controllerName) 739 return nil, nil 740 } 741 742 check := controllerhealthz.NamedPingChecker(controllerName) 743 if ctrl != nil { 744 // check if the controller supports and requests a debugHandler 745 // and it needs the unsecuredMux to mount the handler onto. 746 if debuggable, ok := ctrl.(controller.Debuggable); ok && unsecuredMux != nil { 747 if debugHandler := debuggable.DebuggingHandler(); debugHandler != nil { 748 basePath := "/debug/controllers/" + controllerName 749 unsecuredMux.UnlistedHandle(basePath, http.StripPrefix(basePath, debugHandler)) 750 unsecuredMux.UnlistedHandlePrefix(basePath+"/", http.StripPrefix(basePath, debugHandler)) 751 } 752 } 753 if healthCheckable, ok := ctrl.(controller.HealthCheckable); ok { 754 if realCheck := healthCheckable.HealthChecker(); realCheck != nil { 755 check = controllerhealthz.NamedHealthChecker(controllerName, realCheck) 756 } 757 } 758 } 759 760 logger.Info("Started controller", "controller", controllerName) 761 return check, nil 762 } 763 764 // serviceAccountTokenControllerStarter is special because it must run first to set up permissions for other controllers. 765 // It cannot use the "normal" client builder, so it tracks its own. 766 func newServiceAccountTokenControllerDescriptor(rootClientBuilder clientbuilder.ControllerClientBuilder) *ControllerDescriptor { 767 return &ControllerDescriptor{ 768 name: names.ServiceAccountTokenController, 769 aliases: []string{"serviceaccount-token"}, 770 initFunc: func(ctx context.Context, controllerContext ControllerContext, controllerName string) (controller.Interface, bool, error) { 771 return startServiceAccountTokenController(ctx, controllerContext, controllerName, rootClientBuilder) 772 }, 773 // will make sure it runs first before other controllers 774 requiresSpecialHandling: true, 775 } 776 } 777 778 func startServiceAccountTokenController(ctx context.Context, controllerContext ControllerContext, controllerName string, rootClientBuilder clientbuilder.ControllerClientBuilder) (controller.Interface, bool, error) { 779 logger := klog.FromContext(ctx) 780 if len(controllerContext.ComponentConfig.SAController.ServiceAccountKeyFile) == 0 { 781 logger.Info("Controller is disabled because there is no private key", "controller", controllerName) 782 return nil, false, nil 783 } 784 privateKey, err := keyutil.PrivateKeyFromFile(controllerContext.ComponentConfig.SAController.ServiceAccountKeyFile) 785 if err != nil { 786 return nil, true, fmt.Errorf("error reading key for service account token controller: %v", err) 787 } 788 789 var rootCA []byte 790 if controllerContext.ComponentConfig.SAController.RootCAFile != "" { 791 if rootCA, err = readCA(controllerContext.ComponentConfig.SAController.RootCAFile); err != nil { 792 return nil, true, fmt.Errorf("error parsing root-ca-file at %s: %v", controllerContext.ComponentConfig.SAController.RootCAFile, err) 793 } 794 } else { 795 rootCA = rootClientBuilder.ConfigOrDie("tokens-controller").CAData 796 } 797 798 tokenGenerator, err := serviceaccount.JWTTokenGenerator(serviceaccount.LegacyIssuer, privateKey) 799 if err != nil { 800 return nil, false, fmt.Errorf("failed to build token generator: %v", err) 801 } 802 tokenController, err := serviceaccountcontroller.NewTokensController( 803 controllerContext.InformerFactory.Core().V1().ServiceAccounts(), 804 controllerContext.InformerFactory.Core().V1().Secrets(), 805 rootClientBuilder.ClientOrDie("tokens-controller"), 806 serviceaccountcontroller.TokensControllerOptions{ 807 TokenGenerator: tokenGenerator, 808 RootCA: rootCA, 809 }, 810 ) 811 if err != nil { 812 return nil, true, fmt.Errorf("error creating Tokens controller: %v", err) 813 } 814 go tokenController.Run(ctx, int(controllerContext.ComponentConfig.SAController.ConcurrentSATokenSyncs)) 815 816 // start the first set of informers now so that other controllers can start 817 controllerContext.InformerFactory.Start(ctx.Done()) 818 819 return nil, true, nil 820 } 821 822 func readCA(file string) ([]byte, error) { 823 rootCA, err := os.ReadFile(file) 824 if err != nil { 825 return nil, err 826 } 827 if _, err := certutil.ParseCertsPEM(rootCA); err != nil { 828 return nil, err 829 } 830 831 return rootCA, err 832 } 833 834 // createClientBuilders creates clientBuilder and rootClientBuilder from the given configuration 835 func createClientBuilders(logger klog.Logger, c *config.CompletedConfig) (clientBuilder clientbuilder.ControllerClientBuilder, rootClientBuilder clientbuilder.ControllerClientBuilder) { 836 rootClientBuilder = clientbuilder.SimpleControllerClientBuilder{ 837 ClientConfig: c.Kubeconfig, 838 } 839 if c.ComponentConfig.KubeCloudShared.UseServiceAccountCredentials { 840 if len(c.ComponentConfig.SAController.ServiceAccountKeyFile) == 0 { 841 // It's possible another controller process is creating the tokens for us. 842 // If one isn't, we'll timeout and exit when our client builder is unable to create the tokens. 843 logger.Info("Warning: --use-service-account-credentials was specified without providing a --service-account-private-key-file") 844 } 845 846 clientBuilder = clientbuilder.NewDynamicClientBuilder( 847 restclient.AnonymousClientConfig(c.Kubeconfig), 848 c.Client.CoreV1(), 849 metav1.NamespaceSystem) 850 } else { 851 clientBuilder = rootClientBuilder 852 } 853 return 854 } 855 856 // leaderElectAndRun runs the leader election, and runs the callbacks once the leader lease is acquired. 857 // TODO: extract this function into staging/controller-manager 858 func leaderElectAndRun(ctx context.Context, c *config.CompletedConfig, lockIdentity string, electionChecker *leaderelection.HealthzAdaptor, resourceLock string, leaseName string, callbacks leaderelection.LeaderCallbacks) { 859 logger := klog.FromContext(ctx) 860 rl, err := resourcelock.NewFromKubeconfig(resourceLock, 861 c.ComponentConfig.Generic.LeaderElection.ResourceNamespace, 862 leaseName, 863 resourcelock.ResourceLockConfig{ 864 Identity: lockIdentity, 865 EventRecorder: c.EventRecorder, 866 }, 867 c.Kubeconfig, 868 c.ComponentConfig.Generic.LeaderElection.RenewDeadline.Duration) 869 if err != nil { 870 logger.Error(err, "Error creating lock") 871 klog.FlushAndExit(klog.ExitFlushTimeout, 1) 872 } 873 874 leaderelection.RunOrDie(ctx, leaderelection.LeaderElectionConfig{ 875 Lock: rl, 876 LeaseDuration: c.ComponentConfig.Generic.LeaderElection.LeaseDuration.Duration, 877 RenewDeadline: c.ComponentConfig.Generic.LeaderElection.RenewDeadline.Duration, 878 RetryPeriod: c.ComponentConfig.Generic.LeaderElection.RetryPeriod.Duration, 879 Callbacks: callbacks, 880 WatchDog: electionChecker, 881 Name: leaseName, 882 }) 883 884 panic("unreachable") 885 } 886 887 // filteredControllerDescriptors returns all controllerDescriptors after filtering through filterFunc. 888 func filteredControllerDescriptors(controllerDescriptors map[string]*ControllerDescriptor, filterFunc leadermigration.FilterFunc, expected leadermigration.FilterResult) map[string]*ControllerDescriptor { 889 resultControllers := make(map[string]*ControllerDescriptor) 890 for name, controllerDesc := range controllerDescriptors { 891 if filterFunc(name) == expected { 892 resultControllers[name] = controllerDesc 893 } 894 } 895 return resultControllers 896 }