您好,登錄后才能下訂單哦!
本篇內容主要講解“Kubernetes的Main函數怎么理解”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“Kubernetes的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) } }
首先調用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以后,就執行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) } }
啟動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函數怎么理解”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。