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  }