Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix kubelet flushlogs not working together with exit #104774

Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
49 changes: 16 additions & 33 deletions cmd/kubelet/app/server.go
Expand Up @@ -116,6 +116,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 @@ -152,31 +153,25 @@ 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 {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// 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)
Comment on lines -159 to -160
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After this change we no longer print usage info. I suspect this is okay because the kubelet usage info is massively long and makes it hard to see the error, but we should note this in the release note.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We will still print usage info here

return fmt.Errorf("failed to parse kubelet flag: %v", err)
kerthcet marked this conversation as resolved.
Show resolved Hide resolved
}

// 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
Expand All @@ -185,14 +180,12 @@ HTTP server: The kubelet can also listen for HTTP and respond to a simple API

// 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: %v", 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: %v", err)
}

if kubeletFlags.ContainerRuntime == "remote" && cleanFlagSet.Changed("pod-infra-container-image") {
Expand All @@ -203,28 +196,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: %v, 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: %v", 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: %v", 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: %v, path: %s", err, kubeletConfig)
}

if (kubeletConfig.KubeletCgroups != "" && kubeletConfig.KubeReservedCgroup != "") && (strings.Index(kubeletConfig.KubeletCgroups, kubeletConfig.KubeReservedCgroup) != 0) {
Expand All @@ -244,17 +233,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: %v, 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: %v", err)
}
}
}
Expand All @@ -276,8 +263,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: %v", err)
}

// add the kubelet config controller to kubeletDeps
Expand All @@ -298,10 +284,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