From 037cfd257fcf2d277087410e1a64d1fc37aa4910 Mon Sep 17 00:00:00 2001 From: Nan Deng Date: Thu, 19 Jun 2014 01:26:23 +0000 Subject: [PATCH] add /containerStats --- pkg/api/types.go | 14 +++++++++++ pkg/kubelet/kubelet.go | 45 ++++++++++++++++++++++++++++++++++- pkg/kubelet/kubelet_server.go | 29 ++++++++++++++++++++++ 3 files changed, 87 insertions(+), 1 deletion(-) diff --git a/pkg/api/types.go b/pkg/api/types.go index 0c7ea04a756..a06cb308302 100644 --- a/pkg/api/types.go +++ b/pkg/api/types.go @@ -66,6 +66,20 @@ type Container struct { VolumeMounts []VolumeMount `yaml:"volumeMounts,omitempty" json:"volumeMounts,omitempty"` } +// Percentile represents a pair which contains a percentage from 0 to 100 and +// its corresponding value. +type Percentile struct { + Percentage int `json:"percentage,omitempty"` + Value uint64 `json:"value,omitempty"` +} + +// ContainerStats represents statistical information of a container +type ContainerStats struct { + CpuUsagePercentiles []Percentile `json:"cpu_usage_percentiles,omitempty"` + MemoryUsagePercentiles []Percentile `json:"memory_usage_percentiles,omitempty"` + MaxMemoryUsage uint64 `json:"max_memory_usage,omitempty"` +} + // Event is the representation of an event logged to etcd backends type Event struct { Event string `json:"event,omitempty"` diff --git a/pkg/kubelet/kubelet.go b/pkg/kubelet/kubelet.go index 56d9d3b5433..8cb6269b478 100644 --- a/pkg/kubelet/kubelet.go +++ b/pkg/kubelet/kubelet.go @@ -34,8 +34,8 @@ import ( "github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/util" + "github.com/GoogleCloudPlatform/kubernetes/third_party/src/github.com/fsouza/go-dockerclient" "github.com/coreos/go-etcd/etcd" - "github.com/fsouza/go-dockerclient" "github.com/google/cadvisor/info" "gopkg.in/v1/yaml" ) @@ -650,3 +650,46 @@ func (kl *Kubelet) GetContainerInfo(name string) (string, error) { data, err := json.Marshal(info) return string(data), err } + +func (kl *Kubelet) GetContainerStats(name string) (*api.ContainerStats, error) { + if kl.CadvisorClient == nil { + return nil, nil + } + id, found, err := kl.GetContainerID(name) + if err != nil { + return nil, err + } + if !found { + return nil, nil + } + + path := fmt.Sprintf("/docker/%v", id) + info, err := kl.CadvisorClient.ContainerInfo(path) + + if err != nil { + return nil, err + } + if info.StatsPercentiles == nil { + return nil, nil + } + + ret := new(api.ContainerStats) + ret.MaxMemoryUsage = info.StatsPercentiles.MaxMemoryUsage + if len(info.StatsPercentiles.CpuUsagePercentiles) > 0 { + percentiles := make([]api.Percentile, len(info.StatsPercentiles.CpuUsagePercentiles)) + for i, p := range info.StatsPercentiles.CpuUsagePercentiles { + percentiles[i].Percentage = p.Percentage + percentiles[i].Value = p.Value + } + ret.CpuUsagePercentiles = percentiles + } + if len(info.StatsPercentiles.MemoryUsagePercentiles) > 0 { + percentiles := make([]api.Percentile, len(info.StatsPercentiles.MemoryUsagePercentiles)) + for i, p := range info.StatsPercentiles.MemoryUsagePercentiles { + percentiles[i].Percentage = p.Percentage + percentiles[i].Value = p.Value + } + ret.MemoryUsagePercentiles = percentiles + } + return ret, nil +} diff --git a/pkg/kubelet/kubelet_server.go b/pkg/kubelet/kubelet_server.go index 9eaf5b8e44f..5c65df1bc52 100644 --- a/pkg/kubelet/kubelet_server.go +++ b/pkg/kubelet/kubelet_server.go @@ -17,6 +17,7 @@ limitations under the License. package kubelet import ( + "encoding/json" "fmt" "io/ioutil" "net/http" @@ -35,6 +36,7 @@ type KubeletServer struct { // For testablitiy. type kubeletInterface interface { GetContainerID(name string) (string, bool, error) + GetContainerStats(name string) (*api.ContainerStats, error) GetContainerInfo(name string) (string, error) } @@ -64,6 +66,33 @@ func (s *KubeletServer) ServeHTTP(w http.ResponseWriter, req *http.Request) { return } s.UpdateChannel <- manifest + case u.Path == "/containerStats": + container := u.Query().Get("container") + if len(container) == 0 { + w.WriteHeader(http.StatusBadRequest) + fmt.Fprint(w, "Missing container query arg.") + return + } + stats, err := s.Kubelet.GetContainerStats(container) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + fmt.Fprintf(w, "Internal Error: %#v", err) + return + } + if stats == nil { + w.WriteHeader(http.StatusOK) + fmt.Fprint(w, "{}") + return + } + w.Header().Add("Content-type", "application/json") + w.WriteHeader(http.StatusOK) + encoder := json.NewEncoder(w) + err = encoder.Encode(stats) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + fmt.Fprintf(w, "Internal Error: %#v", err) + return + } case u.Path == "/containerInfo": container := u.Query().Get("container") if len(container) == 0 {