From 3b3fa3ed1c679cece90b56cb5cff8c75419205c5 Mon Sep 17 00:00:00 2001 From: Amir Alavi Date: Wed, 22 Nov 2023 21:13:14 -0500 Subject: [PATCH] fix: json logging Signed-off-by: Amir Alavi --- cmd/descheduler/app/options/options.go | 1 - cmd/descheduler/app/server.go | 67 ++++++++++++-------------- cmd/descheduler/descheduler.go | 1 - docs/cli/descheduler.md | 13 ++++- 4 files changed, 42 insertions(+), 40 deletions(-) diff --git a/cmd/descheduler/app/options/options.go b/cmd/descheduler/app/options/options.go index b8f8db26ab..384afbda27 100644 --- a/cmd/descheduler/app/options/options.go +++ b/cmd/descheduler/app/options/options.go @@ -87,7 +87,6 @@ func newDefaultComponentConfig() (*componentconfig.DeschedulerConfiguration, err // AddFlags adds flags for a specific SchedulerServer to the specified FlagSet func (rs *DeschedulerServer) AddFlags(fs *pflag.FlagSet) { - fs.StringVar(&rs.Logging.Format, "logging-format", "text", `Sets the log format. Permitted formats: "text", "json". Non-default formats don't honor these flags: --add-dir-header, --alsologtostderr, --log-backtrace-at, --log_dir, --log_file, --log_file_max_size, --logtostderr, --skip-headers, --skip-log-headers, --stderrthreshold, --log-flush-frequency.\nNon-default choices are currently alpha and subject to change without warning.`) fs.DurationVar(&rs.DeschedulingInterval, "descheduling-interval", rs.DeschedulingInterval, "Time interval between two consecutive descheduler executions. Setting this value instructs the descheduler to run in a continuous loop at the interval specified.") fs.StringVar(&rs.ClientConnection.Kubeconfig, "kubeconfig", rs.ClientConnection.Kubeconfig, "File with kube configuration. Deprecated, use client-connection-kubeconfig instead.") fs.StringVar(&rs.ClientConnection.Kubeconfig, "client-connection-kubeconfig", rs.ClientConnection.Kubeconfig, "File path to kube configuration for interacting with kubernetes apiserver.") diff --git a/cmd/descheduler/app/server.go b/cmd/descheduler/app/server.go index 9cf8822f2a..33e3b1fc3a 100644 --- a/cmd/descheduler/app/server.go +++ b/cmd/descheduler/app/server.go @@ -20,7 +20,6 @@ package app import ( "context" "io" - "os" "os/signal" "syscall" @@ -32,12 +31,14 @@ import ( "github.com/spf13/cobra" + "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/apimachinery/pkg/watch" apiserver "k8s.io/apiserver/pkg/server" "k8s.io/apiserver/pkg/server/mux" restclient "k8s.io/client-go/rest" - registry "k8s.io/component-base/logs/api/v1" - jsonLog "k8s.io/component-base/logs/json" + "k8s.io/component-base/featuregate" + "k8s.io/component-base/logs" + logsapi "k8s.io/component-base/logs/api/v1" _ "k8s.io/component-base/logs/json/register" "k8s.io/component-base/metrics/legacyregistry" "k8s.io/klog/v2" @@ -50,40 +51,31 @@ func NewDeschedulerCommand(out io.Writer) *cobra.Command { klog.ErrorS(err, "unable to initialize server") } + featureGate := featuregate.NewFeatureGate() + logConfig := logsapi.NewLoggingConfiguration() + cmd := &cobra.Command{ Use: "descheduler", Short: "descheduler", Long: `The descheduler evicts pods which may be bound to less desired nodes`, - Run: func(cmd *cobra.Command, args []string) { - // s.Logs.Config.Format = s.Logging.Format - - // LoopbackClientConfig is a config for a privileged loopback connection - var LoopbackClientConfig *restclient.Config - var SecureServing *apiserver.SecureServingInfo - if err := s.SecureServing.ApplyTo(&SecureServing, &LoopbackClientConfig); err != nil { - klog.ErrorS(err, "failed to apply secure server configuration") - return + RunE: func(cmd *cobra.Command, args []string) error { + logs.InitLogs() + if logsapi.ValidateAndApply(logConfig, featureGate); err != nil { + return err } - SecureServing.DisableHTTP2 = !s.EnableHTTP2 - - var factory registry.LogFormatFactory - if s.Logging.Format == "json" { - factory = jsonLog.Factory{} + // loopbackClientConfig is a config for a privileged loopback connection + var loopbackClientConfig *restclient.Config + var secureServing *apiserver.SecureServingInfo + if err := s.SecureServing.ApplyTo(&secureServing, &loopbackClientConfig); err != nil { + klog.ErrorS(err, "failed to apply secure server configuration") + return err } - if factory == nil { - klog.ClearLogger() - } else { - log, loggerControl := factory.Create(registry.LoggingConfiguration{ - Format: s.Logging.Format, - Verbosity: s.Logging.Verbosity, - }, registry.LoggingOptions{}) - defer loggerControl.Flush() - klog.SetLogger(log) - } + secureServing.DisableHTTP2 = !s.EnableHTTP2 ctx, done := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM) + defer done() pathRecorderMux := mux.NewPathRecorderMux("descheduler") if !s.DisableMetrics { @@ -92,25 +84,31 @@ func NewDeschedulerCommand(out io.Writer) *cobra.Command { healthz.InstallHandler(pathRecorderMux, healthz.NamedCheck("Descheduler", healthz.PingHealthz.Check)) - stoppedCh, _, err := SecureServing.Serve(pathRecorderMux, 0, ctx.Done()) + stoppedCh, _, err := secureServing.Serve(pathRecorderMux, 0, ctx.Done()) if err != nil { klog.Fatalf("failed to start secure server: %v", err) - return + return err } - err = Run(ctx, s) - if err != nil { + if err = Run(ctx, s); err != nil { klog.ErrorS(err, "descheduler server") + return err } - done() // wait for metrics server to close <-stoppedCh + + return nil }, } cmd.SetOut(out) flags := cmd.Flags() s.AddFlags(flags) + + runtime.Must(logsapi.AddFeatureGates(featureGate)) + featureGate.AddFlag(flags) + logsapi.AddFlags(logConfig, flags) + return cmd } @@ -125,8 +123,3 @@ func Run(ctx context.Context, rs *options.DeschedulerServer) error { watch.DefaultChanSize = 100000 return descheduler.Run(ctx, rs) } - -func SetupLogs() { - klog.SetOutput(os.Stdout) - klog.InitFlags(nil) -} diff --git a/cmd/descheduler/descheduler.go b/cmd/descheduler/descheduler.go index f143a118b2..e6cfffb196 100644 --- a/cmd/descheduler/descheduler.go +++ b/cmd/descheduler/descheduler.go @@ -25,7 +25,6 @@ import ( ) func init() { - app.SetupLogs() descheduler.SetupPlugins() } diff --git a/docs/cli/descheduler.md b/docs/cli/descheduler.md index 1dbc3e0fb8..0ec15b0a9b 100644 --- a/docs/cli/descheduler.md +++ b/docs/cli/descheduler.md @@ -22,6 +22,12 @@ descheduler [flags] --disable-metrics Disables metrics. The metrics are by default served through https://localhost:10258/metrics. Secure address, resp. port can be changed through --bind-address, resp. --secure-port flags. --dry-run Execute descheduler in dry run mode. --enable-http2 If http/2 should be enabled for the metrics and health check + --feature-gates mapStringBool A set of key=value pairs that describe feature gates for alpha/experimental features. Options are: + AllAlpha=true|false (ALPHA - default=false) + AllBeta=true|false (BETA - default=false) + ContextualLogging=true|false (ALPHA - default=false) + LoggingAlphaOptions=true|false (ALPHA - default=false) + LoggingBetaOptions=true|false (BETA - default=true) -h, --help help for descheduler --http2-max-streams-per-connection int The limit that the server gives to clients for the maximum number of streams in an HTTP/2 connection. Zero means to use golang's default. --kubeconfig string File with kube configuration. Deprecated, use client-connection-kubeconfig instead. @@ -32,7 +38,10 @@ descheduler [flags] --leader-elect-resource-name string The name of resource object that is used for locking during leader election. (default "descheduler") --leader-elect-resource-namespace string The namespace of resource object that is used for locking during leader election. (default "kube-system") --leader-elect-retry-period duration The duration the clients should wait between attempting acquisition and renewal of a leadership. This is only applicable if leader election is enabled. (default 26s) - --logging-format string Sets the log format. Permitted formats: "text", "json". Non-default formats don't honor these flags: --add-dir-header, --alsologtostderr, --log-backtrace-at, --log_dir, --log_file, --log_file_max_size, --logtostderr, --skip-headers, --skip-log-headers, --stderrthreshold, --log-flush-frequency.\nNon-default choices are currently alpha and subject to change without warning. (default "text") + --log-flush-frequency duration Maximum number of seconds between log flushes (default 5s) + --log-json-info-buffer-size quantity [Alpha] In JSON format with split output streams, the info messages can be buffered for a while to increase performance. The default value of zero bytes disables buffering. The size can be specified as number of bytes (512), multiples of 1000 (1K), multiples of 1024 (2Ki), or powers of those (3M, 4G, 5Mi, 6Gi). Enable the LoggingAlphaOptions feature gate to use this. + --log-json-split-stream [Alpha] In JSON format, write error messages to stderr and info messages to stdout. The default is to write a single stream to stdout. Enable the LoggingAlphaOptions feature gate to use this. + --logging-format string Sets the log format. Permitted formats: "json" (gated by LoggingBetaOptions), "text". (default "text") --otel-collector-endpoint string Set this flag to the OpenTelemetry Collector Service Address --otel-fallback-no-op-on-error Fallback to NoOp Tracer in case of error --otel-sample-rate float Sample rate to collect the Traces (default 1) @@ -50,6 +59,8 @@ descheduler [flags] --tls-min-version string Minimum TLS version supported. Possible values: VersionTLS10, VersionTLS11, VersionTLS12, VersionTLS13 --tls-private-key-file string File containing the default x509 private key matching --tls-cert-file. --tls-sni-cert-key namedCertKey A pair of x509 certificate and private key file paths, optionally suffixed with a list of domain patterns which are fully qualified domain names, possibly with prefixed wildcard segments. The domain patterns also allow IP addresses, but IPs should only be used if the apiserver has visibility to the IP address requested by a client. If no domain patterns are provided, the names of the certificate are extracted. Non-wildcard matches trump over wildcard matches, explicit domain patterns trump over extracted names. For multiple key/certificate pairs, use the --tls-sni-cert-key multiple times. Examples: "example.crt,example.key" or "foo.crt,foo.key:*.foo.com,foo.com". (default []) + -v, --v Level number for the log level verbosity + --vmodule pattern=N,... comma-separated list of pattern=N settings for file-filtered logging (only works for text log format) ``` ### SEE ALSO