Kubernetes的Main函数怎么理解
更新:HHH   时间:2023-1-7


本篇内容主要讲解“Kubernetes的Main函数怎么理解”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Kubernetes的Main函数怎么理解”吧!

Main函数:

读过Kubernetes的源码就会发现,Kubernetes使用的是corba框架,所以各个组件的Main函数都大同小异,如下是kube-controller-manager的main函数,

k8s.io/kubernetes/cmd/kube-controller-manager/controller-manager.go

func main() {
   rand.Seed(time.Now().UTC().UnixNano())

   command := app.NewControllerManagerCommand()  //生成corba格式的Command,添加flag及初始化Command的各个函数

   // TODO: once we switch everything over to Cobra commands, we can go back to calling
   // utilflag.InitFlags() (by removing its pflag.Parse() call). For now, we have to set the
   // normalize func and add the go flag set by hand.
   pflag.CommandLine.SetNormalizeFunc(utilflag.WordSepNormalizeFunc)
   pflag.CommandLine.AddGoFlagSet(goflag.CommandLine)
   // utilflag.InitFlags()
   logs.InitLogs()
   defer logs.FlushLogs()

   if err := command.Execute(); err != nil {  //执行Command  fmt.Fprintf(os.Stderr, "%v\n", err)
      os.Exit(1)
   }
}

NewControllerManagerCommand函数:

  • 首先调用options包的NewKubeControllerManagerOptions函数生成KubeControllerManagerOptions,其中给部分参数赋默认值,参数的默认值可查看代码包:k8s.io/kubernetes/pkg/controller/apis/config/v1alpha1/defaults.go以及NewKubeControllerManagerOptions函数最后10行左右的代码。

  • 生成Kube-controller-manager的Command

  • 生成controller-manager各个controller的参数,并将它们添加到kube-controller-manager的Command的Flag中,controller的参数可查看k8s.io/kubernetes/cmd/kube-controller-manager/app/options库和k8s.io/kubernetes/cmd/controller-manager/app/options库中各个controller包中的AddFlags函数

  • 设置Kube-controller-manager的usage和help函数

k8s.io/kubernetes/cmd/kube-controller-manager/app/controllermanager.go:77func NewControllerManagerCommand() *cobra.Command {
   s, err := options.NewKubeControllerManagerOptions()  //生成KubeControllerManagerOptions结构体
   if err != nil {
      glog.Fatalf("unable to initialize command options: %v", err)
   }

   cmd := &cobra.Command{  //生成kube-controller-manager的Command  Use: "kube-controller-manager",
      Long: `The Kubernetes controller manager is a daemon that embeds
the core control loops shipped with Kubernetes. In applications of robotics and
automation, a control loop is a non-terminating loop that regulates the state of
the system. In Kubernetes, a controller is a control loop that watches the shared
state of the cluster through the apiserver and makes changes attempting to move the
current state towards the desired state. Examples of controllers that ship with
Kubernetes today are the replication controller, endpoints controller, namespace
controller, and serviceaccounts controller.`,
      Run: func(cmd *cobra.Command, args []string) {
         verflag.PrintAndExitIfRequested()
         utilflag.PrintFlags(cmd.Flags())

         c, err := s.Config(KnownControllers(), ControllersDisabledByDefault.List())
         if err != nil {
            fmt.Fprintf(os.Stderr, "%v\n", err)
            os.Exit(1)
         }

         if err := Run(c.Complete(), wait.NeverStop); err != nil {
            fmt.Fprintf(os.Stderr, "%v\n", err)
            os.Exit(1)
         }
      },
   }

   fs := cmd.Flags()
   namedFlagSets := s.Flags(KnownControllers(), ControllersDisabledByDefault.List()) //生成controller-manager各个controller的参数
   for _, f := range namedFlagSets.FlagSets {  //将各个controller的参数添加到Command的flag中  fs.AddFlagSet(f)
   }
   usageFmt := "Usage:\n  %s\n"
   cols, _, _ := apiserverflag.TerminalSize(cmd.OutOrStdout())
   cmd.SetUsageFunc(func(cmd *cobra.Command) error {   //设置Kube-controller-manager的Usage函数  fmt.Fprintf(cmd.OutOrStderr(), usageFmt, cmd.UseLine())
      apiserverflag.PrintSections(cmd.OutOrStderr(), namedFlagSets, cols)
      return nil
   })
   cmd.SetHelpFunc(func(cmd *cobra.Command, args []string) {  //设置Kube-controller-manager的help函数  fmt.Fprintf(cmd.OutOrStdout(), "%s\n\n"+usageFmt, cmd.Long, cmd.UseLine())
      apiserverflag.PrintSections(cmd.OutOrStdout(), namedFlagSets, cols)
   })

   return cmd
}

command.Execute,即command.Run函数

生成command以后,就执行command.Execute函数,即执行上一步NewKubeControllerManagerOptions函数中给command定义的Run函数。注:corba的command.Execute方法是有很多检查的,会有parent command及command本身也会有很多函数(i.e PreRun,PostRun),有兴趣的可以阅读github.com/spf13/cobra项目,因为kube-controller-manager只定义了Run函数,所以这里就直接看Run函数。

  • 检查是否带了--version参数,如果有,则打印Kubernetes的version并退出kube-controller-manager程序

  • 将所有的参数及参数的value打印到日志

  • option的Config方法对所有的controller做validation,并根据options的Master,Kubeconfig,ContentType,Qps,Burst参数生成controller manager config objective

  • 执行本包中的Run函数

k8s.io/kubernetes/cmd/kube-controller-manager/app/controllermanager.go:93Run: func(cmd *cobra.Command, args []string) {
   verflag.PrintAndExitIfRequested()  //检查是否带了--version参数,如果有,则打印Kubernetes的version并退出程序
   utilflag.PrintFlags(cmd.Flags())   //将所有的参数及参数的value打印到日志   //Config方法对所有的controller做validation,并根据options的Master,Kubeconfig,ContentType,Qps,Burst参数生成controller manager config objective
   c, err := s.Config(KnownControllers(), ControllersDisabledByDefault.List())
   if err != nil {
      fmt.Fprintf(os.Stderr, "%v\n", err)
      os.Exit(1)
   }

   if err := Run(c.Complete(), wait.NeverStop); err != nil { //执行本包中的Run函数  fmt.Fprintf(os.Stderr, "%v\n", err)
      os.Exit(1)
   }
}

controllermanager.go包的Run函数

  • 启动http服务,听health接口,以及给prometheus提供metrics接口

  • 定义run函数,主要是定义client,以及启动所有的controller,controller的启动函数都在k8s.io/kubernetes/cmd/kube-controller-manager/app/core.go中

  • 如果没有启用leader-elect,则直接执行上面的run函数

  • 如果启用了leader-elect,在选举以后,再执行上面看的run函数

k8s.io/kubernetes/cmd/kube-controller-manager/app/controllermanager.go:141func Run(c *config.CompletedConfig, stopCh <-chan struct{}) error {
   // To help debugging, immediately log version
   glog.Infof("Version: %+v", version.Get())

   if cfgz, err := configz.New("componentconfig"); err == nil {
      cfgz.Set(c.ComponentConfig)
   } else {
      glog.Errorf("unable to register configz: %c", err)
   }

   // 启动http服务,提供health接口,以及给prometheus提供metrics接口
   // Start the controller manager HTTP server
   // unsecuredMux is the handler for these controller *after* authn/authz filters have been applied
   var unsecuredMux *mux.PathRecorderMux
   if c.SecureServing != nil {
      unsecuredMux = genericcontrollermanager.NewBaseHandler(&c.ComponentConfig.Generic.Debugging)
      handler := genericcontrollermanager.BuildHandlerChain(unsecuredMux, &c.Authorization, &c.Authentication)
      if err := c.SecureServing.Serve(handler, 0, stopCh); err != nil {
         return err
      }
   }
   if c.InsecureServing != nil {
      unsecuredMux = genericcontrollermanager.NewBaseHandler(&c.ComponentConfig.Generic.Debugging)
      insecureSuperuserAuthn := server.AuthenticationInfo{Authenticator: &server.InsecureSuperuser{}}
      handler := genericcontrollermanager.BuildHandlerChain(unsecuredMux, nil, &insecureSuperuserAuthn)
      if err := c.InsecureServing.Serve(handler, 0, stopCh); err != nil {
         return err
      }
   }

   //定义run函数
   run := func(ctx context.Context) {
      rootClientBuilder := controller.SimpleControllerClientBuilder{  //定义rootrootClientBuilder ClientConfig: c.Kubeconfig,
      }
      var clientBuilder controller.ControllerClientBuilder
      //如果设置了UseServiceAccountCredentials,设clientBuilder为SAControllerClientBuilder(带授权),否则为普通的rootClientBuilder  if c.ComponentConfig.KubeCloudShared.UseServiceAccountCredentials { 
         if len(c.ComponentConfig.SAController.ServiceAccountKeyFile) == 0 {
            // It'c possible another controller process is creating the tokens for us.
            // If one isn't, we'll timeout and exit when our client builder is unable to create the tokens.
            glog.Warningf("--use-service-account-credentials was specified without providing a --service-account-private-key-file")
         }
         clientBuilder = controller.SAControllerClientBuilder{ 
            ClientConfig:         restclient.AnonymousClientConfig(c.Kubeconfig),
            CoreClient:           c.Client.CoreV1(),
            AuthenticationClient: c.Client.AuthenticationV1(),
            Namespace:            "kube-system",
         }
      } else {
         clientBuilder = rootClientBuilder
      }
      controllerContext, err := CreateControllerContext(c, rootClientBuilder, clientBuilder, ctx.Done())
      if err != nil {
         glog.Fatalf("error building controller context: %v", err)
      }
      //定义saTokenControllerInitFunc  saTokenControllerInitFunc := serviceAccountTokenControllerStarter{rootClientBuilder: rootClientBuilder}.startServiceAccountTokenController

      //启动所有的controller,NewControllerInitializers函数中有所有的controller  if err := StartControllers(controllerContext, saTokenControllerInitFunc, NewControllerInitializers(controllerContext.LoopMode), unsecuredMux); err != nil {
         glog.Fatalf("error starting controllers: %v", err)
      }

      controllerContext.InformerFactory.Start(controllerContext.Stop)
      close(controllerContext.InformersStarted)

      select {}
   }

   if !c.ComponentConfig.Generic.LeaderElection.LeaderElect { //如果没有启用leader-elect,则直接执行上面的run函数  run(context.TODO())
      panic("unreachable")
   }

   id, err := os.Hostname()
   if err != nil {
      return err
   }

   //如果启用了leader-elect,在选举以后,再执行上面看的run函数
   // add a uniquifier so that two processes on the same host don't accidentally both become active
   id = id + "_" + string(uuid.NewUUID())
   rl, err := resourcelock.New(c.ComponentConfig.Generic.LeaderElection.ResourceLock,
      "kube-system",
      "kube-controller-manager",
      c.LeaderElectionClient.CoreV1(),
      resourcelock.ResourceLockConfig{
         Identity:      id,
         EventRecorder: c.EventRecorder,
      })
   if err != nil {
      glog.Fatalf("error creating lock: %v", err)
   }

   leaderelection.RunOrDie(context.TODO(), leaderelection.LeaderElectionConfig{
      Lock:          rl,
      LeaseDuration: c.ComponentConfig.Generic.LeaderElection.LeaseDuration.Duration,
      RenewDeadline: c.ComponentConfig.Generic.LeaderElection.RenewDeadline.Duration,
      RetryPeriod:   c.ComponentConfig.Generic.LeaderElection.RetryPeriod.Duration,
      Callbacks: leaderelection.LeaderCallbacks{
         OnStartedLeading: run,
         OnStoppedLeading: func() {
            glog.Fatalf("leaderelection lost")
         },
      },
   })
   panic("unreachable")
}

到此,相信大家对“Kubernetes的Main函数怎么理解”有了更深的了解,不妨来实际操作一番吧!这里是天达云网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

返回云计算教程...