diff --git a/api/v1alpha1/envoygateway_helpers.go b/api/v1alpha1/envoygateway_helpers.go index d7886b6f367..46591b107f3 100644 --- a/api/v1alpha1/envoygateway_helpers.go +++ b/api/v1alpha1/envoygateway_helpers.go @@ -6,6 +6,8 @@ package v1alpha1 import ( + "fmt" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -21,6 +23,7 @@ func DefaultEnvoyGateway() *EnvoyGateway { Provider: DefaultEnvoyGatewayProvider(), Logging: DefaultEnvoyGatewayLogging(), Admin: DefaultEnvoyGatewayAdmin(), + Debug: DefaultEnvoyGatewayDebug(), }, } } @@ -45,6 +48,9 @@ func (e *EnvoyGateway) SetEnvoyGatewayDefaults() { if e.Admin == nil { e.Admin = DefaultEnvoyGatewayAdmin() } + if e.Debug == nil { + e.Debug = DefaultEnvoyGatewayDebug() + } } // GetEnvoyGatewayAdmin returns the EnvoyGatewayAdmin of EnvoyGateway or a default EnvoyGatewayAdmin if unspecified. @@ -60,6 +66,36 @@ func (e *EnvoyGateway) GetEnvoyGatewayAdmin() *EnvoyGatewayAdmin { return e.Admin } +// GetEnvoyGatewayAdminAddress returns the EnvoyGateway Admin Address. +func (e *EnvoyGateway) GetEnvoyGatewayAdminAddress() string { + address := e.GetEnvoyGatewayAdmin().Address + if address != nil { + return fmt.Sprintf("%s:%d", address.Host, address.Port) + } + + return "" +} + +// GetEnvoyGatewayDebug returns the EnvoyGatewayDebug of EnvoyGateway or a default EnvoyGatewayDebug if unspecified. +func (e *EnvoyGateway) GetEnvoyGatewayDebug() *EnvoyGatewayDebug { + if e.Debug != nil { + return e.Debug + } + e.Debug = DefaultEnvoyGatewayDebug() + + return e.Debug +} + +// GetEnvoyGatewayDebugAddress returns the EnvoyGateway Debug Address. +func (e *EnvoyGateway) GetEnvoyGatewayDebugAddress() string { + address := e.GetEnvoyGatewayDebug().Address + if address != nil { + return fmt.Sprintf("%s:%d", address.Host, address.Port) + } + + return "" +} + // DefaultGateway returns a new Gateway with default configuration parameters. func DefaultGateway() *Gateway { return &Gateway{ @@ -103,7 +139,6 @@ func DefaultEnvoyGatewayKubeProvider() *EnvoyGatewayKubernetesProvider { // DefaultEnvoyGatewayAdmin returns a new EnvoyGatewayAdmin with default configuration parameters. func DefaultEnvoyGatewayAdmin() *EnvoyGatewayAdmin { return &EnvoyGatewayAdmin{ - Debug: false, Address: DefaultEnvoyGatewayAdminAddress(), } } @@ -116,6 +151,23 @@ func DefaultEnvoyGatewayAdminAddress() *EnvoyGatewayAdminAddress { } } +// DefaultEnvoyGatewayDebug returns a new EnvoyGatewayDebug with default configuration parameters. +func DefaultEnvoyGatewayDebug() *EnvoyGatewayDebug { + return &EnvoyGatewayDebug{ + EnableDumpConfig: false, + EnablePprof: false, + Address: DefaultEnvoyGatewayDebugAddress(), + } +} + +// DefaultEnvoyGatewayDebugAddress returns a new EnvoyGatewayDebugAddress with default configuration parameters. +func DefaultEnvoyGatewayDebugAddress() *EnvoyGatewayDebugAddress { + return &EnvoyGatewayDebugAddress{ + Port: GatewayDebugPort, + Host: GatewayDebugHost, + } +} + // GetEnvoyGatewayKubeProvider returns the EnvoyGatewayKubernetesProvider of Provider or // a default EnvoyGatewayKubernetesProvider if unspecified. If EnvoyGatewayProvider is not of // type "Kubernetes", a nil EnvoyGatewayKubernetesProvider is returned. diff --git a/api/v1alpha1/envoygateway_types.go b/api/v1alpha1/envoygateway_types.go index b96218f0746..2e4a5df03b5 100644 --- a/api/v1alpha1/envoygateway_types.go +++ b/api/v1alpha1/envoygateway_types.go @@ -19,6 +19,10 @@ const ( GatewayAdminPort = 19000 // GatewayAdminHost is the host of envoy gateway admin server. GatewayAdminHost = "127.0.0.1" + // GatewayDebugPort is the port which envoy gateway debug server is listening on. + GatewayDebugPort = 19010 + // GatewayDebugHost is the host of envoy gateway debug server. + GatewayDebugHost = "127.0.0.1" ) // +kubebuilder:object:root=true @@ -51,6 +55,7 @@ type EnvoyGatewaySpec struct { // +optional // +kubebuilder:default={default: info} Logging *EnvoyGatewayLogging `json:"logging,omitempty"` + // Admin defines the desired admin related abilities. // If unspecified, the Admin is used with default configuration // parameters. @@ -58,6 +63,12 @@ type EnvoyGatewaySpec struct { // +optional Admin *EnvoyGatewayAdmin `json:"admin,omitempty"` + // Debug defines the desired debug related abilities. + // If unspecified, the debug will not be running, including pprof, dump config etc. + // + // +optional + Debug *EnvoyGatewayDebug `json:"debug,omitempty"` + // RateLimit defines the configuration associated with the Rate Limit service // deployed by Envoy Gateway required to implement the Global Rate limiting // functionality. The specific rate limit service used here is the reference @@ -424,11 +435,26 @@ type EnvoyGatewayAdmin struct { // // +optional Address *EnvoyGatewayAdminAddress `json:"address,omitempty"` +} + +// EnvoyGatewayDebug defines the Envoy Gateway Debug configuration. +type EnvoyGatewayDebug struct { + + // EnableDumpConfig defines if enables dump the Envoy Gateway config in logs. + // + // +optional + EnableDumpConfig bool `json:"enableDumpConfig,omitempty"` + + // EnablePprof defines if enables pprof in Envoy Gateway debug server. + // + // +optional + EnablePprof bool `json:"enablePprof,omitempty"` - // Debug defines if enable the /debug endpoint of Envoy Gateway. + // Address defines the address of Envoy Gateway Debug Server. + // Pprof will use the debug address, if you set it to non-nil. // // +optional - Debug bool `json:"debug,omitempty"` + Address *EnvoyGatewayDebugAddress `json:"address,omitempty"` } // EnvoyGatewayAdminAddress defines the Envoy Gateway Admin Address configuration. @@ -446,6 +472,21 @@ type EnvoyGatewayAdminAddress struct { Host string `json:"host,omitempty"` } +// EnvoyGatewayDebugAddress defines the Envoy Gateway Debug Address configuration. +type EnvoyGatewayDebugAddress struct { + // Port defines the port the debug server is exposed on. + // + // +optional + // +kubebuilder:validation:Minimum=0 + // +kubebuilder:default=19010 + Port int `json:"port,omitempty"` + // Host defines the debug server hostname. + // + // +optional + // +kubebuilder:default="127.0.0.1" + Host string `json:"host,omitempty"` +} + func init() { SchemeBuilder.Register(&EnvoyGateway{}) } diff --git a/api/v1alpha1/envoyproxy_types.go b/api/v1alpha1/envoyproxy_types.go index 575eb2b9e08..00f4c38a7c4 100644 --- a/api/v1alpha1/envoyproxy_types.go +++ b/api/v1alpha1/envoyproxy_types.go @@ -129,44 +129,44 @@ type ProxyLogging struct { // and the log level is the value. If unspecified, defaults to "default: warn". // // +kubebuilder:default={default: warn} - Level map[LogComponent]LogLevel `json:"level,omitempty"` + Level map[ProxyLogComponent]LogLevel `json:"level,omitempty"` } -// LogComponent defines a component that supports a configured logging level. +// ProxyLogComponent defines a component that supports a configured logging level. // +kubebuilder:validation:Enum=system;upstream;http;connection;admin;client;filter;main;router;runtime -type LogComponent string +type ProxyLogComponent string const ( // LogComponentDefault defines the default logging component. // See more details: https://www.envoyproxy.io/docs/envoy/latest/operations/cli#cmdoption-l - LogComponentDefault LogComponent = "default" + LogComponentDefault ProxyLogComponent = "default" // LogComponentUpstream defines the "upstream" logging component. - LogComponentUpstream LogComponent = "upstream" + LogComponentUpstream ProxyLogComponent = "upstream" // LogComponentHTTP defines the "http" logging component. - LogComponentHTTP LogComponent = "http" + LogComponentHTTP ProxyLogComponent = "http" // LogComponentConnection defines the "connection" logging component. - LogComponentConnection LogComponent = "connection" + LogComponentConnection ProxyLogComponent = "connection" // LogComponentAdmin defines the "admin" logging component. - LogComponentAdmin LogComponent = "admin" + LogComponentAdmin ProxyLogComponent = "admin" // LogComponentClient defines the "client" logging component. - LogComponentClient LogComponent = "client" + LogComponentClient ProxyLogComponent = "client" // LogComponentFilter defines the "filter" logging component. - LogComponentFilter LogComponent = "filter" + LogComponentFilter ProxyLogComponent = "filter" // LogComponentMain defines the "main" logging component. - LogComponentMain LogComponent = "main" + LogComponentMain ProxyLogComponent = "main" // LogComponentRouter defines the "router" logging component. - LogComponentRouter LogComponent = "router" + LogComponentRouter ProxyLogComponent = "router" // LogComponentRuntime defines the "runtime" logging component. - LogComponentRuntime LogComponent = "runtime" + LogComponentRuntime ProxyLogComponent = "runtime" ) // ProxyBootstrap defines Envoy Bootstrap configuration. diff --git a/api/v1alpha1/validation/validate_test.go b/api/v1alpha1/validation/validate_test.go index 1a12cd54e09..007cb5da771 100644 --- a/api/v1alpha1/validation/validate_test.go +++ b/api/v1alpha1/validation/validate_test.go @@ -535,15 +535,12 @@ func TestEnvoyGatewayAdmin(t *testing.T) { // values should be set in default egAdmin := eg.GetEnvoyGatewayAdmin() assert.True(t, egAdmin != nil) - assert.True(t, egAdmin.Debug == false) assert.True(t, egAdmin.Address.Port == egv1a1.GatewayAdminPort) assert.True(t, egAdmin.Address.Host == egv1a1.GatewayAdminHost) // override the admin config // values should be updated - eg.Admin.Debug = true eg.Admin.Address = nil - assert.True(t, eg.Admin.Debug == true) assert.True(t, eg.GetEnvoyGatewayAdmin().Address.Port == egv1a1.GatewayAdminPort) assert.True(t, eg.GetEnvoyGatewayAdmin().Address.Host == egv1a1.GatewayAdminHost) @@ -552,20 +549,54 @@ func TestEnvoyGatewayAdmin(t *testing.T) { eg.Admin = nil eg.SetEnvoyGatewayDefaults() assert.True(t, eg.Admin != nil) - assert.True(t, eg.Admin.Debug == false) assert.True(t, eg.Admin.Address.Port == egv1a1.GatewayAdminPort) assert.True(t, eg.Admin.Address.Host == egv1a1.GatewayAdminHost) } +func TestEnvoyGatewayDebug(t *testing.T) { + // default envoygateway config debug should not be nil + eg := egv1a1.DefaultEnvoyGateway() + assert.True(t, eg.Debug != nil) + + // get default debug config from envoygateway + // values should be set in default + egDebug := eg.GetEnvoyGatewayDebug() + assert.True(t, egDebug != nil) + assert.True(t, eg.Debug.Address.Host == egv1a1.GatewayDebugHost) + assert.True(t, eg.Debug.Address.Port == egv1a1.GatewayDebugPort) + assert.True(t, egDebug.EnableDumpConfig == false) + assert.True(t, egDebug.EnablePprof == false) + + // override the debug config + // values should be updated + eg.Debug.Address = &egv1a1.EnvoyGatewayDebugAddress{ + Host: "0.0.0.0", + Port: 8899, + } + eg.Debug.EnableDumpConfig = true + eg.Debug.EnablePprof = true + assert.True(t, eg.GetEnvoyGatewayDebug().Address.Port == 8899) + assert.True(t, eg.GetEnvoyGatewayDebug().Address.Host == "0.0.0.0") + assert.True(t, egDebug.EnableDumpConfig == true) + assert.True(t, egDebug.EnablePprof == true) + + // set eg defaults when debug is nil + // the debug should not be nil + eg.Debug = nil + eg.SetEnvoyGatewayDefaults() + assert.True(t, eg.Debug != nil) + assert.True(t, eg.Debug.Address != nil) +} + func TestGetEnvoyProxyDefaultComponentLevel(t *testing.T) { cases := []struct { logging egv1a1.ProxyLogging - component egv1a1.LogComponent + component egv1a1.ProxyLogComponent expected egv1a1.LogLevel }{ { logging: egv1a1.ProxyLogging{ - Level: map[egv1a1.LogComponent]egv1a1.LogLevel{ + Level: map[egv1a1.ProxyLogComponent]egv1a1.LogLevel{ egv1a1.LogComponentDefault: egv1a1.LogLevelInfo, }, }, @@ -573,7 +604,7 @@ func TestGetEnvoyProxyDefaultComponentLevel(t *testing.T) { }, { logging: egv1a1.ProxyLogging{ - Level: map[egv1a1.LogComponent]egv1a1.LogLevel{ + Level: map[egv1a1.ProxyLogComponent]egv1a1.LogLevel{ egv1a1.LogComponentDefault: egv1a1.LogLevelInfo, }, }, @@ -600,7 +631,7 @@ func TestGetEnvoyProxyComponentLevelArgs(t *testing.T) { }, { logging: egv1a1.ProxyLogging{ - Level: map[egv1a1.LogComponent]egv1a1.LogLevel{ + Level: map[egv1a1.ProxyLogComponent]egv1a1.LogLevel{ egv1a1.LogComponentDefault: egv1a1.LogLevelInfo, }, }, @@ -608,7 +639,7 @@ func TestGetEnvoyProxyComponentLevelArgs(t *testing.T) { }, { logging: egv1a1.ProxyLogging{ - Level: map[egv1a1.LogComponent]egv1a1.LogLevel{ + Level: map[egv1a1.ProxyLogComponent]egv1a1.LogLevel{ egv1a1.LogComponentDefault: egv1a1.LogLevelInfo, egv1a1.LogComponentAdmin: egv1a1.LogLevelWarn, }, @@ -617,7 +648,7 @@ func TestGetEnvoyProxyComponentLevelArgs(t *testing.T) { }, { logging: egv1a1.ProxyLogging{ - Level: map[egv1a1.LogComponent]egv1a1.LogLevel{ + Level: map[egv1a1.ProxyLogComponent]egv1a1.LogLevel{ egv1a1.LogComponentDefault: egv1a1.LogLevelInfo, egv1a1.LogComponentAdmin: egv1a1.LogLevelWarn, egv1a1.LogComponentFilter: egv1a1.LogLevelDebug, @@ -627,7 +658,7 @@ func TestGetEnvoyProxyComponentLevelArgs(t *testing.T) { }, { logging: egv1a1.ProxyLogging{ - Level: map[egv1a1.LogComponent]egv1a1.LogLevel{ + Level: map[egv1a1.ProxyLogComponent]egv1a1.LogLevel{ egv1a1.LogComponentDefault: egv1a1.LogLevelInfo, egv1a1.LogComponentAdmin: egv1a1.LogLevelWarn, egv1a1.LogComponentFilter: egv1a1.LogLevelDebug, diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index b0a1f4f18c0..22cd1a49b9c 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -342,6 +342,41 @@ func (in *EnvoyGatewayCustomProvider) DeepCopy() *EnvoyGatewayCustomProvider { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *EnvoyGatewayDebug) DeepCopyInto(out *EnvoyGatewayDebug) { + *out = *in + if in.Address != nil { + in, out := &in.Address, &out.Address + *out = new(EnvoyGatewayDebugAddress) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EnvoyGatewayDebug. +func (in *EnvoyGatewayDebug) DeepCopy() *EnvoyGatewayDebug { + if in == nil { + return nil + } + out := new(EnvoyGatewayDebug) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *EnvoyGatewayDebugAddress) DeepCopyInto(out *EnvoyGatewayDebugAddress) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EnvoyGatewayDebugAddress. +func (in *EnvoyGatewayDebugAddress) DeepCopy() *EnvoyGatewayDebugAddress { + if in == nil { + return nil + } + out := new(EnvoyGatewayDebugAddress) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *EnvoyGatewayFileResourceProvider) DeepCopyInto(out *EnvoyGatewayFileResourceProvider) { *out = *in @@ -517,6 +552,11 @@ func (in *EnvoyGatewaySpec) DeepCopyInto(out *EnvoyGatewaySpec) { *out = new(EnvoyGatewayAdmin) (*in).DeepCopyInto(*out) } + if in.Debug != nil { + in, out := &in.Debug, &out.Debug + *out = new(EnvoyGatewayDebug) + (*in).DeepCopyInto(*out) + } if in.RateLimit != nil { in, out := &in.RateLimit, &out.RateLimit *out = new(RateLimit) @@ -1488,7 +1528,7 @@ func (in *ProxyLogging) DeepCopyInto(out *ProxyLogging) { *out = *in if in.Level != nil { in, out := &in.Level, &out.Level - *out = make(map[LogComponent]LogLevel, len(*in)) + *out = make(map[ProxyLogComponent]LogLevel, len(*in)) for key, val := range *in { (*out)[key] = val } diff --git a/internal/cmd/server.go b/internal/cmd/server.go index b6979023f09..d3382061736 100644 --- a/internal/cmd/server.go +++ b/internal/cmd/server.go @@ -6,17 +6,10 @@ package cmd import ( - "fmt" - "net" - "net/http" - "net/http/pprof" - "time" - - "github.com/davecgh/go-spew/spew" - "github.com/spf13/cobra" ctrl "sigs.k8s.io/controller-runtime" + "github.com/envoyproxy/gateway/internal/debug" "github.com/envoyproxy/gateway/internal/envoygateway/config" extensionregistry "github.com/envoyproxy/gateway/internal/extension/registry" gatewayapirunner "github.com/envoyproxy/gateway/internal/gatewayapi/runner" @@ -57,12 +50,11 @@ func server() error { return err } - if cfg.EnvoyGateway.Admin.Debug { - spewConfig := spew.NewDefaultConfig() - spewConfig.DisableMethods = true - spewConfig.Dump(cfg) + // Init eg debug servers. + if err := debug.Init(cfg); err != nil { + return err } - + // init eg runners. if err := setupRunners(cfg); err != nil { return err } @@ -203,9 +195,6 @@ func setupRunners(cfg *config.Server) error { } } - // Start the admin server - go setupAdminServer(cfg) - // Wait until done <-ctx.Done() // Close messages @@ -223,33 +212,3 @@ func setupRunners(cfg *config.Server) error { return nil } - -func setupAdminServer(cfg *config.Server) { - adminHandlers := http.NewServeMux() - - address := cfg.EnvoyGateway.GetEnvoyGatewayAdmin().Address - - if cfg.EnvoyGateway.GetEnvoyGatewayAdmin().Debug { - // Serve pprof endpoints to aid in live debugging. - adminHandlers.HandleFunc("/debug/pprof/", pprof.Index) - adminHandlers.HandleFunc("/debug/pprof/profile", pprof.Profile) - adminHandlers.HandleFunc("/debug/pprof/trace", pprof.Trace) - adminHandlers.HandleFunc("/debug/pprof/symbol", pprof.Symbol) - adminHandlers.HandleFunc("/debug/pprof/cmdline", pprof.Cmdline) - } - - adminServer := &http.Server{ - Handler: adminHandlers, - Addr: net.JoinHostPort(address.Host, fmt.Sprint(address.Port)), - ReadTimeout: 5 * time.Second, - ReadHeaderTimeout: 5 * time.Second, - WriteTimeout: 10 * time.Second, - IdleTimeout: 15 * time.Second, - } - - // Listen And Serve Admin Server. - if err := adminServer.ListenAndServe(); err != nil { - cfg.Logger.Error(err, "start debug server failed") - } - -} diff --git a/internal/debug/server.go b/internal/debug/server.go new file mode 100644 index 00000000000..1fd75e0b8c6 --- /dev/null +++ b/internal/debug/server.go @@ -0,0 +1,67 @@ +// Copyright Envoy Gateway Authors +// SPDX-License-Identifier: Apache-2.0 +// The full text of the Apache license is available in the LICENSE file at +// the root of the repo. + +package debug + +import ( + "net/http" + "net/http/pprof" + "time" + + "github.com/davecgh/go-spew/spew" + + "github.com/envoyproxy/gateway/api/v1alpha1" + "github.com/envoyproxy/gateway/internal/envoygateway/config" + "github.com/envoyproxy/gateway/internal/logging" +) + +var ( + debugLogger = logging.DefaultLogger(v1alpha1.LogLevelInfo).WithName("debug") +) + +func Init(cfg *config.Server) error { + if cfg.EnvoyGateway.GetEnvoyGatewayDebug().EnableDumpConfig { + spewConfig := spew.NewDefaultConfig() + spewConfig.DisableMethods = true + spewConfig.Dump(cfg) + } + + return start(cfg) +} + +func start(cfg *config.Server) error { + handlers := http.NewServeMux() + address := cfg.EnvoyGateway.GetEnvoyGatewayDebugAddress() + enablePprof := cfg.EnvoyGateway.GetEnvoyGatewayDebug().EnablePprof + + debugLogger.Info("starting debug server", "address", address, "enablePprof", enablePprof) + + if enablePprof { + // Serve pprof endpoints to aid in live debugging. + handlers.HandleFunc("/debug/pprof/", pprof.Index) + handlers.HandleFunc("/debug/pprof/profile", pprof.Profile) + handlers.HandleFunc("/debug/pprof/trace", pprof.Trace) + handlers.HandleFunc("/debug/pprof/symbol", pprof.Symbol) + handlers.HandleFunc("/debug/pprof/cmdline", pprof.Cmdline) + } + + debugServer := &http.Server{ + Handler: handlers, + Addr: address, + ReadTimeout: 5 * time.Second, + ReadHeaderTimeout: 5 * time.Second, + WriteTimeout: 10 * time.Second, + IdleTimeout: 15 * time.Second, + } + + // Listen And Serve Debug Server. + go func() { + if err := debugServer.ListenAndServe(); err != nil { + cfg.Logger.Error(err, "start debug server failed") + } + }() + + return nil +} diff --git a/internal/debug/server_test.go b/internal/debug/server_test.go new file mode 100644 index 00000000000..31ee956831a --- /dev/null +++ b/internal/debug/server_test.go @@ -0,0 +1,34 @@ +// Copyright Envoy Gateway Authors +// SPDX-License-Identifier: Apache-2.0 +// The full text of the Apache license is available in the LICENSE file at +// the root of the repo. + +package debug + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/envoyproxy/gateway/api/v1alpha1" + "github.com/envoyproxy/gateway/internal/envoygateway/config" +) + +func TestInitDebugServer(t *testing.T) { + svrConfig := &config.Server{ + EnvoyGateway: &v1alpha1.EnvoyGateway{ + EnvoyGatewaySpec: v1alpha1.EnvoyGatewaySpec{ + Debug: &v1alpha1.EnvoyGatewayDebug{ + EnableDumpConfig: true, + EnablePprof: true, + Address: &v1alpha1.EnvoyGatewayDebugAddress{ + Host: "127.0.0.1", + Port: 19010, + }, + }, + }, + }, + } + err := Init(svrConfig) + assert.NoError(t, err) +} diff --git a/internal/infrastructure/kubernetes/proxy/resource_provider_test.go b/internal/infrastructure/kubernetes/proxy/resource_provider_test.go index 50ce69946e9..d8344d0ceaa 100644 --- a/internal/infrastructure/kubernetes/proxy/resource_provider_test.go +++ b/internal/infrastructure/kubernetes/proxy/resource_provider_test.go @@ -65,7 +65,7 @@ func TestDeployment(t *testing.T) { caseName string infra *ir.Infra deploy *egv1a1.KubernetesDeploymentSpec - proxyLogging map[egv1a1.LogComponent]egv1a1.LogLevel + proxyLogging map[egv1a1.ProxyLogComponent]egv1a1.LogLevel bootstrap string telemetry *egv1a1.ProxyTelemetry concurrency *int32 @@ -248,7 +248,7 @@ func TestDeployment(t *testing.T) { caseName: "component-level", infra: newTestInfra(), deploy: nil, - proxyLogging: map[egv1a1.LogComponent]egv1a1.LogLevel{ + proxyLogging: map[egv1a1.ProxyLogComponent]egv1a1.LogLevel{ egv1a1.LogComponentDefault: egv1a1.LogLevelError, egv1a1.LogComponentFilter: egv1a1.LogLevelInfo, }, diff --git a/internal/provider/kubernetes/kubernetes.go b/internal/provider/kubernetes/kubernetes.go index 820868eeafb..c679dd9a1f0 100644 --- a/internal/provider/kubernetes/kubernetes.go +++ b/internal/provider/kubernetes/kubernetes.go @@ -15,7 +15,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/healthz" "sigs.k8s.io/controller-runtime/pkg/manager" - metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server" + "sigs.k8s.io/controller-runtime/pkg/metrics/server" "github.com/envoyproxy/gateway/api/v1alpha1" "github.com/envoyproxy/gateway/internal/envoygateway" @@ -41,19 +41,22 @@ func New(cfg *rest.Config, svr *config.Server, resources *message.ProviderResour LeaderElection: false, HealthProbeBindAddress: ":8081", LeaderElectionID: "5b9825d2.gateway.envoyproxy.io", - Metrics: metricsserver.Options{ - BindAddress: ":8080", - }, + } + + if address := svr.EnvoyGateway.GetEnvoyGatewayAdminAddress(); address != "" { + mgrOpts.Metrics = server.Options{ + BindAddress: address, + } } // TODO: implement config validation on the watch mode config - byNamespace := + namespacedMode := svr.EnvoyGateway.Provider != nil && svr.EnvoyGateway.Provider.Kubernetes != nil && (svr.EnvoyGateway.Provider.Kubernetes.Watch != nil) && (svr.EnvoyGateway.Provider.Kubernetes.Watch.Type == v1alpha1.KubernetesWatchModeTypeNamespaces) && (len(svr.EnvoyGateway.Provider.Kubernetes.Watch.Namespaces) > 0) - if byNamespace { + if namespacedMode { mgrOpts.Cache.DefaultNamespaces = make(map[string]cache.Config) for _, watchNS := range svr.EnvoyGateway.Provider.Kubernetes.Watch.Namespaces { mgrOpts.Cache.DefaultNamespaces[watchNS] = cache.Config{} diff --git a/site/content/en/latest/api/extension_types.md b/site/content/en/latest/api/extension_types.md index 73bff134936..e530a0973c5 100644 --- a/site/content/en/latest/api/extension_types.md +++ b/site/content/en/latest/api/extension_types.md @@ -202,6 +202,7 @@ EnvoyGateway is the schema for the envoygateways API. | `provider` _[EnvoyGatewayProvider](#envoygatewayprovider)_ | Provider defines the desired provider and provider-specific configuration. If unspecified, the Kubernetes provider is used with default configuration parameters. | | `logging` _[EnvoyGatewayLogging](#envoygatewaylogging)_ | Logging defines logging parameters for Envoy Gateway. | | `admin` _[EnvoyGatewayAdmin](#envoygatewayadmin)_ | Admin defines the desired admin related abilities. If unspecified, the Admin is used with default configuration parameters. | +| `debug` _[EnvoyGatewayDebug](#envoygatewaydebug)_ | Debug defines the desired debug related abilities. If unspecified, the debug will not be running, including pprof, dump config etc. | | `rateLimit` _[RateLimit](#ratelimit)_ | RateLimit defines the configuration associated with the Rate Limit service deployed by Envoy Gateway required to implement the Global Rate limiting functionality. The specific rate limit service used here is the reference implementation in Envoy. For more details visit https://github.com/envoyproxy/ratelimit. This configuration is unneeded for "Local" rate limiting. | | `extensionManager` _[ExtensionManager](#extensionmanager)_ | ExtensionManager defines an extension manager to register for the Envoy Gateway Control Plane. | | `extensionApis` _[ExtensionAPISettings](#extensionapisettings)_ | ExtensionAPIs defines the settings related to specific Gateway API Extensions implemented by Envoy Gateway | @@ -220,7 +221,6 @@ _Appears in:_ | Field | Description | | --- | --- | | `address` _[EnvoyGatewayAdminAddress](#envoygatewayadminaddress)_ | Address defines the address of Envoy Gateway Admin Server. | -| `debug` _boolean_ | Debug defines if enable the /debug endpoint of Envoy Gateway. | #### EnvoyGatewayAdminAddress @@ -253,6 +253,38 @@ _Appears in:_ | `infrastructure` _[EnvoyGatewayInfrastructureProvider](#envoygatewayinfrastructureprovider)_ | Infrastructure defines the desired infrastructure provider. This provider is used to specify the provider to be used to provide an environment to deploy the out resources like the Envoy Proxy data plane. | +#### EnvoyGatewayDebug + + + +EnvoyGatewayDebug defines the Envoy Gateway Debug configuration. + +_Appears in:_ +- [EnvoyGateway](#envoygateway) +- [EnvoyGatewaySpec](#envoygatewayspec) + +| Field | Description | +| --- | --- | +| `enableDumpConfig` _boolean_ | EnableDumpConfig defines if enables dump the Envoy Gateway config in logs. | +| `enablePprof` _boolean_ | EnablePprof defines if enables pprof in Envoy Gateway debug server. | +| `address` _[EnvoyGatewayDebugAddress](#envoygatewaydebugaddress)_ | Address defines the address of Envoy Gateway Debug Server. Pprof will use the debug address, if you set it to non-nil. | + + +#### EnvoyGatewayDebugAddress + + + +EnvoyGatewayDebugAddress defines the Envoy Gateway Debug Address configuration. + +_Appears in:_ +- [EnvoyGatewayDebug](#envoygatewaydebug) + +| Field | Description | +| --- | --- | +| `port` _integer_ | Port defines the port the debug server is exposed on. | +| `host` _string_ | Host defines the debug server hostname. | + + #### EnvoyGatewayFileResourceProvider @@ -383,6 +415,7 @@ _Appears in:_ | `provider` _[EnvoyGatewayProvider](#envoygatewayprovider)_ | Provider defines the desired provider and provider-specific configuration. If unspecified, the Kubernetes provider is used with default configuration parameters. | | `logging` _[EnvoyGatewayLogging](#envoygatewaylogging)_ | Logging defines logging parameters for Envoy Gateway. | | `admin` _[EnvoyGatewayAdmin](#envoygatewayadmin)_ | Admin defines the desired admin related abilities. If unspecified, the Admin is used with default configuration parameters. | +| `debug` _[EnvoyGatewayDebug](#envoygatewaydebug)_ | Debug defines the desired debug related abilities. If unspecified, the debug will not be running, including pprof, dump config etc. | | `rateLimit` _[RateLimit](#ratelimit)_ | RateLimit defines the configuration associated with the Rate Limit service deployed by Envoy Gateway required to implement the Global Rate limiting functionality. The specific rate limit service used here is the reference implementation in Envoy. For more details visit https://github.com/envoyproxy/ratelimit. This configuration is unneeded for "Local" rate limiting. | | `extensionManager` _[ExtensionManager](#extensionmanager)_ | ExtensionManager defines an extension manager to register for the Envoy Gateway Control Plane. | | `extensionApis` _[ExtensionAPISettings](#extensionapisettings)_ | ExtensionAPIs defines the settings related to specific Gateway API Extensions implemented by Envoy Gateway | @@ -888,17 +921,6 @@ _Appears in:_ | `value` _string_ | Value defines the hard-coded value to add to each span. | -#### LogComponent - -_Underlying type:_ `string` - -LogComponent defines a component that supports a configured logging level. - -_Appears in:_ -- [ProxyLogging](#proxylogging) - - - #### LogLevel _Underlying type:_ `string` @@ -1116,6 +1138,17 @@ _Appears in:_ | `value` _string_ | Value is a YAML string of the bootstrap. | +#### ProxyLogComponent + +_Underlying type:_ `string` + +ProxyLogComponent defines a component that supports a configured logging level. + +_Appears in:_ +- [ProxyLogging](#proxylogging) + + + #### ProxyLogging @@ -1127,7 +1160,7 @@ _Appears in:_ | Field | Description | | --- | --- | -| `level` _object (keys:[LogComponent](#logcomponent), values:[LogLevel](#loglevel))_ | Level is a map of logging level per component, where the component is the key and the log level is the value. If unspecified, defaults to "default: warn". | +| `level` _object (keys:[ProxyLogComponent](#proxylogcomponent), values:[LogLevel](#loglevel))_ | Level is a map of logging level per component, where the component is the key and the log level is the value. If unspecified, defaults to "default: warn". | #### ProxyMetrics diff --git a/site/content/en/latest/design/pprof.md b/site/content/en/latest/design/pprof.md index c535b480071..1a744c47ea4 100644 --- a/site/content/en/latest/design/pprof.md +++ b/site/content/en/latest/design/pprof.md @@ -1,15 +1,19 @@ --- -title: "Add Pprof support in Envoy Gateway" +title: "Debug support in Envoy Gateway" --- ## Overview -Envoy Gateway exposes endpoints at `localhost:8899/debug/pprof` to run Golang profiles to aid in live debugging. The endpoints are equivalent to those found in the http/pprof package. `/debug/pprof/` returns an HTML page listing the available profiles. +Envoy Gateway exposes endpoints at `localhost:19010/debug/pprof` to run Golang profiles to aid in live debugging. + +The endpoints are equivalent to those found in the http/pprof package. `/debug/pprof/` returns an HTML page listing the available profiles. ## Goals -* Add Debug Pprof support to Envoy Gateway control plane. +* Add debug server to Envoy Gateway control plane, separated with admin server. +* Add pprof support to Envoy Gateway control plane. * Define an API to allow Envoy Gateway to custom debug server configuration. +* Define an API to allow Envoy Gateway to open envoy gateway config dump in logs. The following are the different types of profiles end-user can run: @@ -30,11 +34,13 @@ PROFILE | FUNCTION ## API -* Add `admin` field in EnvoyGateway config. -* Add `debug` field under `admin` field. -* Add `enable`, `port` and `host` under `address` field. +* Add `debug` field in EnvoyGateway config. +* Add `address` field under `debug` field. +* Add `port` and `host` under `address` field. +* Add `enableDumpConfig` field under `debug field. +* Add `enablePprof` field under `debug field. -Here is an example configuration +Here is an example configuration to open debug server and enable Pprof: ``` yaml apiVersion: gateway.envoyproxy.io/v1alpha1 @@ -43,9 +49,22 @@ gateway: kind: EnvoyGateway provider: type: "Kubernetes" -admin: - debug: true - address: - port: 8899 - host: "127.0.0.1" +debug: + enablePprof: true + address: + host: 127.0.0.1 + port: 19010 +``` + +Here is an example configuration to open envoy gateway config dump in logs: + +```yaml +apiVersion: gateway.envoyproxy.io/v1alpha1 +gateway: + controllerName: "gateway.envoyproxy.io/gatewayclass-controller" +kind: EnvoyGateway +provider: + type: "Kubernetes" +debug: + enableDumpConfig: true ```