From b5e78331cc2bfb6896d20d077b7ba79c3f3e7f2d Mon Sep 17 00:00:00 2001 From: Arunprasad Rajkumar Date: Tue, 26 Oct 2021 21:19:40 +0530 Subject: [PATCH] Implement kube_*_labels and kube_*_annotations metrics for pdb This commit introduces kube_*_labels and kube_*_annotations metrics to poddisruptionbudget to keep in consistency with other k8s objects. Signed-off-by: Arunprasad Rajkumar --- docs/poddisruptionbudget-metrics.md | 2 + internal/store/builder.go | 2 +- internal/store/poddisruptionbudget.go | 46 +++++++++++++++++++++- internal/store/poddisruptionbudget_test.go | 46 ++++++++++++++++++++-- 4 files changed, 90 insertions(+), 6 deletions(-) diff --git a/docs/poddisruptionbudget-metrics.md b/docs/poddisruptionbudget-metrics.md index ae5668f968..0a18622e16 100644 --- a/docs/poddisruptionbudget-metrics.md +++ b/docs/poddisruptionbudget-metrics.md @@ -2,6 +2,8 @@ | Metric name| Metric type | Labels/tags | Status | | ---------- | ----------- | ----------- | ----------- | +| kube_poddisruptionbudget_annotations | Gauge | `poddisruptionbudget`=<poddisruptionbudget-name>
`namespace`=<poddisruptionbudget-namespace>
`annotation_PODDISRUPTIONBUDGET_ANNOTATION`=<PODDISRUPTIONBUDGET_ANNOATION> | EXPERIMENTAL | +| kube_poddisruptionbudget_labels | Gauge | `poddisruptionbudget`=<poddisruptionbudget-name>
`namespace`=<poddisruptionbudget-namespace>
`label_PODDISRUPTIONBUDGET_LABEL`=<PODDISRUPTIONBUDGET_ANNOATION> | EXPERIMENTAL | | kube_poddisruptionbudget_created | Gauge | `poddisruptionbudget`=<pdb-name>
`namespace`=<pdb-namespace> | STABLE | kube_poddisruptionbudget_status_current_healthy | Gauge | `poddisruptionbudget`=<pdb-name>
`namespace`=<pdb-namespace> | STABLE | kube_poddisruptionbudget_status_desired_healthy | Gauge | `poddisruptionbudget`=<pdb-name>
`namespace`=<pdb-namespace> | STABLE diff --git a/internal/store/builder.go b/internal/store/builder.go index 47442531c2..f5b9843b29 100644 --- a/internal/store/builder.go +++ b/internal/store/builder.go @@ -325,7 +325,7 @@ func (b *Builder) buildPersistentVolumeStores() []cache.Store { } func (b *Builder) buildPodDisruptionBudgetStores() []cache.Store { - return b.buildStoresFunc(podDisruptionBudgetMetricFamilies, &policy.PodDisruptionBudget{}, createPodDisruptionBudgetListWatch, b.useAPIServerCache) + return b.buildStoresFunc(podDisruptionBudgetMetricFamilies(b.allowAnnotationsList["poddisruptionbudget"], b.allowLabelsList["poddisruptionbudget"]), &policy.PodDisruptionBudget{}, createPodDisruptionBudgetListWatch, b.useAPIServerCache) } func (b *Builder) buildReplicaSetStores() []cache.Store { diff --git a/internal/store/poddisruptionbudget.go b/internal/store/poddisruptionbudget.go index 3855f20b0f..201379ace6 100644 --- a/internal/store/poddisruptionbudget.go +++ b/internal/store/poddisruptionbudget.go @@ -32,8 +32,50 @@ import ( var ( descPodDisruptionBudgetLabelsDefaultLabels = []string{"namespace", "poddisruptionbudget"} + descPodDisruptionBudgetAnnotationsName = "kube_poddisruptionbudget_annotations" + descPodDisruptionBudgetAnnotationsHelp = "Kubernetes annotations converted to Prometheus labels." + descPodDisruptionBudgetLabelsName = "kube_poddisruptionbudget_labels" + descPodDisruptionBudgetLabelsHelp = "Kubernetes labels converted to Prometheus labels." +) - podDisruptionBudgetMetricFamilies = []generator.FamilyGenerator{ +func podDisruptionBudgetMetricFamilies(allowAnnotationsList, allowLabelsList []string) []generator.FamilyGenerator { + return []generator.FamilyGenerator{ + *generator.NewFamilyGenerator( + descPodDisruptionBudgetAnnotationsName, + descPodDisruptionBudgetAnnotationsHelp, + metric.Gauge, + "", + wrapPodDisruptionBudgetFunc(func(p *v1beta1.PodDisruptionBudget) *metric.Family { + annotationKeys, annotationValues := createPrometheusLabelKeysValues("annotation", p.Annotations, allowAnnotationsList) + return &metric.Family{ + Metrics: []*metric.Metric{ + { + LabelKeys: annotationKeys, + LabelValues: annotationValues, + Value: 1, + }, + }, + } + }), + ), + *generator.NewFamilyGenerator( + descPodDisruptionBudgetLabelsName, + descPodDisruptionBudgetLabelsHelp, + metric.Gauge, + "", + wrapPodDisruptionBudgetFunc(func(p *v1beta1.PodDisruptionBudget) *metric.Family { + labelKeys, labelValues := createPrometheusLabelKeysValues("label", p.Labels, allowLabelsList) + return &metric.Family{ + Metrics: []*metric.Metric{ + { + LabelKeys: labelKeys, + LabelValues: labelValues, + Value: 1, + }, + }, + } + }), + ), *generator.NewFamilyGenerator( "kube_poddisruptionbudget_created", "Unix creation timestamp", @@ -129,7 +171,7 @@ var ( }), ), } -) +} func wrapPodDisruptionBudgetFunc(f func(*v1beta1.PodDisruptionBudget) *metric.Family) func(interface{}) *metric.Family { return func(obj interface{}) *metric.Family { diff --git a/internal/store/poddisruptionbudget_test.go b/internal/store/poddisruptionbudget_test.go index 5048c1bbb7..1b5136686b 100644 --- a/internal/store/poddisruptionbudget_test.go +++ b/internal/store/poddisruptionbudget_test.go @@ -29,7 +29,13 @@ import ( func TestPodDisruptionBudgetStore(t *testing.T) { // Fixed metadata on type and help text. We prepend this to every expected // output so we only have to modify a single place when doing adjustments. - const metadata = ` + const labelsAndAnnotationsMetaData = ` + # HELP kube_poddisruptionbudget_annotations Kubernetes annotations converted to Prometheus labels. + # TYPE kube_poddisruptionbudget_annotations gauge + # HELP kube_poddisruptionbudget_labels Kubernetes labels converted to Prometheus labels. + # TYPE kube_poddisruptionbudget_labels gauge + ` + const metadata = labelsAndAnnotationsMetaData + ` # HELP kube_poddisruptionbudget_created Unix creation timestamp # TYPE kube_poddisruptionbudget_created gauge # HELP kube_poddisruptionbudget_status_current_healthy Current number of healthy pods @@ -61,6 +67,8 @@ func TestPodDisruptionBudgetStore(t *testing.T) { }, }, Want: metadata + ` + kube_poddisruptionbudget_annotations{namespace="ns1",poddisruptionbudget="pdb1"} 1 + kube_poddisruptionbudget_labels{namespace="ns1",poddisruptionbudget="pdb1"} 1 kube_poddisruptionbudget_created{namespace="ns1",poddisruptionbudget="pdb1"} 1.5e+09 kube_poddisruptionbudget_status_current_healthy{namespace="ns1",poddisruptionbudget="pdb1"} 12 kube_poddisruptionbudget_status_desired_healthy{namespace="ns1",poddisruptionbudget="pdb1"} 10 @@ -85,6 +93,8 @@ func TestPodDisruptionBudgetStore(t *testing.T) { }, }, Want: metadata + ` + kube_poddisruptionbudget_annotations{namespace="ns2",poddisruptionbudget="pdb2"} 1 + kube_poddisruptionbudget_labels{namespace="ns2",poddisruptionbudget="pdb2"} 1 kube_poddisruptionbudget_status_current_healthy{namespace="ns2",poddisruptionbudget="pdb2"} 8 kube_poddisruptionbudget_status_desired_healthy{namespace="ns2",poddisruptionbudget="pdb2"} 9 kube_poddisruptionbudget_status_pod_disruptions_allowed{namespace="ns2",poddisruptionbudget="pdb2"} 0 @@ -92,10 +102,40 @@ func TestPodDisruptionBudgetStore(t *testing.T) { kube_poddisruptionbudget_status_observed_generation{namespace="ns2",poddisruptionbudget="pdb2"} 1111 `, }, + { + AllowAnnotationsList: []string{ + "app.k8s.io/owner", + }, + AllowLabelsList: []string{ + "app", + }, + Obj: &v1beta1.PodDisruptionBudget{ + ObjectMeta: metav1.ObjectMeta{ + Name: "pdb_with_allowed_labels_and_annotations", + Namespace: "ns", + Annotations: map[string]string{ + "app.k8s.io/owner": "mysql-server", + "foo": "bar", + }, + Labels: map[string]string{ + "app": "mysql-server", + "hello": "world", + }, + }, + }, + Want: labelsAndAnnotationsMetaData + ` + kube_poddisruptionbudget_annotations{annotation_app_k8s_io_owner="mysql-server",namespace="ns",poddisruptionbudget="pdb_with_allowed_labels_and_annotations"} 1 + kube_poddisruptionbudget_labels{label_app="mysql-server",namespace="ns",poddisruptionbudget="pdb_with_allowed_labels_and_annotations"} 1 + `, + MetricNames: []string{ + "kube_poddisruptionbudget_annotations", + "kube_poddisruptionbudget_labels", + }, + }, } for i, c := range cases { - c.Func = generator.ComposeMetricGenFuncs(podDisruptionBudgetMetricFamilies) - c.Headers = generator.ExtractMetricFamilyHeaders(podDisruptionBudgetMetricFamilies) + c.Func = generator.ComposeMetricGenFuncs(podDisruptionBudgetMetricFamilies(c.AllowAnnotationsList, c.AllowLabelsList)) + c.Headers = generator.ExtractMetricFamilyHeaders(podDisruptionBudgetMetricFamilies(c.AllowAnnotationsList, c.AllowLabelsList)) if err := c.run(); err != nil { t.Errorf("unexpected collecting result in %vth run:\n%s", i, err) }