Code change:
introduced configuration of additional logging aspects (e.g. format) through command line flags and config file. This was merged for Kubernetes 1.28. Now the following invocation doesn't work as expected when the config file doesn't configure logging: It should run with verbosity 4. Instead it runs with verbosity 0, from the config. Run with this config file: No response 28 rc n/a No response No response No response No response
This issue is currently awaiting triage. If a SIG or subproject determines this is a relevant issue, they will accept it by applying the label and provide further guidance. The label can be by org members by writing in a comment. <detailsInstructions for interacting with me using PR comments are available . If you have questions or suggestions related to my behavior, please file an issue against the repository. </details
The problem is caused by this line: At that point, is 4 (from the command line flag), and then it gets overwritten with == 0. The normal approach would be: set up config with defaults modify config through flags modify config further by parsing a config file into it. Can kube-proxy do this? It has the downside that a config file can only overwrite fields if they are in the file. A config field doesn't get reset to defaults just by parsing the file. /cc
it looks like kube-proxy special-cases the to let a flag override config... can/should it do the same thing for verbosity? are there any other flags like this?
I don't think that's the normal approach... it's more normal to make flags and config file mutually exclusive. That's difficult for things which started as flags and moved into config
/sig network /sig instrumentation /kind bug /kind regression /milestone v1.28
let's go with and warn it and comment as much as possible, I was going with something like but Patrick is working on it so I assign to him the issue
/assign
Hey folks, v1.28 Bug Triage Lead here Just wanted to know if this is already tracked by SIG leads and someone already working actively fixing it and set a priority?
Perhaps I should have said "this is how component-base/logs was meant to be used". Somehow it worked for kubelet. Here's my preliminary solution: It needs more testing, but I wanted to share it early because I am running out of time today.
it is , I can take over Patrick's work in case is needed
It would be nice if the logs API could distinguish between and , how about make to a pointer? But this change is supposed to be a breaking change, I'm not sure of the scope of the impact. For side, if set and at the same time, should the command flag override the config file or warn it and be discarded? I think it should be overridden.
xref:

Related discussion:
text: } } <ins> // TestOptionsComplete checks that command line flags are combined with a // config properly. func TestOptionsComplete(t *testing.T) { header := `apiVersion: kubeproxy.config.k8s.io/v1alpha1 kind: KubeProxyConfiguration ` // Determine default config (depends on platform defaults). o := NewOptions() require.NoError(t, o.Complete(new(pflag.FlagSet))) expected := o.config config := header + `logging: format: json flushFrequency: 1s verbosity: 10 vmodule: - filePattern: foo.go verbosity: 6 - filePattern: bar.go verbosity: 8 ` expectedLoggingConfig := logsapi.LoggingConfiguration{ Format:         "json", FlushFrequency: logsapi.TimeOrMetaDuration{Duration: metav1.Duration{Duration: time.Second}, SerializeAsString: true}, Verbosity:      10, VModule: []logsapi.VModuleItem{ { FilePattern: "foo.go", Verbosity:   6, }, { FilePattern: "bar.go", Verbosity:   8, }, }, Options: logsapi.FormatOptions{ JSON: logsapi.JSONOptions{ InfoBufferSize: resource.QuantityValue{Quantity: resource.MustParse("0")}, }, }, } for name, tc := range map[string]struct { config   string flags    []string expected *kubeproxyconfig.KubeProxyConfiguration }{ "empty": { expected: expected, }, "empty-config": { config:   header, expected: expected, }, "logging-config": { config: config, expected: func() *kubeproxyconfig.KubeProxyConfiguration { c := expected.DeepCopy() c.Logging = *expectedLoggingConfig.DeepCopy() return c }(), }, "flags": { flags: []string{ "-v=7", "--vmodule", "goo.go=8", }, expected: func() *kubeproxyconfig.KubeProxyConfiguration { c := expected.DeepCopy() c.Logging.Verbosity = 7 c.Logging.VModule = append(c.Logging.VModule, logsapi.VModuleItem{ FilePattern: "goo.go", Verbosity:   8, }) return c }(), }, "both": { config: config, flags: []string{ "-v=7", "--vmodule", "goo.go=8", "--ipvs-scheduler", "some-scheduler", // Overwritten by config. }, expected: func() *kubeproxyconfig.KubeProxyConfiguration { c := expected.DeepCopy() c.Logging = *expectedLoggingConfig.DeepCopy() // Flag wins. c.Logging.Verbosity = 7 // Flag and config get merged with command line flags first. c.Logging.VModule = append([]logsapi.VModuleItem{ { FilePattern: "goo.go", Verbosity:   8, }, }, c.Logging.VModule...) return c }(), }, } { t.Run(name, func(t *testing.T) { options := NewOptions() fs := new(pflag.FlagSet) options.AddFlags(fs) flags := tc.flags if len(tc.config) > 0 { tmp := t.TempDir() configFile := path.Join(tmp, "kube-proxy.conf") require.NoError(t, ioutil.WriteFile(configFile, []byte(tc.config), 0666)) flags = append(flags, "--config", configFile) } require.NoError(t, fs.Parse(flags)) require.NoError(t, options.Complete(fs)) assert.Equal(t, tc.expected, options.config) }) } } </ins> type fakeProxyServerLongRun struct{} // Run runs the specified ProxyServer.