Selaa lähdekoodia

Merge pull request #831 from kubecost/mmd/emit-kube_node_labels

Emit kube_node_labels like KSMv1
Michael Dresser 5 vuotta sitten
vanhempi
sitoutus
e67c88d652
2 muutettua tiedostoa jossa 108 lisäystä ja 0 poistoa
  1. 100 0
      pkg/costmodel/metrics.go
  2. 8 0
      pkg/env/costmodelenv.go

+ 100 - 0
pkg/costmodel/metrics.go

@@ -827,6 +827,100 @@ func (nam KubePodLabelsMetric) Write(m *dto.Metric) error {
 	return nil
 }
 
+//--------------------------------------------------------------------------
+//  KubeNodeLabelsCollector
+//--------------------------------------------------------------------------
+//
+// We use this to emit kube_node_labels with all of a node's labels, regardless
+// of the whitelist setting introduced in KSM v2. See
+// https://github.com/kubernetes/kube-state-metrics/issues/1270#issuecomment-712986441
+
+// KubeNodeLabelsCollector is a prometheus collector that generates
+// KubeNodeLabelsMetrics
+type KubeNodeLabelsCollector struct {
+	KubeClusterCache clustercache.ClusterCache
+}
+
+// Describe sends the super-set of all possible descriptors of metrics
+// collected by this Collector.
+func (nsac KubeNodeLabelsCollector) Describe(ch chan<- *prometheus.Desc) {
+	ch <- prometheus.NewDesc("kube_node_labels", "all labels for each node prefixed with label_", []string{}, nil)
+}
+
+// Collect is called by the Prometheus registry when collecting metrics.
+func (nsac KubeNodeLabelsCollector) Collect(ch chan<- prometheus.Metric) {
+	nodes := nsac.KubeClusterCache.GetAllNodes()
+	for _, node := range nodes {
+
+		labelNames, labelValues := prom.KubePrependQualifierToLabels(node.GetLabels(), "label_")
+
+		m := newKubeNodeLabelsMetric(
+			node.GetName(),
+			"kube_node_labels",
+			labelNames,
+			labelValues,
+		)
+		ch <- m
+	}
+}
+
+//--------------------------------------------------------------------------
+//  KubeNodeLabelsMetric
+//--------------------------------------------------------------------------
+
+// KubeNodeLabelsMetric is a prometheus.Metric used to encode
+// a duplicate of the deprecated kube-state-metrics metric
+// kube_node_labels
+type KubeNodeLabelsMetric struct {
+	fqName      string
+	help        string
+	labelNames  []string
+	labelValues []string
+	node        string
+}
+
+// Creates a new KubeNodeLabelsMetric, implementation of prometheus.Metric
+func newKubeNodeLabelsMetric(node string, fqname string, labelNames []string, labelValues []string) KubeNodeLabelsMetric {
+	return KubeNodeLabelsMetric{
+		fqName:      fqname,
+		labelNames:  labelNames,
+		labelValues: labelValues,
+		help:        "kube_node_labels all labels for each node prefixed with label_",
+		node:        node,
+	}
+}
+
+// Desc returns the descriptor for the Metric. This method idempotently
+// returns the same descriptor throughout the lifetime of the Metric.
+func (nam KubeNodeLabelsMetric) Desc() *prometheus.Desc {
+	l := prometheus.Labels{
+		"node": nam.node,
+	}
+	return prometheus.NewDesc(nam.fqName, nam.help, nam.labelNames, l)
+}
+
+// Write encodes the Metric into a "Metric" Protocol Buffer data
+// transmission object.
+func (nam KubeNodeLabelsMetric) Write(m *dto.Metric) error {
+	h := float64(1)
+	m.Gauge = &dto.Gauge{
+		Value: &h,
+	}
+
+	var labels []*dto.LabelPair
+	for i := range nam.labelNames {
+		labels = append(labels, &dto.LabelPair{
+			Name:  &nam.labelNames[i],
+			Value: &nam.labelValues[i],
+		})
+	}
+
+	nodeString := "node"
+	labels = append(labels, &dto.LabelPair{Name: &nodeString, Value: &nam.node})
+	m.Label = labels
+	return nil
+}
+
 // toStringPtr is used to create a new string pointer from iteration vars
 func toStringPtr(s string) *string {
 	return &s
@@ -991,6 +1085,12 @@ func initCostModelMetrics(clusterCache clustercache.ClusterCache, provider cloud
 				KubeClusterCache: clusterCache,
 			})
 		}
+
+		if env.IsEmitKubeNodeLabelsMetric() {
+			prometheus.MustRegister(KubeNodeLabelsCollector{
+				KubeClusterCache: clusterCache,
+			})
+		}
 	})
 }
 

+ 8 - 0
pkg/env/costmodelenv.go

@@ -40,6 +40,7 @@ const (
 	EmitKubeNodeStatusCapacityMemoryBytesMetricEnvVar = "EMIT_KUBE_NODE_STATUS_CAPACITY_MEMORY_BYTES_METRIC"
 	EmitKubeNodeStatusCapacityCPUCoresMetricEnvVar    = "EMIT_KUBE_NODE_STATUS_CAPACITY_CPU_CORES_METRIC"
 	EmitKubePodLabelsMetricEnvVar                     = "EMIT_KUBE_POD_LABELS_METRIC"
+	EmitKubeNodeLabelsMetricEnvVar                    = "EMIT_KUBE_NODE_LABELS_METRIC"
 
 	ThanosEnabledEnvVar      = "THANOS_ENABLED"
 	ThanosQueryUrlEnvVar     = "THANOS_QUERY_URL"
@@ -111,6 +112,13 @@ func IsEmitKubePodLabelsMetric() bool {
 	return GetBool(EmitKubePodLabelsMetricEnvVar, true)
 }
 
+// IsEmitKubeNodeLabelsMetric returns true if cost-model is configured
+// to emit the kube_node_labels metric. It uses the old, pre KSM 2.0 logic
+// where all labels are emitted instead of requiring a whitelist.
+func IsEmitKubeNodeLabelsMetric() bool {
+	return GetBool(EmitKubeNodeLabelsMetricEnvVar, true)
+}
+
 // GetAWSAccessKeyID returns the environment variable value for AWSAccessKeyIDEnvVar which represents
 // the AWS access key for authentication
 func GetAWSAccessKeyID() string {