Skip to content

Commit

Permalink
add rolebinding metrics
Browse files Browse the repository at this point in the history
  • Loading branch information
kaitoii11 committed Aug 6, 2022
1 parent fad76e4 commit 51df8fe
Show file tree
Hide file tree
Showing 15 changed files with 602 additions and 1 deletion.
2 changes: 2 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ Per group of metrics there is one file for each metrics. See each file for speci

- [CertificateSigningRequest Metrics](certificatesigningrequest-metrics.md)
- [ClusterRole Metrics](clusterrole-metrics.md)
- [ClusterRoleBinding Metrics](clusterrolebinding-metrics.md)
- [ConfigMap Metrics](configmap-metrics.md)
- [CronJob Metrics](cronjob-metrics.md)
- [DaemonSet Metrics](daemonset-metrics.md)
Expand All @@ -53,6 +54,7 @@ Per group of metrics there is one file for each metrics. See each file for speci
- [ReplicationController Metrics](replicationcontroller-metrics.md)
- [ResourceQuota Metrics](resourcequota-metrics.md)
- [Role Metrics](role-metrics.md)
- [RoleBinding Metrics](rolebinding-metrics.md)
- [Secret Metrics](secret-metrics.md)
- [Service Metrics](service-metrics.md)
- [ServiceAccount Metrics](serviceaccount-metrics.md)
Expand Down
2 changes: 1 addition & 1 deletion docs/cli-arguments.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ Usage of ./kube-state-metrics:
--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.
--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.
--port int Port to expose metrics on. (default 8080)
--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"
--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"
--shard int32 The instances shard nominal (zero indexed) within the total number of shards. (default 0)
--skip_headers If true, avoid header prefixes in the log messages
--skip_log_headers If true, avoid headers when opening log files
Expand Down
9 changes: 9 additions & 0 deletions docs/clusterrolebinding-metrics.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# ClusterRoleBinding Metrics

| Metric name| Metric type | Labels/tags | Status |
| ---------- | ----------- | ----------- | ----------- |
| kube_clusterrolebinding_annotations | Gauge | `clusterrolebinding`=<clusterrolebinding-name> | EXPERIMENTAL
| kube_clusterrolebinding_labels | Gauge | `clusterrolebinding`=<clusterrolebinding-name> | EXPERIMENTAL
| kube_clusterrolebinding_info | Gauge | `clusterrolebinding`=&lt;clusterrolebinding-name&gt; <br> `roleref-kind`=&lt;roleref-kind&gt; <br> `roleref-name`=&lt;roleref-name&gt; | EXPERIMENTAL
| kube_clusterrolebinding_created | Gauge | `clusterrolebinding`=&lt;clusterrolebinding-name&gt; | EXPERIMENTAL |
| kube_clusterrolebinding_metadata_resource_version | Gauge | `clusterrolebinding`=&lt;clusterrolebinding-name&gt; | EXPERIMENTAL |
9 changes: 9 additions & 0 deletions docs/rolebinding-metrics.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# RoleBinding Metrics

| Metric name| Metric type | Labels/tags | Status |
| ---------- | ----------- | ----------- | ----------- |
| kube_rolebinding_annotations | Gauge | `rolebinding`=&lt;rolebinding-name&gt; <br> `namespace`=&lt;rolebinding-namespace&gt; | EXPERIMENTAL
| kube_rolebinding_labels | Gauge | `rolebinding`=&lt;rolebinding-name&gt; <br> `namespace`=&lt;rolebinding-namespace&gt; | EXPERIMENTAL
| 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
| kube_rolebinding_created | Gauge | `rolebinding`=&lt;rolebinding-name&gt; <br> `namespace`=&lt;rolebinding-namespace&gt; | EXPERIMENTAL |
| kube_rolebinding_metadata_resource_version | Gauge | `rolebinding`=&lt;rolebinding-name&gt; <br> `namespace`=&lt;rolebinding-namespace&gt; | EXPERIMENTAL |
2 changes: 2 additions & 0 deletions examples/autosharding/cluster-role.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,9 @@ rules:
- rbac.authorization.k8s.io
resources:
- clusterroles
- clusterrolebindings
- roles
- rolesbindings
verbs:
- list
- watch
2 changes: 2 additions & 0 deletions examples/standard/cluster-role.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,9 @@ rules:
- rbac.authorization.k8s.io
resources:
- clusterroles
- clusterrolebindings
- roles
- rolesbindings
verbs:
- list
- watch
10 changes: 10 additions & 0 deletions internal/store/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,7 @@ var availableStores = map[string]func(f *Builder) []cache.Store{
"certificatesigningrequests": func(b *Builder) []cache.Store { return b.buildCsrStores() },
"clusterroles": func(b *Builder) []cache.Store { return b.buildClusterRoleStores() },
"configmaps": func(b *Builder) []cache.Store { return b.buildConfigMapStores() },
"clusterrolebindings": func(b *Builder) []cache.Store { return b.buildClusterRoleBindingStores() },
"cronjobs": func(b *Builder) []cache.Store { return b.buildCronJobStores() },
"daemonsets": func(b *Builder) []cache.Store { return b.buildDaemonSetStores() },
"deployments": func(b *Builder) []cache.Store { return b.buildDeploymentStores() },
Expand All @@ -285,6 +286,7 @@ var availableStores = map[string]func(f *Builder) []cache.Store{
"replicationcontrollers": func(b *Builder) []cache.Store { return b.buildReplicationControllerStores() },
"resourcequotas": func(b *Builder) []cache.Store { return b.buildResourceQuotaStores() },
"roles": func(b *Builder) []cache.Store { return b.buildRoleStores() },
"rolebindings": func(b *Builder) []cache.Store { return b.buildRoleBindingStores() },
"secrets": func(b *Builder) []cache.Store { return b.buildSecretStores() },
"serviceaccounts": func(b *Builder) []cache.Store { return b.buildServiceAccountStores() },
"services": func(b *Builder) []cache.Store { return b.buildServiceStores() },
Expand Down Expand Up @@ -436,6 +438,14 @@ func (b *Builder) buildRoleStores() []cache.Store {
return b.buildStoresFunc(roleMetricFamilies(b.allowAnnotationsList["roles"], b.allowLabelsList["roles"]), &rbacv1.Role{}, createRoleListWatch, b.useAPIServerCache)
}

func (b *Builder) buildClusterRoleBindingStores() []cache.Store {
return b.buildStoresFunc(clusterRoleBindingMetricFamilies(b.allowAnnotationsList["clusterrolebindings"], b.allowLabelsList["clusterrolebindings"]), &rbacv1.RoleBinding{}, createClusterRoleBindingListWatch, b.useAPIServerCache)
}

func (b *Builder) buildRoleBindingStores() []cache.Store {
return b.buildStoresFunc(roleBindingMetricFamilies(b.allowAnnotationsList["rolebindings"], b.allowLabelsList["rolebindings"]), &rbacv1.RoleBinding{}, createRoleBindingListWatch, b.useAPIServerCache)
}

func (b *Builder) buildStores(
metricFamilies []generator.FamilyGenerator,
expectedType interface{},
Expand Down
156 changes: 156 additions & 0 deletions internal/store/clusterrolebinding.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
/*
Copyright 2022 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"

rbacv1 "k8s.io/api/rbac/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/watch"
clientset "k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/cache"

"k8s.io/kube-state-metrics/v2/pkg/metric"
generator "k8s.io/kube-state-metrics/v2/pkg/metric_generator"
)

var (
descClusterRoleBindingAnnotationsName = "kube_clusterrolebinding_annotations"
descClusterRoleBindingAnnotationsHelp = "Kubernetes annotations converted to Prometheus labels."
descClusterRoleBindingLabelsName = "kube_clusterrolebinding_labels"
descClusterRoleBindingLabelsHelp = "Kubernetes labels converted to Prometheus labels."
descClusterRoleBindingLabelsDefaultLabels = []string{"clusterrolebinding"}
)

func clusterRoleBindingMetricFamilies(allowAnnotationsList, allowLabelsList []string) []generator.FamilyGenerator {
return []generator.FamilyGenerator{
*generator.NewFamilyGenerator(
descClusterRoleBindingAnnotationsName,
descClusterRoleBindingAnnotationsHelp,
metric.Gauge,
"",
wrapClusterRoleBindingFunc(func(r *rbacv1.ClusterRoleBinding) *metric.Family {
annotationKeys, annotationValues := createPrometheusLabelKeysValues("annotation", r.Annotations, allowAnnotationsList)
return &metric.Family{
Metrics: []*metric.Metric{
{
LabelKeys: annotationKeys,
LabelValues: annotationValues,
Value: 1,
},
},
}
}),
),
*generator.NewFamilyGenerator(
descClusterRoleBindingLabelsName,
descClusterRoleBindingLabelsHelp,
metric.Gauge,
"",
wrapClusterRoleBindingFunc(func(r *rbacv1.ClusterRoleBinding) *metric.Family {
labelKeys, labelValues := createPrometheusLabelKeysValues("label", r.Labels, allowLabelsList)
return &metric.Family{
Metrics: []*metric.Metric{
{
LabelKeys: labelKeys,
LabelValues: labelValues,
Value: 1,
},
},
}
}),
),
*generator.NewFamilyGenerator(
"kube_clusterrolebinding_info",
"Information about clusterrolebinding.",
metric.Gauge,
"",
wrapClusterRoleBindingFunc(func(r *rbacv1.ClusterRoleBinding) *metric.Family {
labelKeys := []string{"roleref_kind", "roleref_name"}
labelValues := []string{r.RoleRef.Kind, r.RoleRef.Name}
return &metric.Family{
Metrics: []*metric.Metric{{
LabelKeys: labelKeys,
LabelValues: labelValues,
Value: 1,
}},
}
}),
),
*generator.NewFamilyGenerator(
"kube_clusterrolebinding_created",
"Unix creation timestamp",
metric.Gauge,
"",
wrapClusterRoleBindingFunc(func(r *rbacv1.ClusterRoleBinding) *metric.Family {
ms := []*metric.Metric{}

if !r.CreationTimestamp.IsZero() {
ms = append(ms, &metric.Metric{
LabelKeys: []string{},
LabelValues: []string{},
Value: float64(r.CreationTimestamp.Unix()),
})
}

return &metric.Family{
Metrics: ms,
}
}),
),
*generator.NewFamilyGenerator(
"kube_clusterrolebinding_metadata_resource_version",
"Resource version representing a specific version of the clusterrolebinding.",
metric.Gauge,
"",
wrapClusterRoleBindingFunc(func(r *rbacv1.ClusterRoleBinding) *metric.Family {
return &metric.Family{
Metrics: resourceVersionMetric(r.ObjectMeta.ResourceVersion),
}
}),
),
}
}

func createClusterRoleBindingListWatch(kubeClient clientset.Interface, ns string, fieldSelector string) cache.ListerWatcher {
return &cache.ListWatch{
ListFunc: func(opts metav1.ListOptions) (runtime.Object, error) {
opts.FieldSelector = fieldSelector
return kubeClient.RbacV1().ClusterRoleBindings().List(context.TODO(), opts)
},
WatchFunc: func(opts metav1.ListOptions) (watch.Interface, error) {
opts.FieldSelector = fieldSelector
return kubeClient.RbacV1().ClusterRoleBindings().Watch(context.TODO(), opts)
},
}
}

func wrapClusterRoleBindingFunc(f func(*rbacv1.ClusterRoleBinding) *metric.Family) func(interface{}) *metric.Family {
return func(obj interface{}) *metric.Family {
clusterrolebinding := obj.(*rbacv1.ClusterRoleBinding)

metricFamily := f(clusterrolebinding)

for _, m := range metricFamily.Metrics {
m.LabelKeys, m.LabelValues = mergeKeyValues(descClusterRoleBindingLabelsDefaultLabels, []string{clusterrolebinding.Name}, m.LabelKeys, m.LabelValues)
}

return metricFamily
}
}
113 changes: 113 additions & 0 deletions internal/store/clusterrolebinding_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
/*
Copyright 2022 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 (
"testing"

rbacv1 "k8s.io/api/rbac/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

generator "k8s.io/kube-state-metrics/v2/pkg/metric_generator"
)

func TestClusterRoleBindingStore(t *testing.T) {
startTime := 1501569018
metav1StartTime := metav1.Unix(int64(startTime), 0)

cases := []generateMetricsTestCase{
{
AllowAnnotationsList: []string{
"app.k8s.io/owner",
},
AllowLabelsList: []string{
"app",
},
Obj: &rbacv1.ClusterRoleBinding{
ObjectMeta: metav1.ObjectMeta{
Name: "clusterrolebinding1",
ResourceVersion: "BBBBB",
Annotations: map[string]string{
"app": "mysql-server",
"app.k8s.io/owner": "@foo",
},
Labels: map[string]string{
"excluded": "me",
"app": "mysql-server",
},
},
RoleRef: rbacv1.RoleRef{
APIGroup: "rbac.authorization.k8s.io",
Kind: "Role",
Name: "role",
},
},
Want: `
# HELP kube_clusterrolebinding_annotations Kubernetes annotations converted to Prometheus labels.
# HELP kube_clusterrolebinding_labels Kubernetes labels converted to Prometheus labels.
# HELP kube_clusterrolebinding_info Information about clusterrolebinding.
# HELP kube_clusterrolebinding_metadata_resource_version Resource version representing a specific version of the clusterrolebinding.
# TYPE kube_clusterrolebinding_annotations gauge
# TYPE kube_clusterrolebinding_labels gauge
# TYPE kube_clusterrolebinding_info gauge
# TYPE kube_clusterrolebinding_metadata_resource_version gauge
kube_clusterrolebinding_annotations{annotation_app_k8s_io_owner="@foo",clusterrolebinding="clusterrolebinding1"} 1
kube_clusterrolebinding_labels{clusterrolebinding="clusterrolebinding1",label_app="mysql-server"} 1
kube_clusterrolebinding_info{clusterrolebinding="clusterrolebinding1",roleref_kind="Role",roleref_name="role"} 1
`,
MetricNames: []string{
"kube_clusterrolebinding_annotations",
"kube_clusterrolebinding_labels",
"kube_clusterrolebinding_info",
"kube_clusterrolebinding_metadata_resource_version",
},
},
{
Obj: &rbacv1.ClusterRoleBinding{
ObjectMeta: metav1.ObjectMeta{
Name: "clusterrolebinding2",
CreationTimestamp: metav1StartTime,
ResourceVersion: "10596",
},
RoleRef: rbacv1.RoleRef{
APIGroup: "rbac.authorization.k8s.io",
Kind: "Role",
Name: "role",
},
},
Want: `
# HELP kube_clusterrolebinding_created Unix creation timestamp
# HELP kube_clusterrolebinding_info Information about clusterrolebinding.
# HELP kube_clusterrolebinding_metadata_resource_version Resource version representing a specific version of the clusterrolebinding.
# TYPE kube_clusterrolebinding_created gauge
# TYPE kube_clusterrolebinding_info gauge
# TYPE kube_clusterrolebinding_metadata_resource_version gauge
kube_clusterrolebinding_info{clusterrolebinding="clusterrolebinding2",roleref_kind="Role",roleref_name="role"} 1
kube_clusterrolebinding_created{clusterrolebinding="clusterrolebinding2"} 1.501569018e+09
kube_clusterrolebinding_metadata_resource_version{clusterrolebinding="clusterrolebinding2"} 10596
`,
MetricNames: []string{"kube_clusterrolebinding_info", "kube_clusterrolebinding_created", "kube_clusterrolebinding_metadata_resource_version"},
},
}
for i, c := range cases {
c.Func = generator.ComposeMetricGenFuncs(clusterRoleBindingMetricFamilies(c.AllowAnnotationsList, c.AllowLabelsList))
c.Headers = generator.ExtractMetricFamilyHeaders(clusterRoleBindingMetricFamilies(c.AllowAnnotationsList, c.AllowLabelsList))
if err := c.run(); err != nil {
t.Errorf("unexpected collecting result in %vth run:\n%s", i, err)
}
}
}
Loading

0 comments on commit 51df8fe

Please sign in to comment.