github.com/kubewharf/katalyst-core@v0.5.3/cmd/katalyst-controller/app/controller.go (about) 1 /* 2 Copyright 2022 The Katalyst 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 18 19 import ( 20 "context" 21 "fmt" 22 "os" 23 "time" 24 25 "k8s.io/apimachinery/pkg/util/uuid" 26 "k8s.io/apimachinery/pkg/util/wait" 27 "k8s.io/client-go/pkg/version" 28 "k8s.io/client-go/tools/leaderelection" 29 "k8s.io/client-go/tools/leaderelection/resourcelock" 30 "k8s.io/klog/v2" 31 32 katalystbase "github.com/kubewharf/katalyst-core/cmd/base" 33 "github.com/kubewharf/katalyst-core/cmd/katalyst-controller/app/options" 34 "github.com/kubewharf/katalyst-core/pkg/client" 35 "github.com/kubewharf/katalyst-core/pkg/config" 36 "github.com/kubewharf/katalyst-core/pkg/consts" 37 "github.com/kubewharf/katalyst-core/pkg/metrics" 38 "github.com/kubewharf/katalyst-core/pkg/util/process" 39 ) 40 41 func Run(opt *options.Options, genericOptions ...katalystbase.GenericOptions) error { 42 klog.Infof("Version: %+v", version.Get()) 43 44 conf, err := opt.Config() 45 if err != nil { 46 return err 47 } 48 49 clientSet, err := client.BuildGenericClient(conf.GenericConfiguration.ClientConnection, opt.MasterURL, 50 opt.KubeConfig, fmt.Sprintf("%v", consts.KatalystComponentController)) 51 if err != nil { 52 return err 53 } 54 55 // Set up signals so that we handle the first shutdown signal gracefully. 56 ctx := process.SetupSignalHandler() 57 58 controllerCtx, err := katalystbase.NewGenericContext(clientSet, conf.GenericControllerConfiguration.LabelSelector, 59 conf.GenericControllerConfiguration.DynamicGVResources, ControllersDisabledByDefault, 60 conf.GenericConfiguration, consts.KatalystComponentController, nil) 61 if err != nil { 62 return err 63 } 64 65 for _, genericOption := range genericOptions { 66 genericOption(controllerCtx) 67 } 68 69 // start controller ctx first 70 controllerCtx.Run(ctx) 71 72 startController := func(startCtx context.Context) { 73 defer func() { 74 klog.Infoln("ready to stop controller") 75 startCtx.Done() 76 }() 77 78 klog.Infoln("ready to start controller") 79 var controllers []string 80 controllers, err := startControllers(startCtx, controllerCtx, conf, GetControllerInitializers()) 81 if err != nil { 82 klog.Fatalf("error starting controllers: %v", err) 83 } 84 controllerCtx.StartInformer(startCtx) 85 86 go wait.Until(func() { 87 klog.Infof("heart beating...") 88 89 for _, name := range controllers { 90 _ = controllerCtx.EmitterPool.GetDefaultMetricsEmitter().StoreInt64("heart_beating", 1, metrics.MetricTypeNameCount, 91 metrics.MetricTag{Key: "component", Val: string(consts.KatalystComponentController)}, 92 metrics.MetricTag{Key: "controller", Val: name}, 93 ) 94 } 95 }, 30*time.Second, ctx.Done()) 96 97 <-startCtx.Done() 98 klog.Infof("controller exiting") 99 } 100 101 defer func() { 102 klog.Infoln("katalyst controller is stopped.") 103 }() 104 105 if !conf.GenericControllerConfiguration.LeaderElection.LeaderElect { 106 startController(ctx) 107 <-ctx.Done() 108 109 klog.Infof("controller cmd exiting, wait for goroutines exits.") 110 return nil 111 } 112 113 klog.Infoln("lead election is enabled") 114 id, err := os.Hostname() 115 if err != nil { 116 klog.Error("fail to get hostname") 117 return err 118 } 119 id = id + "_" + string(uuid.NewUUID()) 120 121 rl, err := resourcelock.New(conf.GenericControllerConfiguration.LeaderElection.ResourceLock, 122 conf.GenericControllerConfiguration.LeaderElection.ResourceNamespace, 123 conf.GenericControllerConfiguration.LeaderElection.ResourceName, 124 clientSet.KubeClient.CoreV1(), 125 clientSet.KubeClient.CoordinationV1(), 126 resourcelock.ResourceLockConfig{ 127 Identity: id, 128 EventRecorder: controllerCtx.BroadcastAdapter.DeprecatedNewLegacyRecorder(string(consts.KatalystComponentController)), 129 }) 130 if err != nil { 131 return err 132 } 133 134 leaderelection.RunOrDie(ctx, leaderelection.LeaderElectionConfig{ 135 Lock: rl, 136 LeaseDuration: conf.GenericControllerConfiguration.LeaderElection.LeaseDuration.Duration, 137 RenewDeadline: conf.GenericControllerConfiguration.LeaderElection.RenewDeadline.Duration, 138 RetryPeriod: conf.GenericControllerConfiguration.LeaderElection.RetryPeriod.Duration, 139 Callbacks: leaderelection.LeaderCallbacks{ 140 OnStartedLeading: startController, 141 OnStoppedLeading: func() { 142 klog.Infof("loss leader lock.") 143 }, 144 }, 145 }) 146 147 return fmt.Errorf("lost lease") 148 } 149 150 func startControllers(ctx context.Context, controllerCtx *katalystbase.GenericContext, 151 conf *config.Configuration, controllers map[string]ControllerStarter, 152 ) ([]string, error) { 153 var enabledControllers []string 154 155 for controllerName, starter := range controllers { 156 if !controllerCtx.IsEnabled(controllerName, conf.GenericControllerConfiguration.Controllers) { 157 klog.Warningf("%q is disabled", controllerName) 158 continue 159 } 160 enabledControllers = append(enabledControllers, controllerName) 161 162 klog.Infof("Starting %q", controllerName) 163 started, err := starter.Starter(ctx, controllerCtx, conf, starter.ExtraConf, controllerName) 164 if err != nil { 165 klog.Errorf("Error starting %q", controllerName) 166 return []string{}, err 167 } else if !started { 168 klog.Warningf("Skipping %q", controllerName) 169 continue 170 } 171 172 klog.Infof("Started %q", controllerName) 173 } 174 return enabledControllers, nil 175 }