Skip to content

Commit

Permalink
Merge pull request #104774 from kerthcet/bug/fix-kubelet-log-defer-co…
Browse files Browse the repository at this point in the history
…nflict-with-exit

fix kubelet flushlogs not working together with exit
  • Loading branch information
k8s-ci-robot committed Jan 6, 2022
2 parents d754543 + 185e0a0 commit b1c204a
Showing 1 changed file with 16 additions and 33 deletions.
49 changes: 16 additions & 33 deletions cmd/kubelet/app/server.go
Expand Up @@ -115,6 +115,7 @@ func NewKubeletCommand() *cobra.Command {
cleanFlagSet := pflag.NewFlagSet(componentKubelet, pflag.ContinueOnError)
cleanFlagSet.SetNormalizeFunc(cliflag.WordSepNormalizeFunc)
kubeletFlags := options.NewKubeletFlags()

kubeletConfig, err := options.NewKubeletConfiguration()
// programmer error
if err != nil {
Expand Down Expand Up @@ -151,46 +152,38 @@ HTTP server: The kubelet can also listen for HTTP and respond to a simple API
// 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) {
RunE: func(cmd *cobra.Command, args []string) error {
// initial flag parse, since we disable cobra's flag parsing
if err := cleanFlagSet.Parse(args); err != nil {
klog.ErrorS(err, "Failed to parse kubelet flag")
cmd.Usage()
os.Exit(1)
return fmt.Errorf("failed to parse kubelet flag: %w", err)
}

// check if there are non-flag arguments in the command line
cmds := cleanFlagSet.Args()
if len(cmds) > 0 {
klog.ErrorS(nil, "Unknown command", "command", cmds[0])
cmd.Usage()
os.Exit(1)
return fmt.Errorf("unknown command %+s", cmds[0])
}

// short-circuit on help
help, err := cleanFlagSet.GetBool("help")
if err != nil {
klog.InfoS(`"help" flag is non-bool, programmer error, please correct`)
os.Exit(1)
return errors.New(`"help" flag is non-bool, programmer error, please correct`)
}
if help {
cmd.Help()
return
return cmd.Help()
}

// short-circuit on verflag
verflag.PrintAndExitIfRequested()

// set feature gates from initial flags-based config
if err := utilfeature.DefaultMutableFeatureGate.SetFromMap(kubeletConfig.FeatureGates); err != nil {
klog.ErrorS(err, "Failed to set feature gates from initial flags-based config")
os.Exit(1)
return fmt.Errorf("failed to set feature gates from initial flags-based config: %w", err)
}

// validate the initial KubeletFlags
if err := options.ValidateKubeletFlags(kubeletFlags); err != nil {
klog.ErrorS(err, "Failed to validate kubelet flags")
os.Exit(1)
return fmt.Errorf("failed to validate kubelet flags: %w", err)
}

if kubeletFlags.ContainerRuntime == "remote" && cleanFlagSet.Changed("pod-infra-container-image") {
Expand All @@ -201,28 +194,24 @@ HTTP server: The kubelet can also listen for HTTP and respond to a simple API
if configFile := kubeletFlags.KubeletConfigFile; len(configFile) > 0 {
kubeletConfig, err = loadConfigFile(configFile)
if err != nil {
klog.ErrorS(err, "Failed to load kubelet config file", "path", configFile)
os.Exit(1)
return fmt.Errorf("failed to load kubelet config file, error: %w, path: %s", err, configFile)
}
// 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 {
klog.ErrorS(err, "Failed to precedence kubeletConfigFlag")
os.Exit(1)
return fmt.Errorf("failed to precedence kubeletConfigFlag: %w", err)
}
// update feature gates based on new config
if err := utilfeature.DefaultMutableFeatureGate.SetFromMap(kubeletConfig.FeatureGates); err != nil {
klog.ErrorS(err, "Failed to set feature gates from initial flags-based config")
os.Exit(1)
return fmt.Errorf("failed to set feature gates from initial flags-based config: %w", 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 {
klog.ErrorS(err, "Failed to validate kubelet configuration", "path", kubeletConfig)
os.Exit(1)
return fmt.Errorf("failed to validate kubelet configuration, error: %w, path: %s", err, kubeletConfig)
}

if (kubeletConfig.KubeletCgroups != "" && kubeletConfig.KubeReservedCgroup != "") && (strings.Index(kubeletConfig.KubeletCgroups, kubeletConfig.KubeReservedCgroup) != 0) {
Expand All @@ -242,17 +231,15 @@ HTTP server: The kubelet can also listen for HTTP and respond to a simple API
return kubeletConfigFlagPrecedence(kc, args)
})
if err != nil {
klog.ErrorS(err, "Failed to bootstrap a configuration controller", "dynamicConfigDir", dynamicConfigDir)
os.Exit(1)
return fmt.Errorf("failed to bootstrap a configuration controller, error: %w, dynamicConfigDir: %s", err, dynamicConfigDir)
}
// If we should just use our existing, local config, the controller will return a nil config
if 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.DefaultMutableFeatureGate.SetFromMap(kubeletConfig.FeatureGates); err != nil {
klog.ErrorS(err, "Failed to set feature gates from initial flags-based config")
os.Exit(1)
return fmt.Errorf("failed to set feature gates from initial flags-based config: %w", err)
}
}
}
Expand All @@ -275,8 +262,7 @@ HTTP server: The kubelet can also listen for HTTP and respond to a simple API
// use kubeletServer to construct the default KubeletDeps
kubeletDeps, err := UnsecuredDependencies(kubeletServer, utilfeature.DefaultFeatureGate)
if err != nil {
klog.ErrorS(err, "Failed to construct kubelet dependencies")
os.Exit(1)
return fmt.Errorf("failed to construct kubelet dependencies: %w", err)
}

// add the kubelet config controller to kubeletDeps
Expand All @@ -297,10 +283,7 @@ HTTP server: The kubelet can also listen for HTTP and respond to a simple API
klog.V(5).InfoS("KubeletConfiguration", "configuration", kubeletServer.KubeletConfiguration)

// run the kubelet
if err := Run(ctx, kubeletServer, kubeletDeps, utilfeature.DefaultFeatureGate); err != nil {
klog.ErrorS(err, "Failed to run kubelet")
os.Exit(1)
}
return Run(ctx, kubeletServer, kubeletDeps, utilfeature.DefaultFeatureGate)
},
}

Expand Down

0 comments on commit b1c204a

Please sign in to comment.