Skip to content

Commit 51df8fe

Browse files
committed
add rolebinding metrics
1 parent fad76e4 commit 51df8fe

File tree

15 files changed

+602
-1
lines changed

15 files changed

+602
-1
lines changed

docs/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ Per group of metrics there is one file for each metrics. See each file for speci
3131

3232
- [CertificateSigningRequest Metrics](certificatesigningrequest-metrics.md)
3333
- [ClusterRole Metrics](clusterrole-metrics.md)
34+
- [ClusterRoleBinding Metrics](clusterrolebinding-metrics.md)
3435
- [ConfigMap Metrics](configmap-metrics.md)
3536
- [CronJob Metrics](cronjob-metrics.md)
3637
- [DaemonSet Metrics](daemonset-metrics.md)
@@ -53,6 +54,7 @@ Per group of metrics there is one file for each metrics. See each file for speci
5354
- [ReplicationController Metrics](replicationcontroller-metrics.md)
5455
- [ResourceQuota Metrics](resourcequota-metrics.md)
5556
- [Role Metrics](role-metrics.md)
57+
- [RoleBinding Metrics](rolebinding-metrics.md)
5658
- [Secret Metrics](secret-metrics.md)
5759
- [Service Metrics](service-metrics.md)
5860
- [ServiceAccount Metrics](serviceaccount-metrics.md)

docs/cli-arguments.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ Usage of ./kube-state-metrics:
5050
--pod string Name of the pod that contains the kube-state-metrics container. When set, it is expected that --pod and --pod-namespace are both set. Most likely this should be passed via the downward API. This is used for auto-detecting sharding. If set, this has preference over statically configured sharding. This is experimental, it may be removed without notice.
5151
--pod-namespace string Name of the namespace of the pod specified by --pod. When set, it is expected that --pod and --pod-namespace are both set. Most likely this should be passed via the downward API. This is used for auto-detecting sharding. If set, this has preference over statically configured sharding. This is experimental, it may be removed without notice.
5252
--port int Port to expose metrics on. (default 8080)
53-
--resources string Comma-separated list of Resources to be enabled. Defaults to "certificatesigningrequests,clusterroles,configmaps,cronjobs,daemonsets,deployments,endpoints,horizontalpodautoscalers,ingresses,jobs,leases,limitranges,mutatingwebhookconfigurations,namespaces,networkpolicies,nodes,persistentvolumeclaims,persistentvolumes,poddisruptionbudgets,pods,replicasets,replicationcontrollers,resourcequotas,roles,secrets,serviceaccounts,services,statefulsets,storageclasses,validatingwebhookconfigurations,volumeattachments"
53+
--resources string Comma-separated list of Resources to be enabled. Defaults to "certificatesigningrequests,clusterrolebindings,clusterroles,configmaps,cronjobs,daemonsets,deployments,endpoints,horizontalpodautoscalers,ingresses,jobs,leases,limitranges,mutatingwebhookconfigurations,namespaces,networkpolicies,nodes,persistentvolumeclaims,persistentvolumes,poddisruptionbudgets,pods,replicasets,replicationcontrollers,resourcequotas,rolebindings,roles,secrets,serviceaccounts,services,statefulsets,storageclasses,validatingwebhookconfigurations,volumeattachments"
5454
--shard int32 The instances shard nominal (zero indexed) within the total number of shards. (default 0)
5555
--skip_headers If true, avoid header prefixes in the log messages
5656
--skip_log_headers If true, avoid headers when opening log files

docs/clusterrolebinding-metrics.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# ClusterRoleBinding Metrics
2+
3+
| Metric name| Metric type | Labels/tags | Status |
4+
| ---------- | ----------- | ----------- | ----------- |
5+
| kube_clusterrolebinding_annotations | Gauge | `clusterrolebinding`=<clusterrolebinding-name> | EXPERIMENTAL
6+
| kube_clusterrolebinding_labels | Gauge | `clusterrolebinding`=<clusterrolebinding-name> | EXPERIMENTAL
7+
| kube_clusterrolebinding_info | Gauge | `clusterrolebinding`=&lt;clusterrolebinding-name&gt; <br> `roleref-kind`=&lt;roleref-kind&gt; <br> `roleref-name`=&lt;roleref-name&gt; | EXPERIMENTAL
8+
| kube_clusterrolebinding_created | Gauge | `clusterrolebinding`=&lt;clusterrolebinding-name&gt; | EXPERIMENTAL |
9+
| kube_clusterrolebinding_metadata_resource_version | Gauge | `clusterrolebinding`=&lt;clusterrolebinding-name&gt; | EXPERIMENTAL |

docs/rolebinding-metrics.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# RoleBinding Metrics
2+
3+
| Metric name| Metric type | Labels/tags | Status |
4+
| ---------- | ----------- | ----------- | ----------- |
5+
| kube_rolebinding_annotations | Gauge | `rolebinding`=&lt;rolebinding-name&gt; <br> `namespace`=&lt;rolebinding-namespace&gt; | EXPERIMENTAL
6+
| kube_rolebinding_labels | Gauge | `rolebinding`=&lt;rolebinding-name&gt; <br> `namespace`=&lt;rolebinding-namespace&gt; | EXPERIMENTAL
7+
| kube_rolebinding_info | Gauge | `rolebinding`=&lt;rolebinding-name&gt; <br> `namespace`=&lt;rolebinding-namespace&gt; <br> `roleref-kind`=&lt;roleref-kind&gt; <br> `roleref-name`=&lt;roleref-name&gt;| EXPERIMENTAL
8+
| kube_rolebinding_created | Gauge | `rolebinding`=&lt;rolebinding-name&gt; <br> `namespace`=&lt;rolebinding-namespace&gt; | EXPERIMENTAL |
9+
| kube_rolebinding_metadata_resource_version | Gauge | `rolebinding`=&lt;rolebinding-name&gt; <br> `namespace`=&lt;rolebinding-namespace&gt; | EXPERIMENTAL |

examples/autosharding/cluster-role.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,9 @@ rules:
112112
- rbac.authorization.k8s.io
113113
resources:
114114
- clusterroles
115+
- clusterrolebindings
115116
- roles
117+
- rolesbindings
116118
verbs:
117119
- list
118120
- watch

examples/standard/cluster-role.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,9 @@ rules:
112112
- rbac.authorization.k8s.io
113113
resources:
114114
- clusterroles
115+
- clusterrolebindings
115116
- roles
117+
- rolesbindings
116118
verbs:
117119
- list
118120
- watch

internal/store/builder.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,7 @@ var availableStores = map[string]func(f *Builder) []cache.Store{
264264
"certificatesigningrequests": func(b *Builder) []cache.Store { return b.buildCsrStores() },
265265
"clusterroles": func(b *Builder) []cache.Store { return b.buildClusterRoleStores() },
266266
"configmaps": func(b *Builder) []cache.Store { return b.buildConfigMapStores() },
267+
"clusterrolebindings": func(b *Builder) []cache.Store { return b.buildClusterRoleBindingStores() },
267268
"cronjobs": func(b *Builder) []cache.Store { return b.buildCronJobStores() },
268269
"daemonsets": func(b *Builder) []cache.Store { return b.buildDaemonSetStores() },
269270
"deployments": func(b *Builder) []cache.Store { return b.buildDeploymentStores() },
@@ -285,6 +286,7 @@ var availableStores = map[string]func(f *Builder) []cache.Store{
285286
"replicationcontrollers": func(b *Builder) []cache.Store { return b.buildReplicationControllerStores() },
286287
"resourcequotas": func(b *Builder) []cache.Store { return b.buildResourceQuotaStores() },
287288
"roles": func(b *Builder) []cache.Store { return b.buildRoleStores() },
289+
"rolebindings": func(b *Builder) []cache.Store { return b.buildRoleBindingStores() },
288290
"secrets": func(b *Builder) []cache.Store { return b.buildSecretStores() },
289291
"serviceaccounts": func(b *Builder) []cache.Store { return b.buildServiceAccountStores() },
290292
"services": func(b *Builder) []cache.Store { return b.buildServiceStores() },
@@ -436,6 +438,14 @@ func (b *Builder) buildRoleStores() []cache.Store {
436438
return b.buildStoresFunc(roleMetricFamilies(b.allowAnnotationsList["roles"], b.allowLabelsList["roles"]), &rbacv1.Role{}, createRoleListWatch, b.useAPIServerCache)
437439
}
438440

441+
func (b *Builder) buildClusterRoleBindingStores() []cache.Store {
442+
return b.buildStoresFunc(clusterRoleBindingMetricFamilies(b.allowAnnotationsList["clusterrolebindings"], b.allowLabelsList["clusterrolebindings"]), &rbacv1.RoleBinding{}, createClusterRoleBindingListWatch, b.useAPIServerCache)
443+
}
444+
445+
func (b *Builder) buildRoleBindingStores() []cache.Store {
446+
return b.buildStoresFunc(roleBindingMetricFamilies(b.allowAnnotationsList["rolebindings"], b.allowLabelsList["rolebindings"]), &rbacv1.RoleBinding{}, createRoleBindingListWatch, b.useAPIServerCache)
447+
}
448+
439449
func (b *Builder) buildStores(
440450
metricFamilies []generator.FamilyGenerator,
441451
expectedType interface{},

internal/store/clusterrolebinding.go

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
/*
2+
Copyright 2022 The Kubernetes Authors All rights reserved.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package store
18+
19+
import (
20+
"context"
21+
22+
rbacv1 "k8s.io/api/rbac/v1"
23+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
24+
"k8s.io/apimachinery/pkg/runtime"
25+
"k8s.io/apimachinery/pkg/watch"
26+
clientset "k8s.io/client-go/kubernetes"
27+
"k8s.io/client-go/tools/cache"
28+
29+
"k8s.io/kube-state-metrics/v2/pkg/metric"
30+
generator "k8s.io/kube-state-metrics/v2/pkg/metric_generator"
31+
)
32+
33+
var (
34+
descClusterRoleBindingAnnotationsName = "kube_clusterrolebinding_annotations"
35+
descClusterRoleBindingAnnotationsHelp = "Kubernetes annotations converted to Prometheus labels."
36+
descClusterRoleBindingLabelsName = "kube_clusterrolebinding_labels"
37+
descClusterRoleBindingLabelsHelp = "Kubernetes labels converted to Prometheus labels."
38+
descClusterRoleBindingLabelsDefaultLabels = []string{"clusterrolebinding"}
39+
)
40+
41+
func clusterRoleBindingMetricFamilies(allowAnnotationsList, allowLabelsList []string) []generator.FamilyGenerator {
42+
return []generator.FamilyGenerator{
43+
*generator.NewFamilyGenerator(
44+
descClusterRoleBindingAnnotationsName,
45+
descClusterRoleBindingAnnotationsHelp,
46+
metric.Gauge,
47+
"",
48+
wrapClusterRoleBindingFunc(func(r *rbacv1.ClusterRoleBinding) *metric.Family {
49+
annotationKeys, annotationValues := createPrometheusLabelKeysValues("annotation", r.Annotations, allowAnnotationsList)
50+
return &metric.Family{
51+
Metrics: []*metric.Metric{
52+
{
53+
LabelKeys: annotationKeys,
54+
LabelValues: annotationValues,
55+
Value: 1,
56+
},
57+
},
58+
}
59+
}),
60+
),
61+
*generator.NewFamilyGenerator(
62+
descClusterRoleBindingLabelsName,
63+
descClusterRoleBindingLabelsHelp,
64+
metric.Gauge,
65+
"",
66+
wrapClusterRoleBindingFunc(func(r *rbacv1.ClusterRoleBinding) *metric.Family {
67+
labelKeys, labelValues := createPrometheusLabelKeysValues("label", r.Labels, allowLabelsList)
68+
return &metric.Family{
69+
Metrics: []*metric.Metric{
70+
{
71+
LabelKeys: labelKeys,
72+
LabelValues: labelValues,
73+
Value: 1,
74+
},
75+
},
76+
}
77+
}),
78+
),
79+
*generator.NewFamilyGenerator(
80+
"kube_clusterrolebinding_info",
81+
"Information about clusterrolebinding.",
82+
metric.Gauge,
83+
"",
84+
wrapClusterRoleBindingFunc(func(r *rbacv1.ClusterRoleBinding) *metric.Family {
85+
labelKeys := []string{"roleref_kind", "roleref_name"}
86+
labelValues := []string{r.RoleRef.Kind, r.RoleRef.Name}
87+
return &metric.Family{
88+
Metrics: []*metric.Metric{{
89+
LabelKeys: labelKeys,
90+
LabelValues: labelValues,
91+
Value: 1,
92+
}},
93+
}
94+
}),
95+
),
96+
*generator.NewFamilyGenerator(
97+
"kube_clusterrolebinding_created",
98+
"Unix creation timestamp",
99+
metric.Gauge,
100+
"",
101+
wrapClusterRoleBindingFunc(func(r *rbacv1.ClusterRoleBinding) *metric.Family {
102+
ms := []*metric.Metric{}
103+
104+
if !r.CreationTimestamp.IsZero() {
105+
ms = append(ms, &metric.Metric{
106+
LabelKeys: []string{},
107+
LabelValues: []string{},
108+
Value: float64(r.CreationTimestamp.Unix()),
109+
})
110+
}
111+
112+
return &metric.Family{
113+
Metrics: ms,
114+
}
115+
}),
116+
),
117+
*generator.NewFamilyGenerator(
118+
"kube_clusterrolebinding_metadata_resource_version",
119+
"Resource version representing a specific version of the clusterrolebinding.",
120+
metric.Gauge,
121+
"",
122+
wrapClusterRoleBindingFunc(func(r *rbacv1.ClusterRoleBinding) *metric.Family {
123+
return &metric.Family{
124+
Metrics: resourceVersionMetric(r.ObjectMeta.ResourceVersion),
125+
}
126+
}),
127+
),
128+
}
129+
}
130+
131+
func createClusterRoleBindingListWatch(kubeClient clientset.Interface, ns string, fieldSelector string) cache.ListerWatcher {
132+
return &cache.ListWatch{
133+
ListFunc: func(opts metav1.ListOptions) (runtime.Object, error) {
134+
opts.FieldSelector = fieldSelector
135+
return kubeClient.RbacV1().ClusterRoleBindings().List(context.TODO(), opts)
136+
},
137+
WatchFunc: func(opts metav1.ListOptions) (watch.Interface, error) {
138+
opts.FieldSelector = fieldSelector
139+
return kubeClient.RbacV1().ClusterRoleBindings().Watch(context.TODO(), opts)
140+
},
141+
}
142+
}
143+
144+
func wrapClusterRoleBindingFunc(f func(*rbacv1.ClusterRoleBinding) *metric.Family) func(interface{}) *metric.Family {
145+
return func(obj interface{}) *metric.Family {
146+
clusterrolebinding := obj.(*rbacv1.ClusterRoleBinding)
147+
148+
metricFamily := f(clusterrolebinding)
149+
150+
for _, m := range metricFamily.Metrics {
151+
m.LabelKeys, m.LabelValues = mergeKeyValues(descClusterRoleBindingLabelsDefaultLabels, []string{clusterrolebinding.Name}, m.LabelKeys, m.LabelValues)
152+
}
153+
154+
return metricFamily
155+
}
156+
}
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
/*
2+
Copyright 2022 The Kubernetes Authors All rights reserved.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package store
18+
19+
import (
20+
"testing"
21+
22+
rbacv1 "k8s.io/api/rbac/v1"
23+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
24+
25+
generator "k8s.io/kube-state-metrics/v2/pkg/metric_generator"
26+
)
27+
28+
func TestClusterRoleBindingStore(t *testing.T) {
29+
startTime := 1501569018
30+
metav1StartTime := metav1.Unix(int64(startTime), 0)
31+
32+
cases := []generateMetricsTestCase{
33+
{
34+
AllowAnnotationsList: []string{
35+
"app.k8s.io/owner",
36+
},
37+
AllowLabelsList: []string{
38+
"app",
39+
},
40+
Obj: &rbacv1.ClusterRoleBinding{
41+
ObjectMeta: metav1.ObjectMeta{
42+
Name: "clusterrolebinding1",
43+
ResourceVersion: "BBBBB",
44+
Annotations: map[string]string{
45+
"app": "mysql-server",
46+
"app.k8s.io/owner": "@foo",
47+
},
48+
Labels: map[string]string{
49+
"excluded": "me",
50+
"app": "mysql-server",
51+
},
52+
},
53+
RoleRef: rbacv1.RoleRef{
54+
APIGroup: "rbac.authorization.k8s.io",
55+
Kind: "Role",
56+
Name: "role",
57+
},
58+
},
59+
Want: `
60+
# HELP kube_clusterrolebinding_annotations Kubernetes annotations converted to Prometheus labels.
61+
# HELP kube_clusterrolebinding_labels Kubernetes labels converted to Prometheus labels.
62+
# HELP kube_clusterrolebinding_info Information about clusterrolebinding.
63+
# HELP kube_clusterrolebinding_metadata_resource_version Resource version representing a specific version of the clusterrolebinding.
64+
# TYPE kube_clusterrolebinding_annotations gauge
65+
# TYPE kube_clusterrolebinding_labels gauge
66+
# TYPE kube_clusterrolebinding_info gauge
67+
# TYPE kube_clusterrolebinding_metadata_resource_version gauge
68+
kube_clusterrolebinding_annotations{annotation_app_k8s_io_owner="@foo",clusterrolebinding="clusterrolebinding1"} 1
69+
kube_clusterrolebinding_labels{clusterrolebinding="clusterrolebinding1",label_app="mysql-server"} 1
70+
kube_clusterrolebinding_info{clusterrolebinding="clusterrolebinding1",roleref_kind="Role",roleref_name="role"} 1
71+
`,
72+
MetricNames: []string{
73+
"kube_clusterrolebinding_annotations",
74+
"kube_clusterrolebinding_labels",
75+
"kube_clusterrolebinding_info",
76+
"kube_clusterrolebinding_metadata_resource_version",
77+
},
78+
},
79+
{
80+
Obj: &rbacv1.ClusterRoleBinding{
81+
ObjectMeta: metav1.ObjectMeta{
82+
Name: "clusterrolebinding2",
83+
CreationTimestamp: metav1StartTime,
84+
ResourceVersion: "10596",
85+
},
86+
RoleRef: rbacv1.RoleRef{
87+
APIGroup: "rbac.authorization.k8s.io",
88+
Kind: "Role",
89+
Name: "role",
90+
},
91+
},
92+
Want: `
93+
# HELP kube_clusterrolebinding_created Unix creation timestamp
94+
# HELP kube_clusterrolebinding_info Information about clusterrolebinding.
95+
# HELP kube_clusterrolebinding_metadata_resource_version Resource version representing a specific version of the clusterrolebinding.
96+
# TYPE kube_clusterrolebinding_created gauge
97+
# TYPE kube_clusterrolebinding_info gauge
98+
# TYPE kube_clusterrolebinding_metadata_resource_version gauge
99+
kube_clusterrolebinding_info{clusterrolebinding="clusterrolebinding2",roleref_kind="Role",roleref_name="role"} 1
100+
kube_clusterrolebinding_created{clusterrolebinding="clusterrolebinding2"} 1.501569018e+09
101+
kube_clusterrolebinding_metadata_resource_version{clusterrolebinding="clusterrolebinding2"} 10596
102+
`,
103+
MetricNames: []string{"kube_clusterrolebinding_info", "kube_clusterrolebinding_created", "kube_clusterrolebinding_metadata_resource_version"},
104+
},
105+
}
106+
for i, c := range cases {
107+
c.Func = generator.ComposeMetricGenFuncs(clusterRoleBindingMetricFamilies(c.AllowAnnotationsList, c.AllowLabelsList))
108+
c.Headers = generator.ExtractMetricFamilyHeaders(clusterRoleBindingMetricFamilies(c.AllowAnnotationsList, c.AllowLabelsList))
109+
if err := c.run(); err != nil {
110+
t.Errorf("unexpected collecting result in %vth run:\n%s", i, err)
111+
}
112+
}
113+
}

0 commit comments

Comments
 (0)