diff --git a/cluster/addons/cluster-monitoring/heapster-controller.yaml b/cluster/addons/cluster-monitoring/heapster-controller.yaml index 6f5d18671bf..616798cda58 100644 --- a/cluster/addons/cluster-monitoring/heapster-controller.yaml +++ b/cluster/addons/cluster-monitoring/heapster-controller.yaml @@ -1,9 +1,9 @@ apiVersion: v1beta1 id: monitoring-heapster-controller kind: ReplicationController -desiredState: +desiredState: replicas: 1 - replicaSelector: + replicaSelector: name: heapster podTemplate: desiredState: @@ -13,11 +13,13 @@ desiredState: containers: - name: heapster image: gcr.io/google_containers/heapster:v0.10.0 - env: + env: - name: "INFLUXDB_HOST" value: "monitoring-influxdb" - name: "SINK" value: "influxdb" + - name: "FLAGS" + value: "--kubelet_port=10255" volumeMounts: - name: ssl-certs mountPath: /etc/ssl/certs @@ -27,10 +29,10 @@ desiredState: source: hostDir: path: /etc/ssl/certs - labels: + labels: name: heapster uses: monitoring-influxdb kubernetes.io/cluster-service: "true" -labels: +labels: name: heapster kubernetes.io/cluster-service: "true" diff --git a/cmd/kubelet/app/server.go b/cmd/kubelet/app/server.go index e841b108777..3d136bcc32c 100644 --- a/cmd/kubelet/app/server.go +++ b/cmd/kubelet/app/server.go @@ -61,6 +61,7 @@ type KubeletServer struct { EnableServer bool Address util.IP Port uint + ReadOnlyPort uint HostnameOverride string PodInfraContainerImage string DockerEndpoint string @@ -98,12 +99,13 @@ type KubeletServer struct { // NewKubeletServer will create a new KubeletServer with default values. func NewKubeletServer() *KubeletServer { return &KubeletServer{ - SyncFrequency: 10 * time.Second, - FileCheckFrequency: 20 * time.Second, - HTTPCheckFrequency: 20 * time.Second, - EnableServer: true, - Address: util.IP(net.ParseIP("0.0.0.0")), - Port: ports.KubeletPort, + SyncFrequency: 10 * time.Second, + FileCheckFrequency: 20 * time.Second, + HTTPCheckFrequency: 20 * time.Second, + EnableServer: true, + Address: util.IP(net.ParseIP("0.0.0.0")), + Port: ports.KubeletPort, + ReadOnlyPort: ports.KubeletReadOnlyPort, PodInfraContainerImage: kubelet.PodInfraContainerImage, RootDirectory: defaultRootDir, RegistryBurst: 10, @@ -135,6 +137,7 @@ func (s *KubeletServer) AddFlags(fs *pflag.FlagSet) { fs.BoolVar(&s.EnableServer, "enable_server", s.EnableServer, "Enable the info server") fs.Var(&s.Address, "address", "The IP address for the info server to serve on (set to 0.0.0.0 for all interfaces)") fs.UintVar(&s.Port, "port", s.Port, "The port for the info server to serve on") + fs.UintVar(&s.ReadOnlyPort, "read_only_port", s.ReadOnlyPort, "The read-only port for the info server to serve on (set to 0 to disable)") fs.StringVar(&s.TLSCertFile, "tls_cert_file", s.TLSCertFile, ""+ "File containing x509 Certificate for HTTPS. (CA cert, if any, concatenated after server cert). "+ "If --tls_cert_file and --tls_private_key_file are not provided, a self-signed certificate and key "+ @@ -248,6 +251,7 @@ func (s *KubeletServer) Run(_ []string) error { ClusterDNS: s.ClusterDNS, Runonce: s.RunOnce, Port: s.Port, + ReadOnlyPort: s.ReadOnlyPort, CadvisorInterface: cadvisorInterface, EnableServer: s.EnableServer, EnableDebuggingHandlers: s.EnableDebuggingHandlers, @@ -414,6 +418,11 @@ func startKubelet(k *kubelet.Kubelet, podCfg *config.PodConfig, kc *KubeletConfi kubelet.ListenAndServeKubeletServer(k, net.IP(kc.Address), kc.Port, kc.TLSOptions, kc.EnableDebuggingHandlers) }, 0) } + if kc.ReadOnlyPort > 0 { + go util.Forever(func() { + kubelet.ListenAndServeKubeletReadOnlyServer(k, net.IP(kc.Address), kc.ReadOnlyPort) + }, 0) + } } func makePodSourceConfig(kc *KubeletConfig) *config.PodConfig { @@ -466,6 +475,7 @@ type KubeletConfig struct { EnableServer bool EnableDebuggingHandlers bool Port uint + ReadOnlyPort uint Runonce bool MasterServiceNamespace string VolumePlugins []volume.VolumePlugin diff --git a/pkg/kubelet/server.go b/pkg/kubelet/server.go index d1a68f1b162..3eca3ce1e20 100644 --- a/pkg/kubelet/server.go +++ b/pkg/kubelet/server.go @@ -76,6 +76,24 @@ func ListenAndServeKubeletServer(host HostInterface, address net.IP, port uint, } } +// ListenAndServeKubeletReadOnlyServer initializes a server to respond to HTTP network requests on the Kubelet. +func ListenAndServeKubeletReadOnlyServer(host HostInterface, address net.IP, port uint) { + glog.V(1).Infof("Starting to listen read-only on %s:%d", address, port) + s := &Server{host, http.NewServeMux()} + healthz.InstallHandler(s.mux) + s.mux.HandleFunc("/stats/", s.handleStats) + s.mux.Handle("/metrics", prometheus.Handler()) + + server := &http.Server{ + Addr: net.JoinHostPort(address.String(), strconv.FormatUint(uint64(port), 10)), + Handler: s, + ReadTimeout: 5 * time.Minute, + WriteTimeout: 5 * time.Minute, + MaxHeaderBytes: 1 << 20, + } + glog.Fatal(server.ListenAndServe()) +} + // HostInterface contains all the kubelet methods required by the server. // For testablitiy. type HostInterface interface { diff --git a/pkg/master/ports/ports.go b/pkg/master/ports/ports.go index 5a29409c3aa..12ba851a896 100644 --- a/pkg/master/ports/ports.go +++ b/pkg/master/ports/ports.go @@ -32,4 +32,10 @@ const ( // ControllerManagerPort is the default port for the controller manager status server. // May be overridden by a flag at startup. ControllerManagerPort = 10252 + // KubeletReadOnlyPort exposes basic read-only services from the kubelet. + // May be overridden by a flag at startup. + // This is necessary for heapster to collect monitoring stats from the kubelet + // until heapster can transition to using the SSL endpoint. + // TODO(roberthbailey): Remove this once we have a better solution for heapster. + KubeletReadOnlyPort = 10255 )