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
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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 { | ||
|
@@ -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 { | ||
// 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
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 | ||
|
@@ -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") { | ||
|
@@ -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) { | ||
|
@@ -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) | ||
} | ||
} | ||
} | ||
|
@@ -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 | ||
|
@@ -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) | ||
}, | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://pkg.go.dev/github.com/spf13/cobra#Command.RunE