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{}{},
|
||||
"jobs": struct{}{},
|
||||
"cronjobs": struct{}{},
|
||||
"statefulsets": struct{}{},
|
||||
}
|
||||
availableCollectors = map[string]func(registry prometheus.Registerer, kubeClient clientset.Interface){
|
||||
"cronjobs": collectors.RegisterCronJobCollector,
|
||||
|
|
@ -67,6 +68,7 @@ var (
|
|||
"replicationcontrollers": collectors.RegisterReplicationControllerCollector,
|
||||
"resourcequotas": collectors.RegisterResourceQuotaCollector,
|
||||
"services": collectors.RegisterServiceCollector,
|
||||
"statefulsets": collectors.RegisterStatefulSetCollector,
|
||||
}
|
||||
)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue