From 2d1cd82a98e2e38376008529fe704e04cd67cf7a Mon Sep 17 00:00:00 2001 From: Charandas Date: Mon, 18 Mar 2024 10:25:30 -0700 Subject: [PATCH] K8s: standalone: use Grafana's logger to stream all logs (#84530) --- Co-authored-by: Marcus Efraimsson --- pkg/cmd/grafana/apiserver/apiserver.md | 9 ++++-- pkg/cmd/grafana/apiserver/cmd.go | 17 +++++++---- pkg/cmd/grafana/apiserver/server.go | 42 ++++++++++++++++++-------- pkg/infra/log/log.go | 31 +++++++++++++++++++ 4 files changed, 79 insertions(+), 20 deletions(-) diff --git a/pkg/cmd/grafana/apiserver/apiserver.md b/pkg/cmd/grafana/apiserver/apiserver.md index b1f0756da89..27dce737a7d 100644 --- a/pkg/cmd/grafana/apiserver/apiserver.md +++ b/pkg/cmd/grafana/apiserver/apiserver.md @@ -12,14 +12,19 @@ aggregation path altogether and just run this example apiserver as a standalone ### Usage ```shell -go run ./pkg/cmd/grafana apiserver example.grafana.app \ +go run ./pkg/cmd/grafana apiserver \ + --runtime-config=example.grafana.app/v0alpha1=true \ + --grafana-apiserver-dev-mode \ + --verbosity 10 \ --secure-port 7443 ``` ### Verify that all works +In dev mode, the standalone server's loopback kubeconfig is written to `./data/grafana-apiserver/apiserver.kubeconfig`. + ```shell -export KUBECONFIG=./example-apiserver/kubeconfig +export KUBECONFIG=./data/grafana-apiserver/apiserver.kubeconfig kubectl api-resources NAME SHORTNAMES APIVERSION NAMESPACED KIND diff --git a/pkg/cmd/grafana/apiserver/cmd.go b/pkg/cmd/grafana/apiserver/cmd.go index a7a621adad7..dd63ab8a3d4 100644 --- a/pkg/cmd/grafana/apiserver/cmd.go +++ b/pkg/cmd/grafana/apiserver/cmd.go @@ -5,11 +5,10 @@ import ( "github.com/spf13/cobra" genericapiserver "k8s.io/apiserver/pkg/server" - "k8s.io/apiserver/pkg/server/options" "k8s.io/component-base/cli" + "github.com/grafana/grafana/pkg/infra/log" "github.com/grafana/grafana/pkg/server" - grafanaapiserver "github.com/grafana/grafana/pkg/services/apiserver" "github.com/grafana/grafana/pkg/services/apiserver/standalone" ) @@ -30,6 +29,14 @@ func newCommandStartExampleAPIServer(o *APIServerOptions, stopCh <-chan struct{} devAcknowledgementNotice, Example: "grafana apiserver --runtime-config=example.grafana.app/v0alpha1=true", RunE: func(c *cobra.Command, args []string) error { + if err := log.SetupConsoleLogger("debug"); err != nil { + return nil + } + + if err := o.Validate(); err != nil { + return err + } + runtime, err := standalone.ReadRuntimeConfig(runtimeConfig) if err != nil { return err @@ -67,11 +74,9 @@ func newCommandStartExampleAPIServer(o *APIServerOptions, stopCh <-chan struct{} factoryOptions.AddFlags(cmd.Flags()) } + o.ExtraOptions.AddFlags(cmd.Flags()) + // Register standard k8s flags with the command line - o.RecommendedOptions = options.NewRecommendedOptions( - defaultEtcdPathPrefix, - grafanaapiserver.Codecs.LegacyCodec(), // the codec is passed to etcd and not used - ) o.RecommendedOptions.AddFlags(cmd.Flags()) return cmd diff --git a/pkg/cmd/grafana/apiserver/server.go b/pkg/cmd/grafana/apiserver/server.go index 246123d0290..28e51181154 100644 --- a/pkg/cmd/grafana/apiserver/server.go +++ b/pkg/cmd/grafana/apiserver/server.go @@ -15,6 +15,7 @@ import ( "github.com/grafana/grafana/pkg/apiserver/builder" grafanaAPIServer "github.com/grafana/grafana/pkg/services/apiserver" + grafanaAPIServerOptions "github.com/grafana/grafana/pkg/services/apiserver/options" "github.com/grafana/grafana/pkg/services/apiserver/standalone" "github.com/grafana/grafana/pkg/services/apiserver/utils" "github.com/grafana/grafana/pkg/setting" @@ -29,6 +30,7 @@ const ( type APIServerOptions struct { factory standalone.APIServerFactory builders []builder.APIGroupBuilder + ExtraOptions *grafanaAPIServerOptions.ExtraOptions RecommendedOptions *options.RecommendedOptions AlternateDNS []string @@ -40,6 +42,11 @@ func newAPIServerOptions(out, errOut io.Writer) *APIServerOptions { return &APIServerOptions{ StdOut: out, StdErr: errOut, + RecommendedOptions: options.NewRecommendedOptions( + defaultEtcdPathPrefix, + grafanaAPIServer.Codecs.LegacyCodec(), // the codec is passed to etcd and not used + ), + ExtraOptions: grafanaAPIServerOptions.NewExtraOptions(), } } @@ -148,6 +155,12 @@ func (o *APIServerOptions) Config() (*genericapiserver.RecommendedConfig, error) } } + if o.ExtraOptions != nil { + if err := o.ExtraOptions.ApplyTo(serverConfig); err != nil { + return nil, err + } + } + serverConfig.DisabledPostStartHooks = serverConfig.DisabledPostStartHooks.Insert("generic-apiserver-start-informers") serverConfig.DisabledPostStartHooks = serverConfig.DisabledPostStartHooks.Insert("priority-and-fairness-config-consumer") @@ -165,12 +178,15 @@ func (o *APIServerOptions) Config() (*genericapiserver.RecommendedConfig, error) } // Validate validates APIServerOptions -// NOTE: we don't call validate on the top level recommended options as it doesn't like skipping etcd-servers -// the function is left here for troubleshooting any other config issues -func (o *APIServerOptions) Validate(args []string) error { - errors := []error{} - errors = append(errors, o.RecommendedOptions.Validate()...) - errors = append(errors, o.factory.GetOptions().ValidateOptions()...) +func (o *APIServerOptions) Validate() error { + errors := make([]error, 0) + // NOTE: we don't call validate on the top level recommended options as it doesn't like skipping etcd-servers + // the function is left here for troubleshooting any other config issues + // errors = append(errors, o.RecommendedOptions.Validate()...) + if factoryOptions := o.factory.GetOptions(); factoryOptions != nil { + errors = append(errors, factoryOptions.ValidateOptions()...) + } + return utilerrors.NewAggregate(errors) } @@ -183,7 +199,7 @@ func (o *APIServerOptions) RunAPIServer(config *genericapiserver.RecommendedConf delegationTarget := genericapiserver.NewEmptyDelegate() completedConfig := config.Complete() - server, err := completedConfig.New("example-apiserver", delegationTarget) + server, err := completedConfig.New("standalone-apiserver", delegationTarget) if err != nil { return err } @@ -195,11 +211,13 @@ func (o *APIServerOptions) RunAPIServer(config *genericapiserver.RecommendedConf } // write the local config to disk - if err = clientcmd.WriteToFile( - utils.FormatKubeConfig(server.LoopbackClientConfig), - path.Join(dataPath, "apiserver.kubeconfig"), - ); err != nil { - return err + if o.ExtraOptions.DevMode { + if err = clientcmd.WriteToFile( + utils.FormatKubeConfig(server.LoopbackClientConfig), + path.Join(dataPath, "apiserver.kubeconfig"), + ); err != nil { + return err + } } return server.PrepareRun().Run(stopCh) diff --git a/pkg/infra/log/log.go b/pkg/infra/log/log.go index 53e80ca07c7..f9c741e1346 100644 --- a/pkg/infra/log/log.go +++ b/pkg/infra/log/log.go @@ -499,3 +499,34 @@ func ReadLoggingConfig(modes []string, logsPath string, cfg *ini.File) error { return nil } + +// SetupConsoleLogger setup Grafana console logger with provided level. +func SetupConsoleLogger(level string) error { + iniFile := ini.Empty() + sLog, err := iniFile.NewSection("log") + if err != nil { + return err + } + + _, err = sLog.NewKey("level", level) + if err != nil { + return err + } + + sLogConsole, err := iniFile.NewSection("log.console") + if err != nil { + return err + } + + _, err = sLogConsole.NewKey("format", "console") + if err != nil { + return err + } + + err = ReadLoggingConfig([]string{"console"}, "", iniFile) + if err != nil { + return err + } + + return nil +}