Add Metrics About StorageClass
This commit is contained in:
parent
332c90f3be
commit
c18dfa26cf
|
|
@ -60,6 +60,7 @@ Per group of metrics there is one file for each metrics. See each file for speci
|
||||||
- [ResourceQuota Metrics](resourcequota-metrics.md)
|
- [ResourceQuota Metrics](resourcequota-metrics.md)
|
||||||
- [Service Metrics](service-metrics.md)
|
- [Service Metrics](service-metrics.md)
|
||||||
- [StatefulSet Metrics](statefulset-metrics.md)
|
- [StatefulSet Metrics](statefulset-metrics.md)
|
||||||
|
- [StorageClass Metrics](storageclass-metrics.md)
|
||||||
- [Namespace Metrics](namespace-metrics.md)
|
- [Namespace Metrics](namespace-metrics.md)
|
||||||
- [Horizontal Pod Autoscaler Metrics](horizontalpodautoscaler-metrics.md)
|
- [Horizontal Pod Autoscaler Metrics](horizontalpodautoscaler-metrics.md)
|
||||||
- [Endpoint Metrics](endpoint-metrics.md)
|
- [Endpoint Metrics](endpoint-metrics.md)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
# StorageClass Metrics
|
||||||
|
|
||||||
|
| Metric name| Metric type | Labels/tags | Status |
|
||||||
|
| ---------- | ----------- | ----------- | ----------- |
|
||||||
|
| kube_storageclass_info | Gauge | `storageclass`=<storageclass-name> <br> `provisioner`=<storageclass-provisioner> <br> `reclaimPolicy`=<storageclass-reclaimPolicy> <br> `volumeBindingMode`=<storageclass-volumeBindingMode> | STABLE |
|
||||||
|
| kube_storageclass_labels | Gauge | `storageclass`=<storageclass-name> <br> `label_STORAGECLASS_LABEL`=<STORAGECLASS_LABEL> | STABLE |
|
||||||
|
| kube_storageclass_created | Gauge | `storageclass`=<storageclass-name> | STABLE |
|
||||||
|
| kube_storageclass_metadata_resource_version | Gauge | `storageclass`=<storageclass-name> <br> `resource_version`=<storageclass-resource-version> | STABLE |
|
||||||
|
|
@ -31,6 +31,7 @@ import (
|
||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
extensions "k8s.io/api/extensions/v1beta1"
|
extensions "k8s.io/api/extensions/v1beta1"
|
||||||
policy "k8s.io/api/policy/v1beta1"
|
policy "k8s.io/api/policy/v1beta1"
|
||||||
|
storagev1 "k8s.io/api/storage/v1"
|
||||||
clientset "k8s.io/client-go/kubernetes"
|
clientset "k8s.io/client-go/kubernetes"
|
||||||
"k8s.io/client-go/tools/cache"
|
"k8s.io/client-go/tools/cache"
|
||||||
coll "k8s.io/kube-state-metrics/pkg/collector"
|
coll "k8s.io/kube-state-metrics/pkg/collector"
|
||||||
|
|
@ -135,6 +136,7 @@ var availableCollectors = map[string]func(f *Builder) *coll.Collector{
|
||||||
"secrets": func(b *Builder) *coll.Collector { return b.buildSecretCollector() },
|
"secrets": func(b *Builder) *coll.Collector { return b.buildSecretCollector() },
|
||||||
"services": func(b *Builder) *coll.Collector { return b.buildServiceCollector() },
|
"services": func(b *Builder) *coll.Collector { return b.buildServiceCollector() },
|
||||||
"statefulsets": func(b *Builder) *coll.Collector { return b.buildStatefulSetCollector() },
|
"statefulsets": func(b *Builder) *coll.Collector { return b.buildStatefulSetCollector() },
|
||||||
|
"storageclasses": func(b *Builder) *coll.Collector { return b.buildStorageClassCollector() },
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Builder) buildConfigMapCollector() *coll.Collector {
|
func (b *Builder) buildConfigMapCollector() *coll.Collector {
|
||||||
|
|
@ -217,6 +219,10 @@ func (b *Builder) buildStatefulSetCollector() *coll.Collector {
|
||||||
return b.buildCollector(statefulSetMetricFamilies, &appsv1.StatefulSet{}, createStatefulSetListWatch)
|
return b.buildCollector(statefulSetMetricFamilies, &appsv1.StatefulSet{}, createStatefulSetListWatch)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *Builder) buildStorageClassCollector() *coll.Collector {
|
||||||
|
return b.buildCollector(storageClassMetricFamilies, &storagev1.StorageClass{}, createStorageClassListWatch)
|
||||||
|
}
|
||||||
|
|
||||||
func (b *Builder) buildPodCollector() *coll.Collector {
|
func (b *Builder) buildPodCollector() *coll.Collector {
|
||||||
return b.buildCollector(podMetricFamilies, &v1.Pod{}, createPodListWatch)
|
return b.buildCollector(podMetricFamilies, &v1.Pod{}, createPodListWatch)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,122 @@
|
||||||
|
/*
|
||||||
|
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 collector
|
||||||
|
|
||||||
|
import (
|
||||||
|
"k8s.io/kube-state-metrics/pkg/metric"
|
||||||
|
|
||||||
|
storagev1 "k8s.io/api/storage/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"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
descStorageClassLabelsName = "kube_storageclass_labels"
|
||||||
|
descStorageClassLabelsHelp = "Kubernetes labels converted to Prometheus labels."
|
||||||
|
descStorageClassLabelsDefaultLabels = []string{"storageclass"}
|
||||||
|
|
||||||
|
storageClassMetricFamilies = []metric.FamilyGenerator{
|
||||||
|
{
|
||||||
|
Name: "kube_storageclass_info",
|
||||||
|
Type: metric.Gauge,
|
||||||
|
Help: "Information about storageclass.",
|
||||||
|
GenerateFunc: wrapStorageClassFunc(func(s *storagev1.StorageClass) *metric.Family {
|
||||||
|
m := metric.Metric{
|
||||||
|
LabelKeys: []string{"provisioner", "reclaimPolicy", "volumeBindingMode"},
|
||||||
|
LabelValues: []string{s.Provisioner, string(*s.ReclaimPolicy), string(*s.VolumeBindingMode)},
|
||||||
|
Value: 1,
|
||||||
|
}
|
||||||
|
return &metric.Family{Metrics: []*metric.Metric{&m}}
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "kube_storageclass_created",
|
||||||
|
Type: metric.Gauge,
|
||||||
|
Help: "Unix creation timestamp",
|
||||||
|
GenerateFunc: wrapStorageClassFunc(func(s *storagev1.StorageClass) *metric.Family {
|
||||||
|
ms := []*metric.Metric{}
|
||||||
|
if !s.CreationTimestamp.IsZero() {
|
||||||
|
ms = append(ms, &metric.Metric{
|
||||||
|
Value: float64(s.CreationTimestamp.Unix()),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return &metric.Family{
|
||||||
|
Metrics: ms,
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "kube_storageclass_metadata_resource_version",
|
||||||
|
Type: metric.Gauge,
|
||||||
|
Help: "Resource version representing a specific version of storageclass.",
|
||||||
|
GenerateFunc: wrapStorageClassFunc(func(s *storagev1.StorageClass) *metric.Family {
|
||||||
|
return &metric.Family{
|
||||||
|
Metrics: []*metric.Metric{
|
||||||
|
{
|
||||||
|
LabelKeys: []string{"resource_version"},
|
||||||
|
LabelValues: []string{s.ObjectMeta.ResourceVersion},
|
||||||
|
Value: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: descStorageClassLabelsName,
|
||||||
|
Type: metric.Gauge,
|
||||||
|
Help: descStorageClassLabelsHelp,
|
||||||
|
GenerateFunc: wrapStorageClassFunc(func(s *storagev1.StorageClass) *metric.Family {
|
||||||
|
labelKeys, labelValues := kubeLabelsToPrometheusLabels(s.Labels)
|
||||||
|
return &metric.Family{
|
||||||
|
Metrics: []*metric.Metric{
|
||||||
|
{
|
||||||
|
LabelKeys: labelKeys,
|
||||||
|
LabelValues: labelValues,
|
||||||
|
Value: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func wrapStorageClassFunc(f func(*storagev1.StorageClass) *metric.Family) func(interface{}) *metric.Family {
|
||||||
|
return func(obj interface{}) *metric.Family {
|
||||||
|
storageClass := obj.(*storagev1.StorageClass)
|
||||||
|
|
||||||
|
metricFamily := f(storageClass)
|
||||||
|
|
||||||
|
for _, m := range metricFamily.Metrics {
|
||||||
|
m.LabelKeys = append(descStorageClassLabelsDefaultLabels, m.LabelKeys...)
|
||||||
|
m.LabelValues = append([]string{storageClass.Name}, m.LabelValues...)
|
||||||
|
}
|
||||||
|
|
||||||
|
return metricFamily
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func createStorageClassListWatch(kubeClient clientset.Interface, ns string) cache.ListerWatcher {
|
||||||
|
return &cache.ListWatch{
|
||||||
|
ListFunc: func(opts metav1.ListOptions) (runtime.Object, error) {
|
||||||
|
return kubeClient.StorageV1().StorageClasses().List(opts)
|
||||||
|
},
|
||||||
|
WatchFunc: func(opts metav1.ListOptions) (watch.Interface, error) {
|
||||||
|
return kubeClient.StorageV1().StorageClasses().Watch(opts)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,121 @@
|
||||||
|
/*
|
||||||
|
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 collector
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
v1 "k8s.io/api/core/v1"
|
||||||
|
storagev1 "k8s.io/api/storage/v1"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/kube-state-metrics/pkg/metric"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestStorageClassCollector(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.
|
||||||
|
|
||||||
|
startTime := 1501569018
|
||||||
|
metav1StartTime := metav1.Unix(int64(startTime), 0)
|
||||||
|
reclaimPolicy := v1.PersistentVolumeReclaimDelete
|
||||||
|
volumeBindingMode := storagev1.VolumeBindingImmediate
|
||||||
|
|
||||||
|
const metadata = `
|
||||||
|
# HELP kube_storageclass_labels Kubernetes labels converted to Prometheus labels.
|
||||||
|
# TYPE kube_storageclass_labels gauge
|
||||||
|
# HELP kube_storageclass_info Information about storageclass.
|
||||||
|
# TYPE kube_storageclass_info gauge
|
||||||
|
# HELP kube_storageclass_created Unix creation timestamp
|
||||||
|
# TYPE kube_storageclass_created gauge
|
||||||
|
# HELP kube_storageclass_metadata_resource_version Resource version representing a specific version of secret.
|
||||||
|
# TYPE kube_storageclass_metadata_resource_version gauge
|
||||||
|
`
|
||||||
|
cases := []generateMetricsTestCase{
|
||||||
|
{
|
||||||
|
Obj: &storagev1.StorageClass{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "test_storageclass-info",
|
||||||
|
},
|
||||||
|
Provisioner: "kubernetes.io/rbd",
|
||||||
|
ReclaimPolicy: &reclaimPolicy,
|
||||||
|
VolumeBindingMode: &volumeBindingMode,
|
||||||
|
},
|
||||||
|
Want: `
|
||||||
|
kube_storageclass_info{storageclass="test_storageclass-info",provisioner="kubernetes.io/rbd",reclaimPolicy="Delete",volumeBindingMode="Immediate"} 1
|
||||||
|
`,
|
||||||
|
MetricNames: []string{
|
||||||
|
"kube_storageclass_info",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Obj: &storagev1.StorageClass{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "test_kube_storageclass_created",
|
||||||
|
CreationTimestamp: metav1StartTime,
|
||||||
|
},
|
||||||
|
Provisioner: "kubernetes.io/rbd",
|
||||||
|
ReclaimPolicy: &reclaimPolicy,
|
||||||
|
VolumeBindingMode: &volumeBindingMode,
|
||||||
|
},
|
||||||
|
Want: `
|
||||||
|
kube_storageclass_created{storageclass="test_kube_storageclass_created"} 1.501569018e+09
|
||||||
|
`,
|
||||||
|
MetricNames: []string{
|
||||||
|
"kube_storageclass_created",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Obj: &storagev1.StorageClass{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "test_kube_storageclass_resource_version",
|
||||||
|
ResourceVersion: "abcdef",
|
||||||
|
},
|
||||||
|
Provisioner: "kubernetes.io/rbd",
|
||||||
|
ReclaimPolicy: &reclaimPolicy,
|
||||||
|
VolumeBindingMode: &volumeBindingMode,
|
||||||
|
},
|
||||||
|
Want: `
|
||||||
|
kube_storageclass_metadata_resource_version{storageclass="test_kube_storageclass_resource_version",resource_version="abcdef"} 1
|
||||||
|
`,
|
||||||
|
MetricNames: []string{
|
||||||
|
"kube_storageclass_metadata_resource_version",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Obj: &storagev1.StorageClass{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "test_storageclass-labels",
|
||||||
|
Labels: map[string]string{
|
||||||
|
"foo": "bar",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Provisioner: "kubernetes.io/rbd",
|
||||||
|
ReclaimPolicy: &reclaimPolicy,
|
||||||
|
VolumeBindingMode: &volumeBindingMode,
|
||||||
|
},
|
||||||
|
Want: `
|
||||||
|
kube_storageclass_labels{storageclass="test_storageclass-labels",label_foo="bar"} 1
|
||||||
|
`,
|
||||||
|
MetricNames: []string{
|
||||||
|
"kube_storageclass_labels",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for i, c := range cases {
|
||||||
|
c.Func = metric.ComposeMetricGenFuncs(storageClassMetricFamilies)
|
||||||
|
if err := c.run(); err != nil {
|
||||||
|
t.Errorf("unexpected collecting result in %vth run:\n%s", i, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -50,4 +50,8 @@ rules:
|
||||||
resources:
|
resources:
|
||||||
- certificatesigningrequests
|
- certificatesigningrequests
|
||||||
verbs: ["list", "watch"]
|
verbs: ["list", "watch"]
|
||||||
|
- apiGroups: ["storage.k8s.io"]
|
||||||
|
resources:
|
||||||
|
- storageclasses
|
||||||
|
verbs: ["list", "watch"]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -48,5 +48,6 @@ var (
|
||||||
"secrets": struct{}{},
|
"secrets": struct{}{},
|
||||||
"services": struct{}{},
|
"services": struct{}{},
|
||||||
"statefulsets": struct{}{},
|
"statefulsets": struct{}{},
|
||||||
|
"storageclasses": struct{}{},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
apiVersion: storage.k8s.io/v1
|
||||||
|
kind: StorageClass
|
||||||
|
metadata:
|
||||||
|
name: storageclass
|
||||||
|
provisioner: kubernetes.io/rbd
|
||||||
|
reclaimPolicy: Delete
|
||||||
|
volumeBindingMode: Immediate
|
||||||
|
|
@ -126,6 +126,7 @@ k8s.io/api/certificates/v1beta1
|
||||||
k8s.io/api/core/v1
|
k8s.io/api/core/v1
|
||||||
k8s.io/api/extensions/v1beta1
|
k8s.io/api/extensions/v1beta1
|
||||||
k8s.io/api/policy/v1beta1
|
k8s.io/api/policy/v1beta1
|
||||||
|
k8s.io/api/storage/v1
|
||||||
k8s.io/api/apps/v1beta1
|
k8s.io/api/apps/v1beta1
|
||||||
k8s.io/api/admissionregistration/v1beta1
|
k8s.io/api/admissionregistration/v1beta1
|
||||||
k8s.io/api/autoscaling/v1
|
k8s.io/api/autoscaling/v1
|
||||||
|
|
@ -151,7 +152,6 @@ k8s.io/api/scheduling/v1
|
||||||
k8s.io/api/scheduling/v1alpha1
|
k8s.io/api/scheduling/v1alpha1
|
||||||
k8s.io/api/scheduling/v1beta1
|
k8s.io/api/scheduling/v1beta1
|
||||||
k8s.io/api/settings/v1alpha1
|
k8s.io/api/settings/v1alpha1
|
||||||
k8s.io/api/storage/v1
|
|
||||||
k8s.io/api/storage/v1alpha1
|
k8s.io/api/storage/v1alpha1
|
||||||
k8s.io/api/storage/v1beta1
|
k8s.io/api/storage/v1beta1
|
||||||
# k8s.io/apimachinery v0.0.0-20190313205120-d7deff9243b1
|
# k8s.io/apimachinery v0.0.0-20190313205120-d7deff9243b1
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue