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  }