github.com/timstclair/heapster@v0.20.0-alpha1/metrics/processors/pod_based_enricher.go (about) 1 // Copyright 2015 Google Inc. All Rights Reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package processors 16 17 import ( 18 "net/url" 19 "time" 20 21 "github.com/golang/glog" 22 23 kube_config "k8s.io/heapster/common/kubernetes" 24 "k8s.io/heapster/metrics/util" 25 26 "k8s.io/heapster/metrics/core" 27 kube_api "k8s.io/kubernetes/pkg/api" 28 "k8s.io/kubernetes/pkg/client/cache" 29 kube_client "k8s.io/kubernetes/pkg/client/unversioned" 30 "k8s.io/kubernetes/pkg/fields" 31 "k8s.io/kubernetes/pkg/labels" 32 ) 33 34 type PodBasedEnricher struct { 35 podLister *cache.StoreToPodLister 36 reflector *cache.Reflector 37 } 38 39 func (this *PodBasedEnricher) Name() string { 40 return "pod_based_enricher" 41 } 42 43 func (this *PodBasedEnricher) Process(batch *core.DataBatch) (*core.DataBatch, error) { 44 pods, err := this.podLister.List(labels.Everything()) 45 if err != nil { 46 return nil, err 47 } 48 for _, pod := range pods { 49 addPodInfo(pod, batch) 50 } 51 return batch, nil 52 } 53 54 func addPodInfo(pod *kube_api.Pod, batch *core.DataBatch) { 55 podMs, found := batch.MetricSets[core.PodKey(pod.Namespace, pod.Name)] 56 if !found { 57 // create pod stub. 58 glog.V(2).Infof("Pod not found: %s", core.PodKey(pod.Namespace, pod.Name)) 59 podMs = &core.MetricSet{ 60 MetricValues: make(map[string]core.MetricValue), 61 Labels: map[string]string{ 62 core.LabelMetricSetType.Key: core.MetricSetTypePod, 63 core.LabelNamespaceName.Key: pod.Namespace, 64 core.LabelPodNamespace.Key: pod.Namespace, 65 core.LabelPodName.Key: pod.Name, 66 }, 67 } 68 batch.MetricSets[core.PodKey(pod.Namespace, pod.Name)] = podMs 69 } 70 // Add UID to pod 71 podMs.Labels[core.LabelPodId.Key] = string(pod.UID) 72 podMs.Labels[core.LabelLabels.Key] = util.LabelsToString(pod.Labels, ",") 73 74 // Add cpu/mem requests and limits to containers 75 for _, container := range pod.Spec.Containers { 76 requests := container.Resources.Requests 77 limits := container.Resources.Limits 78 79 cpuRequestMilli := int64(0) 80 memRequest := int64(0) 81 cpuLimitMilli := int64(0) 82 memLimit := int64(0) 83 84 if val, found := requests[kube_api.ResourceCPU]; found { 85 cpuRequestMilli = val.MilliValue() 86 } 87 if val, found := requests[kube_api.ResourceMemory]; found { 88 memRequest = val.Value() 89 } 90 91 if val, found := limits[kube_api.ResourceCPU]; found { 92 cpuLimitMilli = val.MilliValue() 93 } 94 if val, found := limits[kube_api.ResourceMemory]; found { 95 memLimit = val.Value() 96 } 97 98 containerKey := core.PodContainerKey(pod.Namespace, pod.Name, container.Name) 99 containerMs, found := batch.MetricSets[containerKey] 100 if !found { 101 glog.V(2).Infof("Container %s not found, creating a stub", containerKey) 102 containerMs = &core.MetricSet{ 103 MetricValues: make(map[string]core.MetricValue), 104 Labels: map[string]string{ 105 core.LabelMetricSetType.Key: core.MetricSetTypePodContainer, 106 core.LabelNamespaceName.Key: pod.Namespace, 107 core.LabelPodNamespace.Key: pod.Namespace, 108 core.LabelPodName.Key: pod.Name, 109 core.LabelContainerName.Key: container.Name, 110 core.LabelContainerBaseImage.Key: container.Image, 111 }, 112 } 113 batch.MetricSets[containerKey] = containerMs 114 } 115 116 containerMs.MetricValues[core.MetricCpuRequest.Name] = intValue(cpuRequestMilli) 117 containerMs.MetricValues[core.MetricMemoryRequest.Name] = intValue(memRequest) 118 containerMs.MetricValues[core.MetricCpuLimit.Name] = intValue(cpuLimitMilli) 119 containerMs.MetricValues[core.MetricMemoryLimit.Name] = intValue(memLimit) 120 121 containerMs.Labels[core.LabelPodId.Key] = string(pod.UID) 122 containerMs.Labels[core.LabelLabels.Key] = util.LabelsToString(pod.Labels, ",") 123 } 124 } 125 126 func intValue(value int64) core.MetricValue { 127 return core.MetricValue{ 128 IntValue: value, 129 MetricType: core.MetricGauge, 130 ValueType: core.ValueInt64, 131 } 132 } 133 134 func NewPodBasedEnricher(url *url.URL) (*PodBasedEnricher, error) { 135 kubeConfig, err := kube_config.GetKubeClientConfig(url) 136 if err != nil { 137 return nil, err 138 } 139 kubeClient := kube_client.NewOrDie(kubeConfig) 140 141 // watch nodes 142 lw := cache.NewListWatchFromClient(kubeClient, "pods", kube_api.NamespaceAll, fields.Everything()) 143 podLister := &cache.StoreToPodLister{Store: cache.NewStore(cache.MetaNamespaceKeyFunc)} 144 reflector := cache.NewReflector(lw, &kube_api.Pod{}, podLister.Store, time.Hour) 145 reflector.Run() 146 147 return &PodBasedEnricher{ 148 podLister: podLister, 149 reflector: reflector, 150 }, nil 151 }