Kubernetes的Main函数怎么理解

69次阅读
没有评论

共计 9278 个字符,预计需要花费 24 分钟才能阅读完成。

本篇内容主要讲解“Kubernetes 的 Main 函数怎么理解”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让丸趣 TV 小编来带大家学习“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 函数怎么理解”有了更深的了解,不妨来实际操作一番吧!这里是丸趣 TV 网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

正文完
 
丸趣
版权声明:本站原创文章,由 丸趣 2023-08-16发表,共计9278字。
转载说明:除特殊说明外本站除技术相关以外文章皆由网络搜集发布,转载请注明出处。
评论(没有评论)