Selaa lähdekoodia

initial pass of a whitelist that adds labels relevant for aggregation only

Ajay Tripathy 2 vuotta sitten
vanhempi
sitoutus
577eceb3ad

+ 3 - 1
pkg/metrics/metricsconfig.go

@@ -17,7 +17,9 @@ var (
 )
 
 type MetricsConfig struct {
-	DisabledMetrics []string `json:"disabledMetrics"`
+	DisabledMetrics    []string        `json:"disabledMetrics"`
+	UseLabelsWhitelist bool            `json:"useLabelsWhitelist,omitempty"`
+	LabelsWhitelist    map[string]bool `json:"labelsWhiteList,omitempty"`
 }
 
 // Gets map of disabled metrics to empty structs

+ 53 - 1
pkg/metrics/podlabelmetrics.go

@@ -14,6 +14,14 @@ import (
 type KubePodLabelsCollector struct {
 	KubeClusterCache clustercache.ClusterCache
 	metricsConfig    MetricsConfig
+	labelsWhitelist  map[string]bool
+}
+
+func (kpmc *KubePodLabelsCollector) SetLabelsWhiteList() {
+	kpmc.labelsWhitelist = make(map[string]bool)
+	for k, v := range kpmc.metricsConfig.LabelsWhitelist {
+		kpmc.labelsWhitelist[k] = v
+	}
 }
 
 // Describe sends the super-set of all possible descriptors of pod labels only
@@ -29,6 +37,40 @@ func (kpmc KubePodLabelsCollector) Describe(ch chan<- *prometheus.Desc) {
 	}
 }
 
+func (kpmc *KubePodLabelsCollector) UpdateControllerSelectorsCache() {
+	for _, r := range kpmc.KubeClusterCache.GetAllReplicaSets() {
+		for k := range r.Spec.Selector.MatchLabels {
+			kpmc.labelsWhitelist[k] = true
+		}
+		for _, v := range r.Spec.Selector.MatchExpressions {
+			kpmc.labelsWhitelist[v.Key] = true
+		}
+	}
+	for _, ss := range kpmc.KubeClusterCache.GetAllStatefulSets() {
+		for k := range ss.Spec.Selector.MatchLabels {
+			kpmc.labelsWhitelist[k] = true
+		}
+		for _, v := range ss.Spec.Selector.MatchExpressions {
+			kpmc.labelsWhitelist[v.Key] = true
+		}
+	}
+}
+
+func (kpmc *KubePodLabelsCollector) UpdateServiceLabels() {
+	for _, service := range kpmc.KubeClusterCache.GetAllServices() {
+		// Just unroll the selector and keep all labels whose keys could match a service selector
+		for k := range service.Spec.Selector {
+			kpmc.labelsWhitelist[k] = true
+		}
+	}
+}
+
+func (kpmc *KubePodLabelsCollector) UpdateWhitelist() {
+	kpmc.SetLabelsWhiteList()
+	kpmc.UpdateControllerSelectorsCache()
+	kpmc.UpdateServiceLabels()
+}
+
 // Collect is called by the Prometheus registry when collecting metrics.
 func (kpmc KubePodLabelsCollector) Collect(ch chan<- prometheus.Metric) {
 	pods := kpmc.KubeClusterCache.GetAllPods()
@@ -41,7 +83,17 @@ func (kpmc KubePodLabelsCollector) Collect(ch chan<- prometheus.Metric) {
 
 		// Pod Labels
 		if _, disabled := disabledMetrics["kube_pod_labels"]; !disabled {
-			labelNames, labelValues := promutil.KubePrependQualifierToLabels(promutil.SanitizeLabels(pod.GetLabels()), "label_")
+			podLabels := pod.GetLabels()
+			if kpmc.metricsConfig.UseLabelsWhitelist {
+				kpmc.UpdateWhitelist()
+				for lname := range podLabels {
+					if _, ok := kpmc.labelsWhitelist[lname]; !ok {
+						delete(podLabels, lname)
+					}
+				}
+			}
+
+			labelNames, labelValues := promutil.KubePrependQualifierToLabels(promutil.SanitizeLabels(podLabels), "label_")
 			ch <- newKubePodLabelsMetric("kube_pod_labels", podNS, podName, podUID, labelNames, labelValues)
 		}
 

+ 71 - 0
pkg/metrics/podlabelmetrics_test.go

@@ -0,0 +1,71 @@
+package metrics
+
+import (
+	"testing"
+
+	"github.com/opencost/opencost/pkg/clustercache"
+	appsv1 "k8s.io/api/apps/v1"
+	v1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+)
+
+func TestWhitelist(t *testing.T) {
+	sampleServices := []*v1.Service{&v1.Service{
+		Spec: v1.ServiceSpec{
+			Selector: map[string]string{"servicewhitelistlabel": "foo"},
+		},
+	}}
+	replicaSetLabelSelector := metav1.LabelSelector{
+		MatchLabels: map[string]string{"replicasetwhitelistlabel1": "bar"},
+	}
+	sampleReplicaSets := []*appsv1.ReplicaSet{{
+		Spec: appsv1.ReplicaSetSpec{
+			Selector: &replicaSetLabelSelector,
+		},
+	}}
+
+	sampleStatefulSets := []*appsv1.StatefulSet{}
+
+	kc := NewFakeCache(sampleReplicaSets, sampleStatefulSets, sampleServices)
+	wl := map[string]bool{
+		"whitelistedlabel": true,
+	}
+	mc := MetricsConfig{
+		DisabledMetrics:    []string{},
+		UseLabelsWhitelist: true,
+		LabelsWhitelist:    wl,
+	}
+	kplc := KubePodLabelsCollector{
+		KubeClusterCache: kc,
+		metricsConfig:    mc,
+	}
+	kplc.UpdateWhitelist()
+	//kplc.labelsWhitelist[]
+}
+
+type FakeCache struct {
+	clustercache.ClusterCache
+	replicasets  []*appsv1.ReplicaSet
+	statefulsets []*appsv1.StatefulSet
+	services     []*v1.Service
+}
+
+func (f FakeCache) GetAllReplicaSets() []*appsv1.ReplicaSet {
+	return f.replicasets
+}
+
+func (f FakeCache) GetAllStatefulSets() []*appsv1.StatefulSet {
+	return f.statefulsets
+}
+
+func (f FakeCache) GetAllServices() []*v1.Service {
+	return f.services
+}
+
+func NewFakeCache(replicasets []*appsv1.ReplicaSet, statefulsets []*appsv1.StatefulSet, services []*v1.Service) FakeCache {
+	return FakeCache{
+		replicasets:  replicasets,
+		statefulsets: statefulsets,
+		services:     services,
+	}
+}