diff --git a/artifacts/deploy/karmada-metrics-adapter.yaml b/artifacts/deploy/karmada-metrics-adapter.yaml index 678edb13baf5..19eaf8954cac 100644 --- a/artifacts/deploy/karmada-metrics-adapter.yaml +++ b/artifacts/deploy/karmada-metrics-adapter.yaml @@ -27,6 +27,7 @@ spec: command: - /bin/karmada-metrics-adapter - --kubeconfig=/etc/karmada/config/karmada.config + - --metrics-bind-address=:8080 - --authentication-kubeconfig=/etc/karmada/config/karmada.config - --authorization-kubeconfig=/etc/karmada/config/karmada.config - --client-ca-file=/etc/karmada/pki/server/ca.crt diff --git a/charts/karmada/templates/karmada-metrics-adapter.yaml b/charts/karmada/templates/karmada-metrics-adapter.yaml index 4c13ea825d38..0bb881d469e5 100644 --- a/charts/karmada/templates/karmada-metrics-adapter.yaml +++ b/charts/karmada/templates/karmada-metrics-adapter.yaml @@ -44,6 +44,7 @@ spec: command: - /bin/karmada-metrics-adapter - --kubeconfig=/etc/kubeconfig + - --metrics-bind-address=:8080 - --authentication-kubeconfig=/etc/kubeconfig - --authorization-kubeconfig=/etc/kubeconfig - --tls-cert-file=/etc/kubernetes/pki/karmada.crt diff --git a/cmd/metrics-adapter/app/options/options.go b/cmd/metrics-adapter/app/options/options.go index 37c930637558..c75e4071dd2c 100755 --- a/cmd/metrics-adapter/app/options/options.go +++ b/cmd/metrics-adapter/app/options/options.go @@ -18,6 +18,9 @@ package options import ( "context" + "net/http" + "os" + "time" "github.com/spf13/pflag" openapinamer "k8s.io/apiserver/pkg/endpoints/openapi" @@ -25,6 +28,8 @@ import ( "k8s.io/client-go/informers" "k8s.io/client-go/kubernetes" "k8s.io/client-go/tools/clientcmd" + "k8s.io/component-base/metrics" + "k8s.io/component-base/metrics/legacyregistry" "k8s.io/klog/v2" "sigs.k8s.io/custom-metrics-apiserver/pkg/cmd/options" "sigs.k8s.io/metrics-server/pkg/api" @@ -39,10 +44,45 @@ import ( "github.com/karmada-io/karmada/pkg/version" ) +const ( + // ReadHeaderTimeout is the amount of time allowed to read + // request headers. + // HTTP timeouts are necessary to expire inactive connections + // and failing to do so might make the application vulnerable + // to attacks like slowloris which work by sending data very slow, + // which in case of no timeout will keep the connection active + // eventually leading to a denial-of-service (DoS) attack. + // References: + // - https://en.wikipedia.org/wiki/Slowloris_(computer_security) + ReadHeaderTimeout = 32 * time.Second + // WriteTimeout is the amount of time allowed to write the + // request data. + // HTTP timeouts are necessary to expire inactive connections + // and failing to do so might make the application vulnerable + // to attacks like slowloris which work by sending data very slow, + // which in case of no timeout will keep the connection active + // eventually leading to a denial-of-service (DoS) attack. + WriteTimeout = 5 * time.Minute + // ReadTimeout is the amount of time allowed to read + // response data. + // HTTP timeouts are necessary to expire inactive connections + // and failing to do so might make the application vulnerable + // to attacks like slowloris which work by sending data very slow, + // which in case of no timeout will keep the connection active + // eventually leading to a denial-of-service (DoS) attack. + ReadTimeout = 5 * time.Minute +) + // Options contains everything necessary to create and run metrics-adapter. type Options struct { CustomMetricsAdapterServerOptions *options.CustomMetricsAdapterServerOptions + // MetricsBindAddress is the TCP address that the server should bind to + // for serving prometheus metrics. + // It can be set to "0" to disable the metrics serving. + // Defaults to ":8080". + MetricsBindAddress string + KubeConfig string // ClusterAPIQPS is the QPS to use while talking with cluster kube-apiserver. ClusterAPIQPS float32 @@ -73,6 +113,7 @@ func (o *Options) Complete() error { func (o *Options) AddFlags(fs *pflag.FlagSet) { o.CustomMetricsAdapterServerOptions.AddFlags(fs) o.ProfileOpts.AddFlags(fs) + fs.StringVar(&o.MetricsBindAddress, "metrics-bind-address", ":8080", "The TCP address that the server should bind to for serving prometheus metrics(e.g. 127.0.0.1:8080, :8080). It can be set to \"0\" to disable the metrics serving. Defaults to 0.0.0.0:8080.") fs.Float32Var(&o.ClusterAPIQPS, "cluster-api-qps", 40.0, "QPS to use while talking with cluster kube-apiserver.") fs.IntVar(&o.ClusterAPIBurst, "cluster-api-burst", 60, "Burst to use while talking with cluster kube-apiserver.") fs.Float32Var(&o.KubeAPIQPS, "kube-api-qps", 40.0, "QPS to use while talking with karmada-apiserver.") @@ -136,6 +177,9 @@ func (o *Options) Config(stopCh <-chan struct{}) (*metricsadapter.MetricsServer, // Run runs the metrics-adapter with options. This should never exit. func (o *Options) Run(ctx context.Context) error { klog.Infof("karmada-metrics-adapter version: %s", version.Get()) + if o.MetricsBindAddress != "0" { + go serveMetrics(o.MetricsBindAddress) + } profileflag.ListenAndServe(o.ProfileOpts) @@ -147,3 +191,31 @@ func (o *Options) Run(ctx context.Context) error { return metricsServer.StartServer(ctx) } + +func serveMetrics(address string) { + mux := http.NewServeMux() + mux.Handle("/metrics", metricsHandler()) + serveHTTP(address, mux, "metrics") +} + +func metricsHandler() http.Handler { + return metrics.HandlerFor(legacyregistry.DefaultGatherer, metrics.HandlerOpts{ + ErrorHandling: metrics.HTTPErrorOnError, + }) +} + +func serveHTTP(address string, handler http.Handler, name string) { + httpServer := &http.Server{ + Addr: address, + Handler: handler, + ReadHeaderTimeout: ReadHeaderTimeout, + WriteTimeout: WriteTimeout, + ReadTimeout: ReadTimeout, + } + + klog.Infof("Starting %s server on %s", name, address) + if err := httpServer.ListenAndServe(); err != nil { + klog.Errorf("Failed to serve %s on %s: %v", name, address, err) + os.Exit(1) + } +} diff --git a/operator/pkg/controlplane/metricsadapter/manifests.go b/operator/pkg/controlplane/metricsadapter/manifests.go index cab68714ba87..e9212593f712 100644 --- a/operator/pkg/controlplane/metricsadapter/manifests.go +++ b/operator/pkg/controlplane/metricsadapter/manifests.go @@ -48,6 +48,7 @@ spec: command: - /bin/karmada-metrics-adapter - --kubeconfig=/etc/karmada/kubeconfig + - --metrics-bind-address=:8080 - --authentication-kubeconfig=/etc/karmada/kubeconfig - --authorization-kubeconfig=/etc/karmada/kubeconfig - --client-ca-file=/etc/karmada/pki/ca.crt diff --git a/pkg/karmadactl/addons/metricsadapter/manifests.go b/pkg/karmadactl/addons/metricsadapter/manifests.go index 521f4bbe91ee..930e69a3db94 100644 --- a/pkg/karmadactl/addons/metricsadapter/manifests.go +++ b/pkg/karmadactl/addons/metricsadapter/manifests.go @@ -53,6 +53,7 @@ spec: command: - /bin/karmada-metrics-adapter - --kubeconfig=/etc/kubeconfig + - --metrics-bind-address=:8080 - --authentication-kubeconfig=/etc/kubeconfig - --authorization-kubeconfig=/etc/kubeconfig - --client-ca-file=/etc/karmada/pki/ca.crt