// NewKubeletCommand creates a *cobra.Command object with default parametersfuncNewKubeletCommand(stopCh <-chanstruct{}) *cobra.Command {... cmd :=&cobra.Command{ Use: componentKubelet, Long: `...`,// The Kubelet has special flag parsing requirements to enforce flag precedence rules,// so we do all our parsing manually in Run, below.// DisableFlagParsing=true provides the full set of flags passed to the kubelet in the// `args` arg to Run, without Cobra's interference. DisableFlagParsing: true, Run: func(cmd *cobra.Command, args []string) {...// run the kubelet glog.V(5).Infof("KubeletConfiguration: %#v", kubeletServer.KubeletConfiguration)if err :=Run(kubeletServer, kubeletDeps, stopCh); err !=nil { glog.Fatal(err) } }, }...return cmd}
// initial flag parse, since we disable cobra's flag parsingif err := cleanFlagSet.Parse(args); err !=nil { cmd.Usage() glog.Fatal(err)}// check if there are non-flag arguments in the command linecmds := cleanFlagSet.Args()iflen(cmds) >0 { cmd.Usage() glog.Fatalf("unknown command: %s", cmds[0])}
遇到help和version参数则打印相关内容并退出。
// short-circuit on helphelp, err := cleanFlagSet.GetBool("help")if err !=nil { glog.Fatal(`"help" flag is non-bool, programmer error, please correct`)}if help { cmd.Help()return}// short-circuit on verflagverflag.PrintAndExitIfRequested()utilflag.PrintFlags(cleanFlagSet)
// set feature gates from initial flags-based configif err := utilfeature.DefaultFeatureGate.SetFromMap(kubeletConfig.FeatureGates); err !=nil { glog.Fatal(err)}// validate the initial KubeletFlagsif err := options.ValidateKubeletFlags(kubeletFlags); err !=nil { glog.Fatal(err)}if kubeletFlags.ContainerRuntime =="remote"&& cleanFlagSet.Changed("pod-infra-container-image") { glog.Warning("Warning: For remote container runtime, --pod-infra-container-image is ignored in kubelet, which should be set in that remote runtime instead")}// load kubelet config file, if providedif configFile := kubeletFlags.KubeletConfigFile; len(configFile) >0 { kubeletConfig, err =loadConfigFile(configFile)if err !=nil { glog.Fatal(err) }// We must enforce flag precedence by re-parsing the command line into the new object.// This is necessary to preserve backwards-compatibility across binary upgrades.// See issue #56171 for more details.if err :=kubeletConfigFlagPrecedence(kubeletConfig, args); err !=nil { glog.Fatal(err) }// update feature gates based on new configif err := utilfeature.DefaultFeatureGate.SetFromMap(kubeletConfig.FeatureGates); err !=nil { glog.Fatal(err) }}// We always validate the local configuration (command line + config file).// This is the default "last-known-good" config for dynamic config, and must always remain valid.if err := kubeletconfigvalidation.ValidateKubeletConfiguration(kubeletConfig); err !=nil { glog.Fatal(err)}
2.1.4. dynamic kubelet config
如果开启使用动态kubelet的配置,则由动态配置文件替换kubelet配置文件。
// use dynamic kubelet config, if enabledvar kubeletConfigController *dynamickubeletconfig.Controllerif dynamicConfigDir := kubeletFlags.DynamicConfigDir.Value(); len(dynamicConfigDir) >0 {var dynamicKubeletConfig *kubeletconfiginternal.KubeletConfiguration dynamicKubeletConfig, kubeletConfigController, err =BootstrapKubeletConfigController(dynamicConfigDir,func(kc *kubeletconfiginternal.KubeletConfiguration) error {// Here, we enforce flag precedence inside the controller, prior to the controller's validation sequence,// so that we get a complete validation at the same point where we can decide to reject dynamic config.// This fixes the flag-precedence component of issue #63305.// See issue #56171 for general details on flag precedence.returnkubeletConfigFlagPrecedence(kc, args) })if err !=nil { glog.Fatal(err) }// If we should just use our existing, local config, the controller will return a nil configif dynamicKubeletConfig !=nil { kubeletConfig = dynamicKubeletConfig// Note: flag precedence was already enforced in the controller, prior to validation,// by our above transform function. Now we simply update feature gates from the new config.if err := utilfeature.DefaultFeatureGate.SetFromMap(kubeletConfig.FeatureGates); err !=nil { glog.Fatal(err) } }}
// construct a KubeletServer from kubeletFlags and kubeletConfigkubeletServer :=&options.KubeletServer{ KubeletFlags: *kubeletFlags, KubeletConfiguration: *kubeletConfig,}
2.2.2. kubeletDeps
// use kubeletServer to construct the default KubeletDepskubeletDeps, err :=UnsecuredDependencies(kubeletServer)if err !=nil { glog.Fatal(err)}// add the kubelet config controller to kubeletDepskubeletDeps.KubeletConfigController = kubeletConfigController
2.2.3. docker shim
如果开启了docker shim参数,则执行RunDockershim。
// start the experimental docker shim, if enabledif kubeletServer.KubeletFlags.ExperimentalDockershim {if err :=RunDockershim(&kubeletServer.KubeletFlags, kubeletConfig, stopCh); err !=nil { glog.Fatal(err) }return}
2.3. AddFlags
// keep cleanFlagSet separate, so Cobra doesn't pollute it with the global flagskubeletFlags.AddFlags(cleanFlagSet)options.AddKubeletConfigFlags(cleanFlagSet, kubeletConfig)options.AddGlobalFlags(cleanFlagSet)cleanFlagSet.BoolP("help", "h", false, fmt.Sprintf("help for %s", cmd.Name()))// ugly, but necessary, because Cobra's default UsageFunc and HelpFunc pollute the flagset with global flagsconst usageFmt ="Usage:\n %s\n\nFlags:\n%s"cmd.SetUsageFunc(func(cmd *cobra.Command) error { fmt.Fprintf(cmd.OutOrStderr(), usageFmt, cmd.UseLine(), cleanFlagSet.FlagUsagesWrapped(2))returnnil})cmd.SetHelpFunc(func(cmd *cobra.Command, args []string) { fmt.Fprintf(cmd.OutOrStdout(), "%s\n\n"+usageFmt, cmd.Long, cmd.UseLine(), cleanFlagSet.FlagUsagesWrapped(2))})
// Run runs the specified KubeletServer with the given Dependencies. This should never exit.// The kubeDeps argument may be nil - if so, it is initialized from the settings on KubeletServer.// Otherwise, the caller is assumed to have set up the Dependencies object and a default one will// not be generated.funcRun(s *options.KubeletServer, kubeDeps *kubelet.Dependencies, stopCh <-chanstruct{}) error {// To help debugging, immediately log version glog.Infof("Version: %+v", version.Get())if err :=initForOS(s.KubeletFlags.WindowsService); err !=nil {return fmt.Errorf("failed OS init: %v", err) }if err :=run(s, kubeDeps, stopCh); err !=nil {return fmt.Errorf("failed to run Kubelet: %v", err) }returnnil}
dynamicKubeClient, err = dynamic.NewForConfig(clientConfig)
if err != nil {
glog.Warningf("Failed to initialize dynamic KubeClient: %v", err)
}
3.1.4. eventClient
// make a separate client for events
eventClientConfig := *clientConfig
eventClientConfig.QPS = float32(s.EventRecordQPS)
eventClientConfig.Burst = int(s.EventBurst)
eventClient, err = v1core.NewForConfig(&eventClientConfig)
if err != nil {
glog.Warningf("Failed to create API Server client for Events: %v", err)
}
3.1.5. heartbeatClient
// make a separate client for heartbeat with throttling disabled and a timeout attachedheartbeatClientConfig :=*clientConfigheartbeatClientConfig.Timeout = s.KubeletConfiguration.NodeStatusUpdateFrequency.Duration// if the NodeLease feature is enabled, the timeout is the minimum of the lease duration and status update frequencyif utilfeature.DefaultFeatureGate.Enabled(features.NodeLease) { leaseTimeout := time.Duration(s.KubeletConfiguration.NodeLeaseDurationSeconds) * time.Secondif heartbeatClientConfig.Timeout > leaseTimeout { heartbeatClientConfig.Timeout = leaseTimeout }}heartbeatClientConfig.QPS =float32(-1)heartbeatClient, err = clientset.NewForConfig(&heartbeatClientConfig)if err !=nil { glog.Warningf("Failed to create API Server client for heartbeat: %v", err)}
3.1.6. csiClient
// csiClient works with CRDs that support json onlyclientConfig.ContentType ="application/json"csiClient, err := csiclientset.NewForConfig(clientConfig)if err !=nil { glog.Warningf("Failed to create CSI API client: %v", err)}
// RunKubelet is responsible for setting up and running a kubelet. It is used in three different applications:// 1 Integration tests// 2 Kubelet binary// 3 Standalone 'kubernetes' binary// Eventually, #2 will be replaced with instances of #3funcRunKubelet(kubeServer *options.KubeletServer, kubeDeps *kubelet.Dependencies, runOnce bool) error {... k, err :=CreateAndInitKubelet(&kubeServer.KubeletConfiguration,... kubeServer.NodeStatusMaxImages)if err !=nil {return fmt.Errorf("failed to create kubelet: %v", err) }// NewMainKubelet should have set up a pod source config if one didn't exist// when the builder was run. This is just a precaution.if kubeDeps.PodConfig ==nil {return fmt.Errorf("failed to create kubelet, pod source config was nil") } podCfg := kubeDeps.PodConfig rlimit.RlimitNumFiles(uint64(kubeServer.MaxOpenFiles))// process pods and exit.if runOnce {if _, err := k.RunOnce(podCfg.Updates()); err !=nil {return fmt.Errorf("runonce failed: %v", err) } glog.Infof("Started kubelet as runonce") } else {startKubelet(k, podCfg, &kubeServer.KubeletConfiguration, kubeDeps, kubeServer.EnableServer) glog.Infof("Started kubelet") }returnnil}