github.com/jonaz/heapster@v1.3.0-beta.0.0.20170208112634-cd3c15ca3d29/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  	"fmt"
    19  
    20  	"github.com/golang/glog"
    21  
    22  	"k8s.io/heapster/metrics/util"
    23  
    24  	"k8s.io/heapster/metrics/core"
    25  	kube_api "k8s.io/kubernetes/pkg/api"
    26  	"k8s.io/kubernetes/pkg/client/cache"
    27  )
    28  
    29  type PodBasedEnricher struct {
    30  	podLister *cache.StoreToPodLister
    31  }
    32  
    33  func (this *PodBasedEnricher) Name() string {
    34  	return "pod_based_enricher"
    35  }
    36  
    37  func (this *PodBasedEnricher) Process(batch *core.DataBatch) (*core.DataBatch, error) {
    38  	newMs := make(map[string]*core.MetricSet, len(batch.MetricSets))
    39  	for k, v := range batch.MetricSets {
    40  		switch v.Labels[core.LabelMetricSetType.Key] {
    41  		case core.MetricSetTypePod:
    42  			namespace := v.Labels[core.LabelNamespaceName.Key]
    43  			podName := v.Labels[core.LabelPodName.Key]
    44  			pod, err := this.getPod(namespace, podName)
    45  			if err != nil {
    46  				glog.V(3).Infof("Failed to get pod %s from cache: %v", core.PodKey(namespace, podName), err)
    47  				continue
    48  			}
    49  			addPodInfo(k, v, pod, batch, newMs)
    50  		case core.MetricSetTypePodContainer:
    51  			namespace := v.Labels[core.LabelNamespaceName.Key]
    52  			podName := v.Labels[core.LabelPodName.Key]
    53  			pod, err := this.getPod(namespace, podName)
    54  			if err != nil {
    55  				glog.V(3).Infof("Failed to get pod %s from cache: %v", core.PodKey(namespace, podName), err)
    56  				continue
    57  			}
    58  			addContainerInfo(k, v, pod, batch, newMs)
    59  		}
    60  	}
    61  	for k, v := range newMs {
    62  		batch.MetricSets[k] = v
    63  	}
    64  	return batch, nil
    65  }
    66  
    67  func (this *PodBasedEnricher) getPod(namespace, name string) (*kube_api.Pod, error) {
    68  	pod, err := this.podLister.Pods(namespace).Get(name)
    69  	if err != nil {
    70  		return nil, err
    71  	}
    72  	if pod == nil {
    73  		return nil, fmt.Errorf("cannot find pod definition")
    74  	}
    75  	return pod, nil
    76  }
    77  
    78  func addContainerInfo(key string, containerMs *core.MetricSet, pod *kube_api.Pod, batch *core.DataBatch, newMs map[string]*core.MetricSet) {
    79  	for _, container := range pod.Spec.Containers {
    80  		if key == core.PodContainerKey(pod.Namespace, pod.Name, container.Name) {
    81  			updateContainerResourcesAndLimits(containerMs, container)
    82  			if _, ok := containerMs.Labels[core.LabelContainerBaseImage.Key]; !ok {
    83  				containerMs.Labels[core.LabelContainerBaseImage.Key] = container.Image
    84  			}
    85  			break
    86  		}
    87  	}
    88  
    89  	containerMs.Labels[core.LabelPodId.Key] = string(pod.UID)
    90  	containerMs.Labels[core.LabelLabels.Key] = util.LabelsToString(pod.Labels)
    91  
    92  	namespace := containerMs.Labels[core.LabelNamespaceName.Key]
    93  	podName := containerMs.Labels[core.LabelPodName.Key]
    94  
    95  	podKey := core.PodKey(namespace, podName)
    96  	_, oldfound := batch.MetricSets[podKey]
    97  	if !oldfound {
    98  		_, newfound := newMs[podKey]
    99  		if !newfound {
   100  			glog.V(2).Infof("Pod %s not found, creating a stub", podKey)
   101  			podMs := &core.MetricSet{
   102  				MetricValues: make(map[string]core.MetricValue),
   103  				Labels: map[string]string{
   104  					core.LabelMetricSetType.Key: core.MetricSetTypePod,
   105  					core.LabelNamespaceName.Key: namespace,
   106  					core.LabelPodNamespace.Key:  namespace,
   107  					core.LabelPodName.Key:       podName,
   108  					core.LabelNodename.Key:      containerMs.Labels[core.LabelNodename.Key],
   109  					core.LabelHostname.Key:      containerMs.Labels[core.LabelHostname.Key],
   110  					core.LabelHostID.Key:        containerMs.Labels[core.LabelHostID.Key],
   111  				},
   112  			}
   113  			newMs[podKey] = podMs
   114  			addPodInfo(podKey, podMs, pod, batch, newMs)
   115  		}
   116  	}
   117  }
   118  
   119  func addPodInfo(key string, podMs *core.MetricSet, pod *kube_api.Pod, batch *core.DataBatch, newMs map[string]*core.MetricSet) {
   120  
   121  	// Add UID to pod
   122  	podMs.Labels[core.LabelPodId.Key] = string(pod.UID)
   123  	podMs.Labels[core.LabelLabels.Key] = util.LabelsToString(pod.Labels)
   124  
   125  	// Add cpu/mem requests and limits to containers
   126  	for _, container := range pod.Spec.Containers {
   127  		containerKey := core.PodContainerKey(pod.Namespace, pod.Name, container.Name)
   128  		if _, found := batch.MetricSets[containerKey]; !found {
   129  			if _, found := newMs[containerKey]; !found {
   130  				glog.V(2).Infof("Container %s not found, creating a stub", containerKey)
   131  				containerMs := &core.MetricSet{
   132  					MetricValues: make(map[string]core.MetricValue),
   133  					Labels: map[string]string{
   134  						core.LabelMetricSetType.Key:      core.MetricSetTypePodContainer,
   135  						core.LabelNamespaceName.Key:      pod.Namespace,
   136  						core.LabelPodNamespace.Key:       pod.Namespace,
   137  						core.LabelPodName.Key:            pod.Name,
   138  						core.LabelContainerName.Key:      container.Name,
   139  						core.LabelContainerBaseImage.Key: container.Image,
   140  						core.LabelPodId.Key:              string(pod.UID),
   141  						core.LabelLabels.Key:             util.LabelsToString(pod.Labels),
   142  						core.LabelNodename.Key:           podMs.Labels[core.LabelNodename.Key],
   143  						core.LabelHostname.Key:           podMs.Labels[core.LabelHostname.Key],
   144  						core.LabelHostID.Key:             podMs.Labels[core.LabelHostID.Key],
   145  					},
   146  				}
   147  				updateContainerResourcesAndLimits(containerMs, container)
   148  				newMs[containerKey] = containerMs
   149  			}
   150  		}
   151  	}
   152  }
   153  
   154  func updateContainerResourcesAndLimits(metricSet *core.MetricSet, container kube_api.Container) {
   155  	requests := container.Resources.Requests
   156  	if val, found := requests[kube_api.ResourceCPU]; found {
   157  		metricSet.MetricValues[core.MetricCpuRequest.Name] = intValue(val.MilliValue())
   158  	} else {
   159  		metricSet.MetricValues[core.MetricCpuRequest.Name] = intValue(0)
   160  	}
   161  	if val, found := requests[kube_api.ResourceMemory]; found {
   162  		metricSet.MetricValues[core.MetricMemoryRequest.Name] = intValue(val.Value())
   163  	} else {
   164  		metricSet.MetricValues[core.MetricMemoryRequest.Name] = intValue(0)
   165  	}
   166  
   167  	limits := container.Resources.Limits
   168  	if val, found := limits[kube_api.ResourceCPU]; found {
   169  		metricSet.MetricValues[core.MetricCpuLimit.Name] = intValue(val.MilliValue())
   170  	} else {
   171  		metricSet.MetricValues[core.MetricCpuLimit.Name] = intValue(0)
   172  	}
   173  	if val, found := limits[kube_api.ResourceMemory]; found {
   174  		metricSet.MetricValues[core.MetricMemoryLimit.Name] = intValue(val.Value())
   175  	} else {
   176  		metricSet.MetricValues[core.MetricMemoryLimit.Name] = intValue(0)
   177  	}
   178  }
   179  
   180  func intValue(value int64) core.MetricValue {
   181  	return core.MetricValue{
   182  		IntValue:   value,
   183  		MetricType: core.MetricGauge,
   184  		ValueType:  core.ValueInt64,
   185  	}
   186  }
   187  
   188  func NewPodBasedEnricher(podLister *cache.StoreToPodLister) (*PodBasedEnricher, error) {
   189  	return &PodBasedEnricher{
   190  		podLister: podLister,
   191  	}, nil
   192  }