Add pprof trace support

Add pprof trace support and --enable-contention-profiling to those
components that don't already have it.
pull/6/head
Andy Goldstein 2017-02-28 13:43:08 -05:00
parent 302aab9ba2
commit b011529d8a
16 changed files with 47 additions and 9 deletions

View File

@ -22,6 +22,7 @@ import (
"net/http"
"net/http/pprof"
"os"
goruntime "runtime"
"strconv"
"time"
@ -111,6 +112,10 @@ func Run(s *options.CloudControllerManagerServer, cloud cloudprovider.Interface)
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)
if s.EnableContentionProfiling {
goruntime.SetBlockProfileRate(1)
}
}
configz.InstallHandler(mux)
mux.Handle("/metrics", prometheus.Handler())

View File

@ -75,6 +75,7 @@ func (s *CloudControllerManagerServer) AddFlags(fs *pflag.FlagSet) {
fs.DurationVar(&s.RouteReconciliationPeriod.Duration, "route-reconciliation-period", s.RouteReconciliationPeriod.Duration, "The period for reconciling routes created for Nodes by cloud provider.")
fs.BoolVar(&s.ConfigureCloudRoutes, "configure-cloud-routes", true, "Should CIDRs allocated by allocate-node-cidrs be configured on the cloud provider.")
fs.BoolVar(&s.EnableProfiling, "profiling", true, "Enable profiling via web interface host:port/debug/pprof/")
fs.BoolVar(&s.EnableContentionProfiling, "contention-profiling", false, "Enable lock contention profiling, if profiling is enabled")
fs.StringVar(&s.ClusterCIDR, "cluster-cidr", s.ClusterCIDR, "CIDR Range for Pods in cluster.")
fs.BoolVar(&s.AllocateNodeCIDRs, "allocate-node-cidrs", false, "Should CIDRs for Pods be allocated and set on the cloud provider.")
fs.StringVar(&s.Master, "master", s.Master, "The address of the Kubernetes API server (overrides any value in kubeconfig)")

View File

@ -28,6 +28,7 @@ import (
"net/http"
"net/http/pprof"
"os"
goruntime "runtime"
"strconv"
"time"
@ -135,6 +136,10 @@ func Run(s *options.CMServer) error {
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)
if s.EnableContentionProfiling {
goruntime.SetBlockProfileRate(1)
}
}
configz.InstallHandler(mux)
mux.Handle("/metrics", prometheus.Handler())

View File

@ -178,6 +178,7 @@ func (s *CMServer) AddFlags(fs *pflag.FlagSet, allControllers []string, disabled
fs.StringVar(&s.ClusterSigningKeyFile, "cluster-signing-key-file", s.ClusterSigningKeyFile, "Filename containing a PEM-encoded RSA or ECDSA private key used to sign cluster-scoped certificates")
fs.StringVar(&s.ApproveAllKubeletCSRsForGroup, "insecure-experimental-approve-all-kubelet-csrs-for-group", s.ApproveAllKubeletCSRsForGroup, "The group for which the controller-manager will auto approve all CSRs for kubelet client certificates.")
fs.BoolVar(&s.EnableProfiling, "profiling", true, "Enable profiling via web interface host:port/debug/pprof/")
fs.BoolVar(&s.EnableContentionProfiling, "contention-profiling", false, "Enable lock contention profiling, if profiling is enabled")
fs.StringVar(&s.ClusterName, "cluster-name", s.ClusterName, "The instance prefix for the cluster")
fs.StringVar(&s.ClusterCIDR, "cluster-cidr", s.ClusterCIDR, "CIDR Range for Pods in cluster.")
fs.StringVar(&s.ServiceCIDR, "service-cluster-ip-range", s.ServiceCIDR, "CIDR Range for Services in cluster.")

View File

@ -150,6 +150,7 @@ func (s *KubeletServer) AddFlags(fs *pflag.FlagSet) {
fs.Int32Var(&s.EventBurst, "event-burst", s.EventBurst, "Maximum size of a bursty event records, temporarily allows event records to burst to this number, while still not exceeding event-qps. Only used if --event-qps > 0")
fs.BoolVar(&s.RunOnce, "runonce", s.RunOnce, "If true, exit after spawning pods from local manifests or remote urls. Exclusive with --api-servers, and --enable-server")
fs.BoolVar(&s.EnableDebuggingHandlers, "enable-debugging-handlers", s.EnableDebuggingHandlers, "Enables server endpoints for log collection and local running of containers and commands")
fs.BoolVar(&s.EnableContentionProfiling, "contention-profiling", false, "Enable lock contention profiling, if profiling is enabled")
fs.DurationVar(&s.MinimumGCAge.Duration, "minimum-container-ttl-duration", s.MinimumGCAge.Duration, "Minimum age for a finished container before it is garbage collected. Examples: '300ms', '10s' or '2h45m'")
fs.MarkDeprecated("minimum-container-ttl-duration", "Use --eviction-hard or --eviction-soft instead. Will be removed in a future version.")
fs.Int32Var(&s.MaxPerPodContainerCount, "maximum-dead-containers-per-container", s.MaxPerPodContainerCount, "Maximum number of old instances to retain per container. Each container takes up some disk space. Default: 1.")

View File

@ -878,7 +878,7 @@ func startKubelet(k kubelet.KubeletBootstrap, podCfg *config.PodConfig, kubeCfg
// start the kubelet server
if kubeCfg.EnableServer {
go wait.Until(func() {
k.ListenAndServe(net.ParseIP(kubeCfg.Address), uint(kubeCfg.Port), kubeDeps.TLSOptions, kubeDeps.Auth, kubeCfg.EnableDebuggingHandlers)
k.ListenAndServe(net.ParseIP(kubeCfg.Address), uint(kubeCfg.Port), kubeDeps.TLSOptions, kubeDeps.Auth, kubeCfg.EnableDebuggingHandlers, kubeCfg.EnableContentionProfiling)
}, 0, wait.NeverStop)
}
if kubeCfg.ReadOnlyPort > 0 {

View File

@ -24,6 +24,7 @@ import (
"net"
"net/http"
"net/http/pprof"
goruntime "runtime"
"strconv"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@ -131,6 +132,10 @@ func Run(s *options.CMServer) error {
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)
if s.EnableContentionProfiling {
goruntime.SetBlockProfileRate(1)
}
}
mux.Handle("/metrics", prometheus.Handler())

View File

@ -64,6 +64,8 @@ type ControllerManagerConfiguration struct {
APIServerBurst int `json:"federatedAPIBurst"`
// enableProfiling enables profiling via web interface host:port/debug/pprof/
EnableProfiling bool `json:"enableProfiling"`
// enableContentionProfiling enables lock contention profiling, if enableProfiling is true.
EnableContentionProfiling bool `json:"enableContentionProfiling"`
// leaderElection defines the configuration of leader election client.
LeaderElection componentconfig.LeaderElectionConfiguration `json:"leaderElection"`
// contentType is contentType of requests sent to apiserver.
@ -115,6 +117,7 @@ func (s *CMServer) AddFlags(fs *pflag.FlagSet) {
fs.IntVar(&s.ConcurrentReplicaSetSyncs, "concurrent-replicaset-syncs", s.ConcurrentReplicaSetSyncs, "The number of ReplicaSets syncing operations that will be done concurrently. Larger number = faster endpoint updating, but more CPU (and network) load")
fs.DurationVar(&s.ClusterMonitorPeriod.Duration, "cluster-monitor-period", s.ClusterMonitorPeriod.Duration, "The period for syncing ClusterStatus in ClusterController.")
fs.BoolVar(&s.EnableProfiling, "profiling", true, "Enable profiling via web interface host:port/debug/pprof/")
fs.BoolVar(&s.EnableContentionProfiling, "contention-profiling", false, "Enable lock contention profiling, if profiling is enabled")
fs.StringVar(&s.Master, "master", s.Master, "The address of the federation API server (overrides any value in kubeconfig)")
fs.StringVar(&s.Kubeconfig, "kubeconfig", s.Kubeconfig, "Path to kubeconfig file with authorization and master location information.")
fs.StringVar(&s.ContentType, "kube-api-content-type", s.ContentType, "ContentType of requests sent to apiserver. Passing application/vnd.kubernetes.protobuf is an experimental feature now.")

View File

@ -210,6 +210,8 @@ type KubeletConfiguration struct {
// enableDebuggingHandlers enables server endpoints for log collection
// and local running of containers and commands
EnableDebuggingHandlers bool
// enableContentionProfiling enables lock contention profiling, if enableDebuggingHandlers is true.
EnableContentionProfiling bool
// minimumGCAge is the minimum age for a finished container before it is
// garbage collected.
MinimumGCAge metav1.Duration
@ -757,6 +759,8 @@ type KubeControllerManagerConfiguration struct {
ApproveAllKubeletCSRsForGroup string
// enableProfiling enables profiling via web interface host:port/debug/pprof/
EnableProfiling bool
// enableContentionProfiling enables lock contention profiling, if enableProfiling is true.
EnableContentionProfiling bool
// clusterName is the instance prefix for the cluster.
ClusterName string
// clusterCIDR is CIDR Range for Pods in cluster.

View File

@ -264,6 +264,8 @@ type KubeletConfiguration struct {
// enableDebuggingHandlers enables server endpoints for log collection
// and local running of containers and commands
EnableDebuggingHandlers *bool `json:"enableDebuggingHandlers"`
// enableContentionProfiling enables lock contention profiling, if enableDebuggingHandlers is true.
EnableContentionProfiling bool `json:"enableContentionProfiling"`
// minimumGCAge is the minimum age for a finished container before it is
// garbage collected.
MinimumGCAge metav1.Duration `json:"minimumGCAge"`

View File

@ -180,7 +180,7 @@ type KubeletBootstrap interface {
GetConfiguration() componentconfig.KubeletConfiguration
BirthCry()
StartGarbageCollection()
ListenAndServe(address net.IP, port uint, tlsOptions *server.TLSOptions, auth server.AuthInterface, enableDebuggingHandlers bool)
ListenAndServe(address net.IP, port uint, tlsOptions *server.TLSOptions, auth server.AuthInterface, enableDebuggingHandlers, enableContentionProfiling bool)
ListenAndServeReadOnly(address net.IP, port uint)
Run(<-chan kubetypes.PodUpdate)
RunOnce(<-chan kubetypes.PodUpdate) ([]RunPodResult, error)
@ -2120,8 +2120,8 @@ func (kl *Kubelet) ResyncInterval() time.Duration {
}
// ListenAndServe runs the kubelet HTTP server.
func (kl *Kubelet) ListenAndServe(address net.IP, port uint, tlsOptions *server.TLSOptions, auth server.AuthInterface, enableDebuggingHandlers bool) {
server.ListenAndServeKubeletServer(kl, kl.resourceAnalyzer, address, port, tlsOptions, auth, enableDebuggingHandlers, kl.containerRuntime, kl.criHandler)
func (kl *Kubelet) ListenAndServe(address net.IP, port uint, tlsOptions *server.TLSOptions, auth server.AuthInterface, enableDebuggingHandlers, enableContentionProfiling bool) {
server.ListenAndServeKubeletServer(kl, kl.resourceAnalyzer, address, port, tlsOptions, auth, enableDebuggingHandlers, enableContentionProfiling, kl.containerRuntime, kl.criHandler)
}
// ListenAndServeReadOnly runs the kubelet HTTP server in read-only mode.

View File

@ -25,6 +25,7 @@ import (
"net/http/pprof"
"net/url"
"reflect"
goruntime "runtime"
"strconv"
"strings"
"time"
@ -119,11 +120,12 @@ func ListenAndServeKubeletServer(
port uint,
tlsOptions *TLSOptions,
auth AuthInterface,
enableDebuggingHandlers bool,
enableDebuggingHandlers,
enableContentionProfiling bool,
runtime kubecontainer.Runtime,
criHandler http.Handler) {
glog.Infof("Starting to listen on %s:%d", address, port)
handler := NewServer(host, resourceAnalyzer, auth, enableDebuggingHandlers, runtime, criHandler)
handler := NewServer(host, resourceAnalyzer, auth, enableDebuggingHandlers, enableContentionProfiling, runtime, criHandler)
s := &http.Server{
Addr: net.JoinHostPort(address.String(), strconv.FormatUint(uint64(port), 10)),
Handler: &handler,
@ -140,7 +142,7 @@ func ListenAndServeKubeletServer(
// ListenAndServeKubeletReadOnlyServer initializes a server to respond to HTTP network requests on the Kubelet.
func ListenAndServeKubeletReadOnlyServer(host HostInterface, resourceAnalyzer stats.ResourceAnalyzer, address net.IP, port uint, runtime kubecontainer.Runtime) {
glog.V(1).Infof("Starting to listen read-only on %s:%d", address, port)
s := NewServer(host, resourceAnalyzer, nil, false, runtime, nil)
s := NewServer(host, resourceAnalyzer, nil, false, false, runtime, nil)
server := &http.Server{
Addr: net.JoinHostPort(address.String(), strconv.FormatUint(uint64(port), 10)),
@ -192,7 +194,8 @@ func NewServer(
host HostInterface,
resourceAnalyzer stats.ResourceAnalyzer,
auth AuthInterface,
enableDebuggingHandlers bool,
enableDebuggingHandlers,
enableContentionProfiling bool,
runtime kubecontainer.Runtime,
criHandler http.Handler) Server {
server := Server{
@ -208,6 +211,9 @@ func NewServer(
server.InstallDefaultHandlers()
if enableDebuggingHandlers {
server.InstallDebuggingHandlers(criHandler)
if enableContentionProfiling {
goruntime.SetBlockProfileRate(1)
}
}
return server
}
@ -381,6 +387,8 @@ func (s *Server) InstallDebuggingHandlers(criHandler http.Handler) {
pprof.Symbol(resp, req.Request)
case "cmdline":
pprof.Cmdline(resp, req.Request)
case "trace":
pprof.Trace(resp, req.Request)
default:
pprof.Index(resp, req.Request)
}

View File

@ -240,6 +240,7 @@ func newServerTest() *serverTestFramework {
stats.NewResourceAnalyzer(fw.fakeKubelet, time.Minute, &kubecontainertesting.FakeRuntime{}),
fw.fakeAuth,
true,
false,
&kubecontainertesting.Mock{},
fw.criHandler)
fw.serverUnderTest = &server

View File

@ -146,6 +146,7 @@ func startHTTP(s *options.SchedulerServer) {
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)
if s.EnableContentionProfiling {
goruntime.SetBlockProfileRate(1)
}

View File

@ -42,7 +42,7 @@ func (o *FeatureOptions) AddFlags(fs *pflag.FlagSet) {
fs.BoolVar(&o.EnableProfiling, "profiling", o.EnableProfiling,
"Enable profiling via web interface host:port/debug/pprof/")
fs.BoolVar(&o.EnableContentionProfiling, "contention-profiling", o.EnableContentionProfiling,
"Enable contention profiling. Requires --profiling to be set to work.")
"Enable lock contention profiling, if profiling is enabled")
fs.BoolVar(&o.EnableSwaggerUI, "enable-swagger-ui", o.EnableSwaggerUI,
"Enables swagger ui on the apiserver at /swagger-ui")
}

View File

@ -30,4 +30,5 @@ func (d Profiling) Install(c *mux.APIContainer) {
c.UnlistedRoutes.HandleFunc("/debug/pprof/", pprof.Index)
c.UnlistedRoutes.HandleFunc("/debug/pprof/profile", pprof.Profile)
c.UnlistedRoutes.HandleFunc("/debug/pprof/symbol", pprof.Symbol)
c.UnlistedRoutes.HandleFunc("/debug/pprof/trace", pprof.Trace)
}