Added StatefulSet metrics
This commit is contained in:
parent
57c44db945
commit
fe6a64feba
|
|
@ -0,0 +1,8 @@
|
||||||
|
# Service Metrics
|
||||||
|
|
||||||
|
| Metric name| Metric type | Labels/tags |
|
||||||
|
| ---------- | ----------- | ----------- |
|
||||||
|
| kube_statefulset_status_replicas | Gauge | `statefulset`=<statefulset-name> <br> `namespace`=<statefulset-namespace> |
|
||||||
|
| kube_statefulset_status_observed_generation | Gauge | `statefulset`=<statefulset-name> <br> `namespace`=<statefulset-namespace> |
|
||||||
|
| kube_statefulset_replicas | Gauge | `statefulset`=<statefulset-name> <br> `namespace`=<statefulset-namespace> |
|
||||||
|
| kube_statefulset_metadata_generation | Gauge | `statefulset`=<statefulset-name> <br> `namespace`=<statefulset-namespace> |
|
||||||
|
|
@ -0,0 +1,98 @@
|
||||||
|
package collectors
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
|
"k8s.io/client-go/pkg/apis/apps/v1beta1"
|
||||||
|
"github.com/golang/glog"
|
||||||
|
"k8s.io/client-go/kubernetes"
|
||||||
|
"k8s.io/client-go/tools/cache"
|
||||||
|
"golang.org/x/net/context"
|
||||||
|
"k8s.io/client-go/pkg/api"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
descStatefulSetStatusReplicas = prometheus.NewDesc(
|
||||||
|
"kube_statefulset_status_replicas",
|
||||||
|
"The number of replicas per StatefulSet.",
|
||||||
|
[]string{"namespace", "statefulset"}, nil,
|
||||||
|
)
|
||||||
|
|
||||||
|
descStatefulSetStatusObservedGeneration = prometheus.NewDesc(
|
||||||
|
"kube_statefulset_status_observed_generation",
|
||||||
|
"The generation observed by the StatefulSet controller.",
|
||||||
|
[]string{"namespace", "statefulset"}, nil,
|
||||||
|
)
|
||||||
|
|
||||||
|
descStatefulSetSpecReplicas = prometheus.NewDesc(
|
||||||
|
"kube_statefulset_replicas",
|
||||||
|
"Number of desired pods for a StatefulSet.",
|
||||||
|
[]string{"namespace", "statefulset"}, nil,
|
||||||
|
)
|
||||||
|
|
||||||
|
descStatefulSetMetadataGeneration = prometheus.NewDesc(
|
||||||
|
"kube_statefulset_metadata_generation",
|
||||||
|
"Sequence number representing a specific generation of the desired state for the StatefulSet.",
|
||||||
|
[]string{"namespace", "statefulset"}, nil,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
type StatefulSetLister func() ([]v1beta1.StatefulSet, error)
|
||||||
|
|
||||||
|
func (l StatefulSetLister) List() ([]v1beta1.StatefulSet, error) {
|
||||||
|
return l()
|
||||||
|
}
|
||||||
|
|
||||||
|
func RegisterStatefulSetCollector(registry prometheus.Registerer, kubeClient kubernetes.Interface) {
|
||||||
|
client := kubeClient.AppsV1beta1().RESTClient()
|
||||||
|
dlw := cache.NewListWatchFromClient(client, "statefulsets", api.NamespaceAll, nil)
|
||||||
|
dinf := cache.NewSharedInformer(dlw, &v1beta1.StatefulSet{}, resyncPeriod)
|
||||||
|
|
||||||
|
statefulSetLister := StatefulSetLister(func() (statefulSets []v1beta1.StatefulSet, err error) {
|
||||||
|
for _, c := range dinf.GetStore().List() {
|
||||||
|
statefulSets = append(statefulSets, *(c.(*v1beta1.StatefulSet)))
|
||||||
|
}
|
||||||
|
return statefulSets, nil
|
||||||
|
})
|
||||||
|
|
||||||
|
registry.MustRegister(&statefulSetCollector{store: statefulSetLister})
|
||||||
|
go dinf.Run(context.Background().Done())
|
||||||
|
}
|
||||||
|
|
||||||
|
type statefulSetStore interface {
|
||||||
|
List() (statefulSets []v1beta1.StatefulSet, err error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type statefulSetCollector struct {
|
||||||
|
store statefulSetStore
|
||||||
|
}
|
||||||
|
|
||||||
|
// Describe implements the prometheus.Collector interface.
|
||||||
|
func (dc *statefulSetCollector) Describe(ch chan<- *prometheus.Desc) {
|
||||||
|
ch <- descStatefulSetStatusReplicas
|
||||||
|
ch <- descStatefulSetStatusObservedGeneration
|
||||||
|
ch <- descStatefulSetSpecReplicas
|
||||||
|
ch <- descStatefulSetMetadataGeneration
|
||||||
|
}
|
||||||
|
|
||||||
|
// Collect implements the prometheus.Collector interface.
|
||||||
|
func (sc *statefulSetCollector) Collect(ch chan<- prometheus.Metric) {
|
||||||
|
dpls, err := sc.store.List()
|
||||||
|
if err != nil {
|
||||||
|
glog.Errorf("listing statefulsets failed: %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, d := range dpls {
|
||||||
|
sc.collectStatefulSet(ch, d)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dc *statefulSetCollector) collectStatefulSet(ch chan<- prometheus.Metric, statefulSet v1beta1.StatefulSet) {
|
||||||
|
addGauge := func(desc *prometheus.Desc, v float64, lv ...string) {
|
||||||
|
lv = append([]string{statefulSet.Namespace, statefulSet.Name}, lv...)
|
||||||
|
ch <- prometheus.MustNewConstMetric(desc, prometheus.GaugeValue, v, lv...)
|
||||||
|
}
|
||||||
|
addGauge(descStatefulSetStatusReplicas, float64(statefulSet.Status.Replicas))
|
||||||
|
addGauge(descStatefulSetStatusObservedGeneration, float64(*statefulSet.Status.ObservedGeneration))
|
||||||
|
addGauge(descStatefulSetSpecReplicas, float64(*statefulSet.Spec.Replicas))
|
||||||
|
addGauge(descStatefulSetMetadataGeneration, float64(statefulSet.ObjectMeta.Generation))
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,96 @@
|
||||||
|
package collectors
|
||||||
|
|
||||||
|
import (
|
||||||
|
"k8s.io/client-go/pkg/apis/apps/v1beta1"
|
||||||
|
"testing"
|
||||||
|
"k8s.io/client-go/pkg/api/v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
statefulSet1Replicas int32 = 3
|
||||||
|
statefulSet2Replicas int32 = 6
|
||||||
|
|
||||||
|
statefulSet1ObservedGeneration int64 = 1
|
||||||
|
statefulSet2ObservedGeneration int64 = 2
|
||||||
|
)
|
||||||
|
|
||||||
|
type mockStatefulSetStore struct {
|
||||||
|
f func() ([]v1beta1.StatefulSet, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ds mockStatefulSetStore) List() (deployments []v1beta1.StatefulSet, err error) {
|
||||||
|
return ds.f()
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStatefuleSetCollector(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 = `
|
||||||
|
# HELP kube_statefulset_status_replicas The number of replicas per StatefulSet.
|
||||||
|
# TYPE kube_statefulset_status_replicas gauge
|
||||||
|
# HELP kube_statefulset_status_observed_generation The generation observed by the StatefulSet controller.
|
||||||
|
# TYPE kube_statefulset_status_observed_generation gauge
|
||||||
|
# HELP kube_statefulset_replicas Number of desired pods for a StatefulSet.
|
||||||
|
# TYPE kube_statefulset_replicas gauge
|
||||||
|
# HELP kube_statefulset_metadata_generation Sequence number representing a specific generation of the desired state for the StatefulSet.
|
||||||
|
# TYPE kube_statefulset_metadata_generation gauge
|
||||||
|
`
|
||||||
|
cases := []struct {
|
||||||
|
depls []v1beta1.StatefulSet
|
||||||
|
want string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
depls: []v1beta1.StatefulSet{
|
||||||
|
{
|
||||||
|
ObjectMeta: v1.ObjectMeta{
|
||||||
|
Name: "statefulset1",
|
||||||
|
Namespace: "ns1",
|
||||||
|
Generation: 3,
|
||||||
|
},
|
||||||
|
Spec: v1beta1.StatefulSetSpec{
|
||||||
|
Replicas: &statefulSet1Replicas,
|
||||||
|
ServiceName: "statefulset1service",
|
||||||
|
},
|
||||||
|
Status: v1beta1.StatefulSetStatus{
|
||||||
|
ObservedGeneration: &statefulSet1ObservedGeneration,
|
||||||
|
Replicas: 2,
|
||||||
|
},
|
||||||
|
}, {
|
||||||
|
ObjectMeta: v1.ObjectMeta{
|
||||||
|
Name: "statefulset2",
|
||||||
|
Namespace: "ns2",
|
||||||
|
Generation: 21,
|
||||||
|
},
|
||||||
|
Spec: v1beta1.StatefulSetSpec{
|
||||||
|
Replicas: &statefulSet2Replicas,
|
||||||
|
ServiceName: "statefulset2service",
|
||||||
|
},
|
||||||
|
Status: v1beta1.StatefulSetStatus{
|
||||||
|
ObservedGeneration: &statefulSet2ObservedGeneration,
|
||||||
|
Replicas: 5,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
want: metadata + `
|
||||||
|
kube_statefulset_status_replicas{namespace="ns1",statefulset="statefulset1"} 2
|
||||||
|
kube_statefulset_status_replicas{namespace="ns2",statefulset="statefulset2"} 5
|
||||||
|
kube_statefulset_status_observed_generation{namespace="ns1",statefulset="statefulset1"} 1
|
||||||
|
kube_statefulset_status_observed_generation{namespace="ns2",statefulset="statefulset2"} 2
|
||||||
|
kube_statefulset_replicas{namespace="ns1",statefulset="statefulset1"} 3
|
||||||
|
kube_statefulset_replicas{namespace="ns2",statefulset="statefulset2"} 6
|
||||||
|
kube_statefulset_metadata_generation{namespace="ns1",statefulset="statefulset1"} 3
|
||||||
|
kube_statefulset_metadata_generation{namespace="ns2",statefulset="statefulset2"} 21
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, c := range cases {
|
||||||
|
sc := &statefulSetCollector{
|
||||||
|
store: mockStatefulSetStore{
|
||||||
|
f: func() ([]v1beta1.StatefulSet, error) { return c.depls, nil },
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if err := gatherAndCompare(sc, c.want, nil); err != nil {
|
||||||
|
t.Errorf("unexpected collecting result:\n%s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
2
main.go
2
main.go
|
|
@ -54,6 +54,7 @@ var (
|
||||||
"services": struct{}{},
|
"services": struct{}{},
|
||||||
"jobs": struct{}{},
|
"jobs": struct{}{},
|
||||||
"cronjobs": struct{}{},
|
"cronjobs": struct{}{},
|
||||||
|
"statefulsets": struct{}{},
|
||||||
}
|
}
|
||||||
availableCollectors = map[string]func(registry prometheus.Registerer, kubeClient clientset.Interface){
|
availableCollectors = map[string]func(registry prometheus.Registerer, kubeClient clientset.Interface){
|
||||||
"cronjobs": collectors.RegisterCronJobCollector,
|
"cronjobs": collectors.RegisterCronJobCollector,
|
||||||
|
|
@ -67,6 +68,7 @@ var (
|
||||||
"replicationcontrollers": collectors.RegisterReplicationControllerCollector,
|
"replicationcontrollers": collectors.RegisterReplicationControllerCollector,
|
||||||
"resourcequotas": collectors.RegisterResourceQuotaCollector,
|
"resourcequotas": collectors.RegisterResourceQuotaCollector,
|
||||||
"services": collectors.RegisterServiceCollector,
|
"services": collectors.RegisterServiceCollector,
|
||||||
|
"statefulsets": collectors.RegisterStatefulSetCollector,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue