Skip to content

Commit

Permalink
Enable pprof for all VPA components
Browse files Browse the repository at this point in the history
This change was inspured by how the cluster-autoscaler impliments pprof.

Fixes kubernetes#6946
  • Loading branch information
adrianmoisey committed Aug 10, 2024
1 parent 3e09d37 commit b09286f
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 24 deletions.
27 changes: 24 additions & 3 deletions vertical-pod-autoscaler/pkg/admission-controller/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ import (
"time"

apiv1 "k8s.io/api/core/v1"
"k8s.io/apiserver/pkg/server/mux"
"k8s.io/apiserver/pkg/server/routes"
"k8s.io/client-go/informers"
kube_client "k8s.io/client-go/kubernetes"
kube_flag "k8s.io/component-base/cli/flag"
Expand All @@ -44,6 +46,8 @@ import (
metrics_admission "k8s.io/autoscaler/vertical-pod-autoscaler/pkg/utils/metrics/admission"
"k8s.io/autoscaler/vertical-pod-autoscaler/pkg/utils/status"
vpa_api_util "k8s.io/autoscaler/vertical-pod-autoscaler/pkg/utils/vpa"

"github.com/prometheus/client_golang/prometheus/promhttp"
)

const (
Expand All @@ -62,8 +66,9 @@ var (
tlsPrivateKey: flag.String("tls-private-key", "/etc/tls-certs/serverKey.pem", "Path to server certificate key PEM file."),
reload: flag.Bool("reload-cert", false, "If set to true, reload leaf certificate."),
}
ciphers = flag.String("tls-ciphers", "", "A comma-separated or colon-separated list of ciphers to accept. Only works when min-tls-version is set to tls1_2.")
minTlsVersion = flag.String("min-tls-version", "tls1_2", "The minimum TLS version to accept. Must be set to either tls1_2 (default) or tls1_3.")
ciphers = flag.String("tls-ciphers", "", "A comma-separated or colon-separated list of ciphers to accept. Only works when min-tls-version is set to tls1_2.")
minTlsVersion = flag.String("min-tls-version", "tls1_2", "The minimum TLS version to accept. Must be set to either tls1_2 (default) or tls1_3.")
enableProfiling = flag.Bool("profiling", false, "Is debug/pprof endpoint enabled")

port = flag.Int("port", 8000, "The port to listen on.")
address = flag.String("address", ":8944", "The address to expose Prometheus metrics.")
Expand Down Expand Up @@ -91,9 +96,25 @@ func main() {
}

healthCheck := metrics.NewHealthCheck(time.Minute)
metrics.Initialize(*address, healthCheck)
metrics_admission.Register()

go func() {
pathRecorderMux := mux.NewPathRecorderMux("vertical-pod-autoscaler")

if *enableProfiling {
routes.Profiling{}.Install(pathRecorderMux)
}

if healthCheck != nil {
pathRecorderMux.Handle("/health-check", healthCheck)
}

pathRecorderMux.Handle("/metrics", promhttp.Handler())

err := http.ListenAndServe(*address, pathRecorderMux)
klog.Fatalf("Failed to start metrics: %v", err)
}()

config := common.CreateKubeConfigOrDie(*kubeconfig, float32(*kubeApiQps), int(*kubeApiBurst))

vpaClient := vpa_clientset.NewForConfigOrDie(config)
Expand Down
24 changes: 23 additions & 1 deletion vertical-pod-autoscaler/pkg/recommender/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package main
import (
"context"
"flag"
"net/http"
"os"
"strings"
"time"
Expand All @@ -27,6 +28,8 @@ import (
apiv1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/uuid"
"k8s.io/apiserver/pkg/server/mux"
"k8s.io/apiserver/pkg/server/routes"
"k8s.io/client-go/informers"
kube_client "k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/leaderelection"
Expand All @@ -52,6 +55,8 @@ import (
metrics_quality "k8s.io/autoscaler/vertical-pod-autoscaler/pkg/utils/metrics/quality"
metrics_recommender "k8s.io/autoscaler/vertical-pod-autoscaler/pkg/utils/metrics/recommender"
vpa_api_util "k8s.io/autoscaler/vertical-pod-autoscaler/pkg/utils/vpa"

"github.com/prometheus/client_golang/prometheus/promhttp"
)

var (
Expand All @@ -64,6 +69,7 @@ var (
kubeconfig = flag.String("kubeconfig", "", "Path to a kubeconfig. Only required if out-of-cluster.")
kubeApiQps = flag.Float64("kube-api-qps", 5.0, `QPS limit when making requests to Kubernetes apiserver`)
kubeApiBurst = flag.Float64("kube-api-burst", 10.0, `QPS burst limit when making requests to Kubernetes apiserver`)
enableProfiling = flag.Bool("profiling", false, "Is debug/pprof endpoint enabled")

storage = flag.String("storage", "", `Specifies storage mode. Supported values: prometheus, checkpoint (default)`)
// prometheus history provider configs
Expand Down Expand Up @@ -128,10 +134,26 @@ func main() {
}

healthCheck := metrics.NewHealthCheck(*metricsFetcherInterval * 5)
metrics.Initialize(*address, healthCheck)
metrics_recommender.Register()
metrics_quality.Register()

go func() {
pathRecorderMux := mux.NewPathRecorderMux("vertical-pod-autoscaler")

if *enableProfiling {
routes.Profiling{}.Install(pathRecorderMux)
}

if healthCheck != nil {
pathRecorderMux.Handle("/health-check", healthCheck)
}

pathRecorderMux.Handle("/metrics", promhttp.Handler())

err := http.ListenAndServe(*address, pathRecorderMux)
klog.Fatalf("Failed to start metrics: %v", err)
}()

if !leaderElection.LeaderElect {
run(healthCheck)
} else {
Expand Down
33 changes: 28 additions & 5 deletions vertical-pod-autoscaler/pkg/updater/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package main
import (
"context"
"flag"
"net/http"
"os"
"strings"
"time"
Expand All @@ -27,6 +28,8 @@ import (
apiv1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/uuid"
"k8s.io/apiserver/pkg/server/mux"
"k8s.io/apiserver/pkg/server/routes"
"k8s.io/client-go/informers"
kube_client "k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/leaderelection"
Expand All @@ -47,6 +50,8 @@ import (
metrics_updater "k8s.io/autoscaler/vertical-pod-autoscaler/pkg/utils/metrics/updater"
"k8s.io/autoscaler/vertical-pod-autoscaler/pkg/utils/status"
vpa_api_util "k8s.io/autoscaler/vertical-pod-autoscaler/pkg/utils/vpa"

"github.com/prometheus/client_golang/prometheus/promhttp"
)

var (
Expand All @@ -65,10 +70,11 @@ var (

evictionRateBurst = flag.Int("eviction-rate-burst", 1, `Burst of pods that can be evicted.`)

address = flag.String("address", ":8943", "The address to expose Prometheus metrics.")
kubeconfig = flag.String("kubeconfig", "", "Path to a kubeconfig. Only required if out-of-cluster.")
kubeApiQps = flag.Float64("kube-api-qps", 5.0, `QPS limit when making requests to Kubernetes apiserver`)
kubeApiBurst = flag.Float64("kube-api-burst", 10.0, `QPS burst limit when making requests to Kubernetes apiserver`)
address = flag.String("address", ":8943", "The address to expose Prometheus metrics.")
kubeconfig = flag.String("kubeconfig", "", "Path to a kubeconfig. Only required if out-of-cluster.")
kubeApiQps = flag.Float64("kube-api-qps", 5.0, `QPS limit when making requests to Kubernetes apiserver`)
kubeApiBurst = flag.Float64("kube-api-burst", 10.0, `QPS burst limit when making requests to Kubernetes apiserver`)
enableProfiling = flag.Bool("profiling", false, "Is debug/pprof endpoint enabled")

useAdmissionControllerStatus = flag.Bool("use-admission-controller-status", true,
"If true, updater will only evict pods when admission controller status is valid.")
Expand Down Expand Up @@ -99,7 +105,24 @@ func main() {
}

healthCheck := metrics.NewHealthCheck(*updaterInterval * 5)
metrics.Initialize(*address, healthCheck)

go func() {
pathRecorderMux := mux.NewPathRecorderMux("vertical-pod-autoscaler")

if *enableProfiling {
routes.Profiling{}.Install(pathRecorderMux)
}

if healthCheck != nil {
pathRecorderMux.Handle("/health-check", healthCheck)
}

pathRecorderMux.Handle("/metrics", promhttp.Handler())

err := http.ListenAndServe(*address, pathRecorderMux)
klog.Fatalf("Failed to start metrics: %v", err)
}()

metrics_updater.Register()

if !leaderElection.LeaderElect {
Expand Down
15 changes: 0 additions & 15 deletions vertical-pod-autoscaler/pkg/utils/metrics/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,11 @@ package metrics

import (
"math"
"net/http"
"time"

"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"

_ "k8s.io/component-base/metrics/prometheus/restclient" // for client-go metrics registration
"k8s.io/klog/v2"
)

// ExecutionTimer measures execution time of a computation, split into major steps
Expand All @@ -46,18 +43,6 @@ const (
MaxVpaSizeLog = 20
)

// Initialize sets up Prometheus to expose metrics & (optionally) health-check on the given address
func Initialize(address string, healthCheck *HealthCheck) {
go func() {
http.Handle("/metrics", promhttp.Handler())
if healthCheck != nil {
http.Handle("/health-check", healthCheck)
}
err := http.ListenAndServe(address, nil)
klog.Fatalf("Failed to start metrics: %v", err)
}()
}

// NewExecutionTimer provides a timer for admission latency; call ObserveXXX() on it to measure
func NewExecutionTimer(histo *prometheus.HistogramVec) *ExecutionTimer {
now := time.Now()
Expand Down

0 comments on commit b09286f

Please sign in to comment.