diff --git a/cmd/webhook/main.go b/cmd/webhook/main.go index bd9f4e5f9..47a5e8adc 100644 --- a/cmd/webhook/main.go +++ b/cmd/webhook/main.go @@ -72,6 +72,7 @@ func main() { srv := server.Server{ ListenAddr: fmt.Sprintf(":%d", securePort), HealthzAddr: fmt.Sprintf(":%d", healthzPort), + EnablePprof: true, CertificateSource: source, ValidationWebhook: validationHook, MutationWebhook: mutationHook, diff --git a/pkg/util/BUILD.bazel b/pkg/util/BUILD.bazel index f7a1c5afc..9715f7c6e 100644 --- a/pkg/util/BUILD.bazel +++ b/pkg/util/BUILD.bazel @@ -42,6 +42,7 @@ filegroup( "//pkg/util/feature:all-srcs", "//pkg/util/kube:all-srcs", "//pkg/util/pki:all-srcs", + "//pkg/util/profiling:all-srcs", ], tags = ["automanaged"], visibility = ["//visibility:public"], diff --git a/pkg/util/profiling/BUILD.bazel b/pkg/util/profiling/BUILD.bazel new file mode 100644 index 000000000..855ce146f --- /dev/null +++ b/pkg/util/profiling/BUILD.bazel @@ -0,0 +1,22 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = ["profiling.go"], + importpath = "github.com/jetstack/cert-manager/pkg/util/profiling", + visibility = ["//visibility:public"], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/pkg/util/profiling/profiling.go b/pkg/util/profiling/profiling.go new file mode 100644 index 000000000..edf98027e --- /dev/null +++ b/pkg/util/profiling/profiling.go @@ -0,0 +1,38 @@ +/* +Copyright 2019 The Jetstack cert-manager contributors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package profiling + +import ( + "net/http" + "net/http/pprof" +) + +// Install adds the Profiling webservice to the given mux. +func Install(mux *http.ServeMux) { + mux.HandleFunc("/debug/pprof", redirectTo("/debug/pprof/")) + mux.HandleFunc("/debug/pprof/", pprof.Index) + mux.HandleFunc("/debug/pprof/profile", pprof.Profile) + mux.HandleFunc("/debug/pprof/symbol", pprof.Symbol) + mux.HandleFunc("/debug/pprof/trace", pprof.Trace) +} + +// redirectTo redirects request to a certain destination. +func redirectTo(to string) func(http.ResponseWriter, *http.Request) { + return func(rw http.ResponseWriter, req *http.Request) { + http.Redirect(rw, req, to, http.StatusFound) + } +} diff --git a/pkg/webhook/server/BUILD.bazel b/pkg/webhook/server/BUILD.bazel index c6cb1a1cb..1dc09a177 100644 --- a/pkg/webhook/server/BUILD.bazel +++ b/pkg/webhook/server/BUILD.bazel @@ -11,6 +11,7 @@ go_library( visibility = ["//visibility:public"], deps = [ "//pkg/logs:go_default_library", + "//pkg/util/profiling:go_default_library", "//pkg/webhook/handlers:go_default_library", "@com_github_go_logr_logr//:go_default_library", "@io_k8s_api//admission/v1beta1:go_default_library", diff --git a/pkg/webhook/server/server.go b/pkg/webhook/server/server.go index 935d8a861..337921a27 100644 --- a/pkg/webhook/server/server.go +++ b/pkg/webhook/server/server.go @@ -34,6 +34,7 @@ import ( "k8s.io/apimachinery/pkg/runtime/serializer/json" crlog "sigs.k8s.io/controller-runtime/pkg/log" + "github.com/jetstack/cert-manager/pkg/util/profiling" "github.com/jetstack/cert-manager/pkg/webhook/handlers" ) @@ -72,6 +73,10 @@ type Server struct { // If not specified, the healthz endpoint will not be exposed. HealthzAddr string + // EnablePprof controls whether net/http/pprof handlers are registered with + // the HTTP listener. + EnablePprof bool + // Scheme is used to decode/encode request/response payloads. // If not specified, a default scheme that registers the AdmissionReview // and ConversionReview resource types will be used. @@ -145,6 +150,10 @@ func (s *Server) Run(stopCh <-chan struct{}) error { mux.HandleFunc("/validate", s.handle(s.validate)) mux.HandleFunc("/mutate", s.handle(s.mutate)) mux.HandleFunc("/convert", s.handle(s.convert)) + if s.EnablePprof { + profiling.Install(mux) + s.Log.Info("registered pprof handlers") + } listenerChan := s.startServer(l, internalStopCh, mux) if certSourceChan == nil {