From 7eebf674d452300b797ba3f2efc256e6622c98f1 Mon Sep 17 00:00:00 2001 From: "Timothy St. Clair" Date: Fri, 13 Mar 2015 10:44:11 -0500 Subject: [PATCH] Update to option enable profiling on the master daemon processes. --profiling=true , default is false --- cmd/integration/integration.go | 1 + cmd/kube-apiserver/app/server.go | 3 +++ .../app/controllermanager.go | 15 +++++++++++++-- cmd/kubernetes/kubernetes.go | 2 ++ pkg/master/master.go | 11 +++++++++-- plugin/cmd/kube-scheduler/app/server.go | 13 ++++++++++++- test/integration/client_test.go | 1 + 7 files changed, 41 insertions(+), 5 deletions(-) diff --git a/cmd/integration/integration.go b/cmd/integration/integration.go index 00508e3b59e56..7f20de6afb921 100644 --- a/cmd/integration/integration.go +++ b/cmd/integration/integration.go @@ -179,6 +179,7 @@ func startComponents(manifestURL string) (apiServerURL string) { EtcdHelper: helper, KubeletClient: fakeKubeletClient{}, EnableLogsSupport: false, + EnableProfiling: true, APIPrefix: "/api", Authorizer: apiserver.NewAlwaysAllowAuthorizer(), AdmissionControl: admit.NewAlwaysAdmit(), diff --git a/cmd/kube-apiserver/app/server.go b/cmd/kube-apiserver/app/server.go index f0702470d6844..4203e3d72e5f9 100644 --- a/cmd/kube-apiserver/app/server.go +++ b/cmd/kube-apiserver/app/server.go @@ -74,6 +74,7 @@ type APIServer struct { KubeletConfig client.KubeletConfig ClusterName string SyncPodStatus bool + EnableProfiling bool } // NewAPIServer creates a new APIServer object with default parameters @@ -152,6 +153,7 @@ func (s *APIServer) AddFlags(fs *pflag.FlagSet) { fs.Var(&s.RuntimeConfig, "runtime_config", "A set of key=value pairs that describe runtime configuration that may be passed to the apiserver.") client.BindKubeletClientConfigFlags(fs, &s.KubeletConfig) fs.StringVar(&s.ClusterName, "cluster_name", s.ClusterName, "The instance prefix for the cluster") + fs.BoolVar(&s.EnableProfiling, "profiling", false, "Enable profiling via web interface host:port/debug/pprof/") } // TODO: Longer term we should read this from some config store, rather than a flag. @@ -236,6 +238,7 @@ func (s *APIServer) Run(_ []string) error { EnableLogsSupport: s.EnableLogsSupport, EnableUISupport: true, EnableSwaggerSupport: true, + EnableProfiling: s.EnableProfiling, EnableIndex: true, APIPrefix: s.APIPrefix, CorsAllowedOriginList: s.CorsAllowedOriginList, diff --git a/cmd/kube-controller-manager/app/controllermanager.go b/cmd/kube-controller-manager/app/controllermanager.go index 2d3849d6a4418..d1677f250c4a8 100644 --- a/cmd/kube-controller-manager/app/controllermanager.go +++ b/cmd/kube-controller-manager/app/controllermanager.go @@ -22,6 +22,7 @@ package app import ( "net" "net/http" + "net/http/pprof" "strconv" "time" @@ -61,7 +62,8 @@ type CMServer struct { NodeMilliCPU int64 NodeMemory resource.Quantity - KubeletConfig client.KubeletConfig + KubeletConfig client.KubeletConfig + EnableProfiling bool } // NewCMServer creates a new CMServer with a default config. @@ -108,6 +110,7 @@ func (s *CMServer) AddFlags(fs *pflag.FlagSet) { fs.Int64Var(&s.NodeMilliCPU, "node_milli_cpu", s.NodeMilliCPU, "The amount of MilliCPU provisioned on each node") fs.Var(resource.NewQuantityFlagValue(&s.NodeMemory), "node_memory", "The amount of memory (in bytes) provisioned on each node") client.BindKubeletClientConfigFlags(fs, &s.KubeletConfig) + fs.BoolVar(&s.EnableProfiling, "profiling", false, "Enable profiling via web interface host:port/debug/pprof/") } func (s *CMServer) verifyMinionFlags() { @@ -138,7 +141,15 @@ func (s *CMServer) Run(_ []string) error { glog.Fatalf("Invalid API configuration: %v", err) } - go http.ListenAndServe(net.JoinHostPort(s.Address.String(), strconv.Itoa(s.Port)), nil) + go func() { + if s.EnableProfiling { + mux := http.NewServeMux() + mux.HandleFunc("/debug/pprof/", pprof.Index) + mux.HandleFunc("/debug/pprof/profile", pprof.Profile) + mux.HandleFunc("/debug/pprof/symbol", pprof.Symbol) + } + http.ListenAndServe(net.JoinHostPort(s.Address.String(), strconv.Itoa(s.Port)), nil) + }() endpoints := service.NewEndpointController(kubeClient) go util.Forever(func() { endpoints.SyncServiceEndpoints() }, time.Second*10) diff --git a/cmd/kubernetes/kubernetes.go b/cmd/kubernetes/kubernetes.go index 802b59a8268cb..c80cfd35ac868 100644 --- a/cmd/kubernetes/kubernetes.go +++ b/cmd/kubernetes/kubernetes.go @@ -59,6 +59,7 @@ var ( nodeMilliCPU = flag.Int64("node_milli_cpu", 1000, "The amount of MilliCPU provisioned on each node") nodeMemory = flag.Int64("node_memory", 3*1024*1024*1024, "The amount of memory (in bytes) provisioned on each node") masterServiceNamespace = flag.String("master_service_namespace", api.NamespaceDefault, "The namespace from which the kubernetes master services should be injected into pods") + enableProfiling = flag.Bool("profiling", false, "Enable profiling via web interface host:port/debug/pprof/") ) type delegateHandler struct { @@ -92,6 +93,7 @@ func runApiServer(cl *client.Client, etcdClient tools.EtcdClient, addr net.IP, p }, EnableLogsSupport: false, EnableSwaggerSupport: true, + EnableProfiling: *enableProfiling, APIPrefix: "/api", Authorizer: apiserver.NewAlwaysAllowAuthorizer(), diff --git a/pkg/master/master.go b/pkg/master/master.go index b9dda880759a2..21dd5ada98de4 100644 --- a/pkg/master/master.go +++ b/pkg/master/master.go @@ -21,6 +21,7 @@ import ( "fmt" "net" "net/http" + "net/http/pprof" "net/url" rt "runtime" "strconv" @@ -80,6 +81,7 @@ type Config struct { EnableV1Beta3 bool // allow downstream consumers to disable the index route EnableIndex bool + EnableProfiling bool APIPrefix string CorsAllowedOriginList util.StringList Authenticator authenticator.Request @@ -132,6 +134,7 @@ type Master struct { enableLogsSupport bool enableUISupport bool enableSwaggerSupport bool + enableProfiling bool apiPrefix string corsAllowedOriginList util.StringList authenticator authenticator.Request @@ -286,6 +289,7 @@ func New(c *Config) *Master { enableLogsSupport: c.EnableLogsSupport, enableUISupport: c.EnableUISupport, enableSwaggerSupport: c.EnableSwaggerSupport, + enableProfiling: c.EnableProfiling, apiPrefix: c.APIPrefix, corsAllowedOriginList: c.CorsAllowedOriginList, authenticator: c.Authenticator, @@ -454,8 +458,11 @@ func (m *Master) init(c *Config) { ui.InstallSupport(m.muxHelper, m.enableSwaggerSupport) } - // TODO: install runtime/pprof handler - // See github.com/emicklei/go-restful/blob/master/examples/restful-cpuprofiler-service.go + if c.EnableProfiling { + m.mux.HandleFunc("/debug/pprof/", pprof.Index) + m.mux.HandleFunc("/debug/pprof/profile", pprof.Profile) + m.mux.HandleFunc("/debug/pprof/symbol", pprof.Symbol) + } handler := http.Handler(m.mux.(*http.ServeMux)) diff --git a/plugin/cmd/kube-scheduler/app/server.go b/plugin/cmd/kube-scheduler/app/server.go index 6f770492efa58..120c116ebc2cf 100644 --- a/plugin/cmd/kube-scheduler/app/server.go +++ b/plugin/cmd/kube-scheduler/app/server.go @@ -22,6 +22,7 @@ import ( "io/ioutil" "net" "net/http" + "net/http/pprof" "os" "strconv" @@ -47,6 +48,7 @@ type SchedulerServer struct { ClientConfig client.Config AlgorithmProvider string PolicyConfigFile string + EnableProfiling bool } // NewSchedulerServer creates a new SchedulerServer with default parameters @@ -66,6 +68,7 @@ func (s *SchedulerServer) AddFlags(fs *pflag.FlagSet) { client.BindClientConfigFlags(fs, &s.ClientConfig) fs.StringVar(&s.AlgorithmProvider, "algorithm_provider", s.AlgorithmProvider, "The scheduling algorithm provider to use") fs.StringVar(&s.PolicyConfigFile, "policy_config_file", s.PolicyConfigFile, "File with scheduler policy configuration") + fs.BoolVar(&s.EnableProfiling, "profiling", false, "Enable profiling via web interface host:port/debug/pprof/") } // Run runs the specified SchedulerServer. This should never exit. @@ -77,7 +80,15 @@ func (s *SchedulerServer) Run(_ []string) error { record.StartRecording(kubeClient.Events("")) - go http.ListenAndServe(net.JoinHostPort(s.Address.String(), strconv.Itoa(s.Port)), nil) + go func() { + if s.EnableProfiling { + mux := http.NewServeMux() + mux.HandleFunc("/debug/pprof/", pprof.Index) + mux.HandleFunc("/debug/pprof/profile", pprof.Profile) + mux.HandleFunc("/debug/pprof/symbol", pprof.Symbol) + } + http.ListenAndServe(net.JoinHostPort(s.Address.String(), strconv.Itoa(s.Port)), nil) + }() configFactory := factory.NewConfigFactory(kubeClient) config, err := s.createConfig(configFactory) diff --git a/test/integration/client_test.go b/test/integration/client_test.go index 3bb073e60c36d..b628a32e3403d 100644 --- a/test/integration/client_test.go +++ b/test/integration/client_test.go @@ -54,6 +54,7 @@ func TestClient(t *testing.T) { EtcdHelper: helper, KubeletClient: client.FakeKubeletClient{}, EnableLogsSupport: false, + EnableProfiling: true, EnableUISupport: false, APIPrefix: "/api", Authorizer: apiserver.NewAlwaysAllowAuthorizer(),