diff --git a/internal/store/node.go b/internal/store/node.go index d4f80cb6b5..e2a1851054 100644 --- a/internal/store/node.go +++ b/internal/store/node.go @@ -290,7 +290,7 @@ func createNodeStatusAllocatableFamilyGenerator() generator.FamilyGenerator { case v1.ResourceCPU: ms = append(ms, &metric.Metric{ LabelValues: []string{ - sanitizeLabelName(string(resourceName)), + SanitizeLabelName(string(resourceName)), string(constant.UnitCore), }, Value: float64(val.MilliValue()) / 1000, @@ -302,7 +302,7 @@ func createNodeStatusAllocatableFamilyGenerator() generator.FamilyGenerator { case v1.ResourceMemory: ms = append(ms, &metric.Metric{ LabelValues: []string{ - sanitizeLabelName(string(resourceName)), + SanitizeLabelName(string(resourceName)), string(constant.UnitByte), }, Value: float64(val.MilliValue()) / 1000, @@ -310,7 +310,7 @@ func createNodeStatusAllocatableFamilyGenerator() generator.FamilyGenerator { case v1.ResourcePods: ms = append(ms, &metric.Metric{ LabelValues: []string{ - sanitizeLabelName(string(resourceName)), + SanitizeLabelName(string(resourceName)), string(constant.UnitInteger), }, Value: float64(val.MilliValue()) / 1000, @@ -319,7 +319,7 @@ func createNodeStatusAllocatableFamilyGenerator() generator.FamilyGenerator { if isHugePageResourceName(resourceName) { ms = append(ms, &metric.Metric{ LabelValues: []string{ - sanitizeLabelName(string(resourceName)), + SanitizeLabelName(string(resourceName)), string(constant.UnitByte), }, Value: float64(val.MilliValue()) / 1000, @@ -328,7 +328,7 @@ func createNodeStatusAllocatableFamilyGenerator() generator.FamilyGenerator { if isAttachableVolumeResourceName(resourceName) { ms = append(ms, &metric.Metric{ LabelValues: []string{ - sanitizeLabelName(string(resourceName)), + SanitizeLabelName(string(resourceName)), string(constant.UnitByte), }, Value: float64(val.MilliValue()) / 1000, @@ -337,7 +337,7 @@ func createNodeStatusAllocatableFamilyGenerator() generator.FamilyGenerator { if isExtendedResourceName(resourceName) { ms = append(ms, &metric.Metric{ LabelValues: []string{ - sanitizeLabelName(string(resourceName)), + SanitizeLabelName(string(resourceName)), string(constant.UnitInteger), }, Value: float64(val.MilliValue()) / 1000, @@ -373,7 +373,7 @@ func createNodeStatusCapacityFamilyGenerator() generator.FamilyGenerator { case v1.ResourceCPU: ms = append(ms, &metric.Metric{ LabelValues: []string{ - sanitizeLabelName(string(resourceName)), + SanitizeLabelName(string(resourceName)), string(constant.UnitCore), }, Value: float64(val.MilliValue()) / 1000, @@ -385,7 +385,7 @@ func createNodeStatusCapacityFamilyGenerator() generator.FamilyGenerator { case v1.ResourceMemory: ms = append(ms, &metric.Metric{ LabelValues: []string{ - sanitizeLabelName(string(resourceName)), + SanitizeLabelName(string(resourceName)), string(constant.UnitByte), }, Value: float64(val.MilliValue()) / 1000, @@ -393,7 +393,7 @@ func createNodeStatusCapacityFamilyGenerator() generator.FamilyGenerator { case v1.ResourcePods: ms = append(ms, &metric.Metric{ LabelValues: []string{ - sanitizeLabelName(string(resourceName)), + SanitizeLabelName(string(resourceName)), string(constant.UnitInteger), }, Value: float64(val.MilliValue()) / 1000, @@ -402,7 +402,7 @@ func createNodeStatusCapacityFamilyGenerator() generator.FamilyGenerator { if isHugePageResourceName(resourceName) { ms = append(ms, &metric.Metric{ LabelValues: []string{ - sanitizeLabelName(string(resourceName)), + SanitizeLabelName(string(resourceName)), string(constant.UnitByte), }, Value: float64(val.MilliValue()) / 1000, @@ -411,7 +411,7 @@ func createNodeStatusCapacityFamilyGenerator() generator.FamilyGenerator { if isAttachableVolumeResourceName(resourceName) { ms = append(ms, &metric.Metric{ LabelValues: []string{ - sanitizeLabelName(string(resourceName)), + SanitizeLabelName(string(resourceName)), string(constant.UnitByte), }, Value: float64(val.MilliValue()) / 1000, @@ -420,7 +420,7 @@ func createNodeStatusCapacityFamilyGenerator() generator.FamilyGenerator { if isExtendedResourceName(resourceName) { ms = append(ms, &metric.Metric{ LabelValues: []string{ - sanitizeLabelName(string(resourceName)), + SanitizeLabelName(string(resourceName)), string(constant.UnitInteger), }, Value: float64(val.MilliValue()) / 1000, diff --git a/internal/store/pod.go b/internal/store/pod.go index f6275d2df4..59143a81b8 100644 --- a/internal/store/pod.go +++ b/internal/store/pod.go @@ -177,7 +177,7 @@ func createPodContainerResourceLimitsFamilyGenerator() generator.FamilyGenerator switch resourceName { case v1.ResourceCPU: ms = append(ms, &metric.Metric{ - LabelValues: []string{c.Name, p.Spec.NodeName, sanitizeLabelName(string(resourceName)), string(constant.UnitCore)}, + LabelValues: []string{c.Name, p.Spec.NodeName, SanitizeLabelName(string(resourceName)), string(constant.UnitCore)}, Value: float64(val.MilliValue()) / 1000, }) case v1.ResourceStorage: @@ -186,26 +186,26 @@ func createPodContainerResourceLimitsFamilyGenerator() generator.FamilyGenerator fallthrough case v1.ResourceMemory: ms = append(ms, &metric.Metric{ - LabelValues: []string{c.Name, p.Spec.NodeName, sanitizeLabelName(string(resourceName)), string(constant.UnitByte)}, + LabelValues: []string{c.Name, p.Spec.NodeName, SanitizeLabelName(string(resourceName)), string(constant.UnitByte)}, Value: float64(val.Value()), }) default: if isHugePageResourceName(resourceName) { ms = append(ms, &metric.Metric{ - LabelValues: []string{c.Name, p.Spec.NodeName, sanitizeLabelName(string(resourceName)), string(constant.UnitByte)}, + LabelValues: []string{c.Name, p.Spec.NodeName, SanitizeLabelName(string(resourceName)), string(constant.UnitByte)}, Value: float64(val.Value()), }) } if isAttachableVolumeResourceName(resourceName) { ms = append(ms, &metric.Metric{ Value: float64(val.Value()), - LabelValues: []string{c.Name, p.Spec.NodeName, sanitizeLabelName(string(resourceName)), string(constant.UnitByte)}, + LabelValues: []string{c.Name, p.Spec.NodeName, SanitizeLabelName(string(resourceName)), string(constant.UnitByte)}, }) } if isExtendedResourceName(resourceName) { ms = append(ms, &metric.Metric{ Value: float64(val.Value()), - LabelValues: []string{c.Name, p.Spec.NodeName, sanitizeLabelName(string(resourceName)), string(constant.UnitInteger)}, + LabelValues: []string{c.Name, p.Spec.NodeName, SanitizeLabelName(string(resourceName)), string(constant.UnitInteger)}, }) } @@ -241,7 +241,7 @@ func createPodContainerResourceRequestsFamilyGenerator() generator.FamilyGenerat switch resourceName { case v1.ResourceCPU: ms = append(ms, &metric.Metric{ - LabelValues: []string{c.Name, p.Spec.NodeName, sanitizeLabelName(string(resourceName)), string(constant.UnitCore)}, + LabelValues: []string{c.Name, p.Spec.NodeName, SanitizeLabelName(string(resourceName)), string(constant.UnitCore)}, Value: float64(val.MilliValue()) / 1000, }) case v1.ResourceStorage: @@ -250,25 +250,25 @@ func createPodContainerResourceRequestsFamilyGenerator() generator.FamilyGenerat fallthrough case v1.ResourceMemory: ms = append(ms, &metric.Metric{ - LabelValues: []string{c.Name, p.Spec.NodeName, sanitizeLabelName(string(resourceName)), string(constant.UnitByte)}, + LabelValues: []string{c.Name, p.Spec.NodeName, SanitizeLabelName(string(resourceName)), string(constant.UnitByte)}, Value: float64(val.Value()), }) default: if isHugePageResourceName(resourceName) { ms = append(ms, &metric.Metric{ - LabelValues: []string{c.Name, p.Spec.NodeName, sanitizeLabelName(string(resourceName)), string(constant.UnitByte)}, + LabelValues: []string{c.Name, p.Spec.NodeName, SanitizeLabelName(string(resourceName)), string(constant.UnitByte)}, Value: float64(val.Value()), }) } if isAttachableVolumeResourceName(resourceName) { ms = append(ms, &metric.Metric{ - LabelValues: []string{c.Name, p.Spec.NodeName, sanitizeLabelName(string(resourceName)), string(constant.UnitByte)}, + LabelValues: []string{c.Name, p.Spec.NodeName, SanitizeLabelName(string(resourceName)), string(constant.UnitByte)}, Value: float64(val.Value()), }) } if isExtendedResourceName(resourceName) { ms = append(ms, &metric.Metric{ - LabelValues: []string{c.Name, p.Spec.NodeName, sanitizeLabelName(string(resourceName)), string(constant.UnitInteger)}, + LabelValues: []string{c.Name, p.Spec.NodeName, SanitizeLabelName(string(resourceName)), string(constant.UnitInteger)}, Value: float64(val.Value()), }) } @@ -713,7 +713,7 @@ func createPodInitContainerResourceLimitsFamilyGenerator() generator.FamilyGener switch resourceName { case v1.ResourceCPU: ms = append(ms, &metric.Metric{ - LabelValues: []string{c.Name, p.Spec.NodeName, sanitizeLabelName(string(resourceName)), string(constant.UnitCore)}, + LabelValues: []string{c.Name, p.Spec.NodeName, SanitizeLabelName(string(resourceName)), string(constant.UnitCore)}, Value: float64(val.MilliValue()) / 1000, }) case v1.ResourceStorage: @@ -722,26 +722,26 @@ func createPodInitContainerResourceLimitsFamilyGenerator() generator.FamilyGener fallthrough case v1.ResourceMemory: ms = append(ms, &metric.Metric{ - LabelValues: []string{c.Name, p.Spec.NodeName, sanitizeLabelName(string(resourceName)), string(constant.UnitByte)}, + LabelValues: []string{c.Name, p.Spec.NodeName, SanitizeLabelName(string(resourceName)), string(constant.UnitByte)}, Value: float64(val.Value()), }) default: if isHugePageResourceName(resourceName) { ms = append(ms, &metric.Metric{ - LabelValues: []string{c.Name, p.Spec.NodeName, sanitizeLabelName(string(resourceName)), string(constant.UnitByte)}, + LabelValues: []string{c.Name, p.Spec.NodeName, SanitizeLabelName(string(resourceName)), string(constant.UnitByte)}, Value: float64(val.Value()), }) } if isAttachableVolumeResourceName(resourceName) { ms = append(ms, &metric.Metric{ Value: float64(val.Value()), - LabelValues: []string{c.Name, p.Spec.NodeName, sanitizeLabelName(string(resourceName)), string(constant.UnitByte)}, + LabelValues: []string{c.Name, p.Spec.NodeName, SanitizeLabelName(string(resourceName)), string(constant.UnitByte)}, }) } if isExtendedResourceName(resourceName) { ms = append(ms, &metric.Metric{ Value: float64(val.Value()), - LabelValues: []string{c.Name, p.Spec.NodeName, sanitizeLabelName(string(resourceName)), string(constant.UnitInteger)}, + LabelValues: []string{c.Name, p.Spec.NodeName, SanitizeLabelName(string(resourceName)), string(constant.UnitInteger)}, }) } @@ -777,7 +777,7 @@ func createPodInitContainerResourceRequestsFamilyGenerator() generator.FamilyGen switch resourceName { case v1.ResourceCPU: ms = append(ms, &metric.Metric{ - LabelValues: []string{c.Name, p.Spec.NodeName, sanitizeLabelName(string(resourceName)), string(constant.UnitCore)}, + LabelValues: []string{c.Name, p.Spec.NodeName, SanitizeLabelName(string(resourceName)), string(constant.UnitCore)}, Value: float64(val.MilliValue()) / 1000, }) case v1.ResourceStorage: @@ -786,25 +786,25 @@ func createPodInitContainerResourceRequestsFamilyGenerator() generator.FamilyGen fallthrough case v1.ResourceMemory: ms = append(ms, &metric.Metric{ - LabelValues: []string{c.Name, p.Spec.NodeName, sanitizeLabelName(string(resourceName)), string(constant.UnitByte)}, + LabelValues: []string{c.Name, p.Spec.NodeName, SanitizeLabelName(string(resourceName)), string(constant.UnitByte)}, Value: float64(val.Value()), }) default: if isHugePageResourceName(resourceName) { ms = append(ms, &metric.Metric{ - LabelValues: []string{c.Name, p.Spec.NodeName, sanitizeLabelName(string(resourceName)), string(constant.UnitByte)}, + LabelValues: []string{c.Name, p.Spec.NodeName, SanitizeLabelName(string(resourceName)), string(constant.UnitByte)}, Value: float64(val.Value()), }) } if isAttachableVolumeResourceName(resourceName) { ms = append(ms, &metric.Metric{ - LabelValues: []string{c.Name, p.Spec.NodeName, sanitizeLabelName(string(resourceName)), string(constant.UnitByte)}, + LabelValues: []string{c.Name, p.Spec.NodeName, SanitizeLabelName(string(resourceName)), string(constant.UnitByte)}, Value: float64(val.Value()), }) } if isExtendedResourceName(resourceName) { ms = append(ms, &metric.Metric{ - LabelValues: []string{c.Name, p.Spec.NodeName, sanitizeLabelName(string(resourceName)), string(constant.UnitInteger)}, + LabelValues: []string{c.Name, p.Spec.NodeName, SanitizeLabelName(string(resourceName)), string(constant.UnitInteger)}, Value: float64(val.Value()), }) } diff --git a/internal/store/utils.go b/internal/store/utils.go index 009d5739d7..a42a81de5e 100644 --- a/internal/store/utils.go +++ b/internal/store/utils.go @@ -123,10 +123,10 @@ func mapToPrometheusLabels(labels map[string]string, prefix string) ([]string, [ } func labelName(prefix, labelName string) string { - return prefix + "_" + lintLabelName(sanitizeLabelName(labelName)) + return prefix + "_" + lintLabelName(SanitizeLabelName(labelName)) } -func sanitizeLabelName(s string) string { +func SanitizeLabelName(s string) string { return invalidLabelCharRE.ReplaceAllString(s, "_") } diff --git a/internal/store/verticalpodautoscaler.go b/internal/store/verticalpodautoscaler.go new file mode 100644 index 0000000000..a90bb2a07b --- /dev/null +++ b/internal/store/verticalpodautoscaler.go @@ -0,0 +1,321 @@ +/* +Copyright 2019 The Kubernetes Authors All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package store + +import ( + "context" + + autoscalingv1 "k8s.io/api/autoscaling/v1" + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/watch" + autoscaling "k8s.io/autoscaler/vertical-pod-autoscaler/pkg/apis/autoscaling.k8s.io/v1beta2" + vpaclientset "k8s.io/autoscaler/vertical-pod-autoscaler/pkg/client/clientset/versioned" + clientset "k8s.io/client-go/kubernetes" + "k8s.io/client-go/tools/cache" + basemetrics "k8s.io/component-base/metrics" + + "k8s.io/kube-state-metrics/v2/pkg/constant" + "k8s.io/kube-state-metrics/v2/pkg/metric" + generator "k8s.io/kube-state-metrics/v2/pkg/metric_generator" +) + +var ( + descVerticalPodAutoscalerAnnotationsName = "kube_verticalpodautoscaler_annotations" + descVerticalPodAutoscalerAnnotationsHelp = "Kubernetes annotations converted to Prometheus labels." + descVerticalPodAutoscalerLabelsName = "kube_verticalpodautoscaler_labels" + descVerticalPodAutoscalerLabelsHelp = "Kubernetes labels converted to Prometheus labels." + descVerticalPodAutoscalerLabelsDefaultLabels = []string{"namespace", "verticalpodautoscaler", "target_api_version", "target_kind", "target_name"} +) + +func vpaMetricFamilies(allowAnnotationsList, allowLabelsList []string) []generator.FamilyGenerator { + return []generator.FamilyGenerator{ + *generator.NewFamilyGeneratorWithStability( + descVerticalPodAutoscalerAnnotationsName, + descVerticalPodAutoscalerAnnotationsHelp, + metric.Gauge, + basemetrics.ALPHA, + "v2.9.0", + wrapVPAFunc(func(a *autoscaling.VerticalPodAutoscaler) *metric.Family { + annotationKeys, annotationValues := createPrometheusLabelKeysValues("annotation", a.Annotations, allowAnnotationsList) + return &metric.Family{ + Metrics: []*metric.Metric{ + { + LabelKeys: annotationKeys, + LabelValues: annotationValues, + Value: 1, + }, + }, + } + }), + ), + *generator.NewFamilyGeneratorWithStability( + descVerticalPodAutoscalerLabelsName, + descVerticalPodAutoscalerLabelsHelp, + metric.Gauge, + basemetrics.ALPHA, + "v2.9.0", + wrapVPAFunc(func(a *autoscaling.VerticalPodAutoscaler) *metric.Family { + labelKeys, labelValues := createPrometheusLabelKeysValues("label", a.Labels, allowLabelsList) + return &metric.Family{ + Metrics: []*metric.Metric{ + { + LabelKeys: labelKeys, + LabelValues: labelValues, + Value: 1, + }, + }, + } + }), + ), + *generator.NewFamilyGeneratorWithStability( + "kube_verticalpodautoscaler_spec_updatepolicy_updatemode", + "Update mode of the VerticalPodAutoscaler.", + metric.Gauge, + basemetrics.ALPHA, + "v2.9.0", + wrapVPAFunc(func(a *autoscaling.VerticalPodAutoscaler) *metric.Family { + ms := []*metric.Metric{} + + if a.Spec.UpdatePolicy == nil || a.Spec.UpdatePolicy.UpdateMode == nil { + return &metric.Family{ + Metrics: ms, + } + } + + for _, mode := range []autoscaling.UpdateMode{ + autoscaling.UpdateModeOff, + autoscaling.UpdateModeInitial, + autoscaling.UpdateModeRecreate, + autoscaling.UpdateModeAuto, + } { + var v float64 + if *a.Spec.UpdatePolicy.UpdateMode == mode { + v = 1 + } else { + v = 0 + } + ms = append(ms, &metric.Metric{ + LabelKeys: []string{"update_mode"}, + LabelValues: []string{string(mode)}, + Value: v, + }) + } + + return &metric.Family{ + Metrics: ms, + } + }), + ), + *generator.NewFamilyGeneratorWithStability( + "kube_verticalpodautoscaler_spec_resourcepolicy_container_policies_minallowed", + "Minimum resources the VerticalPodAutoscaler can set for containers matching the name.", + metric.Gauge, + basemetrics.ALPHA, + "v2.9.0", + wrapVPAFunc(func(a *autoscaling.VerticalPodAutoscaler) *metric.Family { + ms := []*metric.Metric{} + if a.Spec.ResourcePolicy == nil || a.Spec.ResourcePolicy.ContainerPolicies == nil { + return &metric.Family{ + Metrics: ms, + } + } + + for _, c := range a.Spec.ResourcePolicy.ContainerPolicies { + ms = append(ms, vpaResourcesToMetrics(c.ContainerName, c.MinAllowed)...) + + } + return &metric.Family{ + Metrics: ms, + } + }), + ), + *generator.NewFamilyGeneratorWithStability( + "kube_verticalpodautoscaler_spec_resourcepolicy_container_policies_maxallowed", + "Maximum resources the VerticalPodAutoscaler can set for containers matching the name.", + metric.Gauge, + basemetrics.ALPHA, + "v2.9.0", + wrapVPAFunc(func(a *autoscaling.VerticalPodAutoscaler) *metric.Family { + ms := []*metric.Metric{} + if a.Spec.ResourcePolicy == nil || a.Spec.ResourcePolicy.ContainerPolicies == nil { + return &metric.Family{ + Metrics: ms, + } + } + + for _, c := range a.Spec.ResourcePolicy.ContainerPolicies { + ms = append(ms, vpaResourcesToMetrics(c.ContainerName, c.MaxAllowed)...) + } + return &metric.Family{ + Metrics: ms, + } + }), + ), + *generator.NewFamilyGeneratorWithStability( + "kube_verticalpodautoscaler_status_recommendation_containerrecommendations_lowerbound", + "Minimum resources the container can use before the VerticalPodAutoscaler updater evicts it.", + metric.Gauge, + basemetrics.ALPHA, + "v2.9.0", + wrapVPAFunc(func(a *autoscaling.VerticalPodAutoscaler) *metric.Family { + ms := []*metric.Metric{} + if a.Status.Recommendation == nil || a.Status.Recommendation.ContainerRecommendations == nil { + return &metric.Family{ + Metrics: ms, + } + } + + for _, c := range a.Status.Recommendation.ContainerRecommendations { + ms = append(ms, vpaResourcesToMetrics(c.ContainerName, c.LowerBound)...) + } + return &metric.Family{ + Metrics: ms, + } + }), + ), + *generator.NewFamilyGeneratorWithStability( + "kube_verticalpodautoscaler_status_recommendation_containerrecommendations_upperbound", + "Maximum resources the container can use before the VerticalPodAutoscaler updater evicts it.", + metric.Gauge, + basemetrics.ALPHA, + "v2.9.0", + wrapVPAFunc(func(a *autoscaling.VerticalPodAutoscaler) *metric.Family { + ms := []*metric.Metric{} + if a.Status.Recommendation == nil || a.Status.Recommendation.ContainerRecommendations == nil { + return &metric.Family{ + Metrics: ms, + } + } + + for _, c := range a.Status.Recommendation.ContainerRecommendations { + ms = append(ms, vpaResourcesToMetrics(c.ContainerName, c.UpperBound)...) + } + return &metric.Family{ + Metrics: ms, + } + }), + ), + *generator.NewFamilyGeneratorWithStability( + "kube_verticalpodautoscaler_status_recommendation_containerrecommendations_target", + "Target resources the VerticalPodAutoscaler recommends for the container.", + metric.Gauge, + basemetrics.ALPHA, + "v2.9.0", + wrapVPAFunc(func(a *autoscaling.VerticalPodAutoscaler) *metric.Family { + ms := []*metric.Metric{} + if a.Status.Recommendation == nil || a.Status.Recommendation.ContainerRecommendations == nil { + return &metric.Family{ + Metrics: ms, + } + } + for _, c := range a.Status.Recommendation.ContainerRecommendations { + ms = append(ms, vpaResourcesToMetrics(c.ContainerName, c.Target)...) + } + return &metric.Family{ + Metrics: ms, + } + }), + ), + *generator.NewFamilyGeneratorWithStability( + "kube_verticalpodautoscaler_status_recommendation_containerrecommendations_uncappedtarget", + "Target resources the VerticalPodAutoscaler recommends for the container ignoring bounds.", + metric.Gauge, + basemetrics.ALPHA, + "v2.9.0", + wrapVPAFunc(func(a *autoscaling.VerticalPodAutoscaler) *metric.Family { + ms := []*metric.Metric{} + if a.Status.Recommendation == nil || a.Status.Recommendation.ContainerRecommendations == nil { + return &metric.Family{ + Metrics: ms, + } + } + for _, c := range a.Status.Recommendation.ContainerRecommendations { + ms = append(ms, vpaResourcesToMetrics(c.ContainerName, c.UncappedTarget)...) + } + return &metric.Family{ + Metrics: ms, + } + }), + ), + } +} + +func vpaResourcesToMetrics(containerName string, resources v1.ResourceList) []*metric.Metric { + ms := []*metric.Metric{} + for resourceName, val := range resources { + switch resourceName { + case v1.ResourceCPU: + ms = append(ms, &metric.Metric{ + LabelValues: []string{containerName, SanitizeLabelName(string(resourceName)), string(constant.UnitCore)}, + Value: float64(val.MilliValue()) / 1000, + }) + case v1.ResourceStorage: + fallthrough + case v1.ResourceEphemeralStorage: + fallthrough + case v1.ResourceMemory: + ms = append(ms, &metric.Metric{ + LabelValues: []string{containerName, SanitizeLabelName(string(resourceName)), string(constant.UnitByte)}, + Value: float64(val.Value()), + }) + } + } + for _, metric := range ms { + metric.LabelKeys = []string{"container", "resource", "unit"} + } + return ms +} + +func wrapVPAFunc(f func(*autoscaling.VerticalPodAutoscaler) *metric.Family) func(interface{}) *metric.Family { + return func(obj interface{}) *metric.Family { + vpa := obj.(*autoscaling.VerticalPodAutoscaler) + + metricFamily := f(vpa) + targetRef := vpa.Spec.TargetRef + + // targetRef was not a mandatory field, which can lead to a nil pointer exception here. + // However, we still want to expose metrics to be able: + // * to alert about VPA objects without target refs + // * to count the right amount of VPA objects in a cluster + if targetRef == nil { + targetRef = &autoscalingv1.CrossVersionObjectReference{} + } + + for _, m := range metricFamily.Metrics { + m.LabelKeys, m.LabelValues = mergeKeyValues(descVerticalPodAutoscalerLabelsDefaultLabels, []string{vpa.Namespace, vpa.Name, targetRef.APIVersion, targetRef.Kind, targetRef.Name}, m.LabelKeys, m.LabelValues) + } + + return metricFamily + } +} + +func createVPAListWatchFunc(vpaClient vpaclientset.Interface) func(kubeClient clientset.Interface, ns string, fieldSelector string) cache.ListerWatcher { + return func(kubeClient clientset.Interface, ns string, fieldSelector string) cache.ListerWatcher { + return &cache.ListWatch{ + ListFunc: func(opts metav1.ListOptions) (runtime.Object, error) { + opts.FieldSelector = fieldSelector + return vpaClient.AutoscalingV1beta2().VerticalPodAutoscalers(ns).List(context.TODO(), opts) + }, + WatchFunc: func(opts metav1.ListOptions) (watch.Interface, error) { + opts.FieldSelector = fieldSelector + return vpaClient.AutoscalingV1beta2().VerticalPodAutoscalers(ns).Watch(context.TODO(), opts) + }, + } + } +} diff --git a/pkg/customresourcestate/registry_factory.go b/pkg/customresourcestate/registry_factory.go index 05a81ae9de..4c145edfab 100644 --- a/pkg/customresourcestate/registry_factory.go +++ b/pkg/customresourcestate/registry_factory.go @@ -30,10 +30,9 @@ import ( "k8s.io/apimachinery/pkg/util/validation" "k8s.io/klog/v2" + "k8s.io/kube-state-metrics/v2/internal/store" "k8s.io/kube-state-metrics/v2/pkg/metric" generator "k8s.io/kube-state-metrics/v2/pkg/metric_generator" - - otelprom "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/translator/prometheus" ) func compile(resource Resource) ([]compiledFamily, error) { @@ -509,8 +508,7 @@ func addPathLabels(obj interface{}, labels map[string]valuePath, result map[stri m := labels[k].Get(obj) if kv, ok := m.(map[string]interface{}); ok { for k, v := range kv { - otelCompatPromLabelName := otelprom.NormalizeLabel(k) - result[otelCompatPromLabelName] = fmt.Sprintf("%v", v) + result[store.SanitizeLabelName(k)] = fmt.Sprintf("%v", v) } } } @@ -523,8 +521,7 @@ func addPathLabels(obj interface{}, labels map[string]valuePath, result map[stri if value == nil { continue } - otelCompatPromLabelName := otelprom.NormalizeLabel(k) - result[otelCompatPromLabelName] = fmt.Sprintf("%v", value) + result[store.SanitizeLabelName(k)] = fmt.Sprintf("%v", value) } }