Merge pull request #226 from cofyc/pvc

Add PVC requested storage metric and storageclass label
This commit is contained in:
Frederic Branczyk 2017-08-24 14:12:55 +02:00 committed by GitHub
commit ce6ea0bd21
3 changed files with 74 additions and 5 deletions

View File

@ -2,4 +2,10 @@
| Metric name| Metric type | Labels/tags |
| ---------- | ----------- | ----------- |
| kube_persistentvolumeclaim_status_phase| Gauge | `namespace`=&lt;persistentvolumeclaim-namespace&gt; <br> `persistentvolumeclaim`=&lt;persistentvolumeclaim-name&gt; <br> `phase`=&lt;Pending\|Bound\|Lost&gt; |
| kube_persistentvolumeclaim_info | Gauge | `namespace`=&lt;persistentvolumeclaim-namespace&gt; <br> `persistentvolumeclaim`=&lt;persistentvolumeclaim-name&gt; <br> `storageclass`=&lt;persistentvolumeclaim-storageclassname&gt; |
| kube_persistentvolumeclaim_status_phase | Gauge | `namespace`=&lt;persistentvolumeclaim-namespace&gt; <br> `persistentvolumeclaim`=&lt;persistentvolumeclaim-name&gt; <br> `phase`=&lt;Pending\|Bound\|Lost&gt; |
| kube_persistentvolumeclaim_resource_requests_storage_bytes | Gauge | `namespace`=&lt;persistentvolumeclaim-namespace&gt; <br> `persistentvolumeclaim`=&lt;persistentvolumeclaim-name&gt; |
Note:
- A special `<none>` string will be used if PVC has no storage class.

View File

@ -26,15 +26,32 @@ import (
)
var (
descPersistentVolumeClaimInfo = prometheus.NewDesc(
"kube_persistentvolumeclaim_info",
"Information about persistent volume claim.",
[]string{
"namespace",
"persistentvolumeclaim",
"storageclass",
}, nil,
)
descPersistentVolumeClaimStatusPhase = prometheus.NewDesc(
"kube_persistentvolumeclaim_status_phase",
"The phase the claim is currently in.",
"The phase the persistent volume claim is currently in.",
[]string{
"namespace",
"persistentvolumeclaim",
"phase",
}, nil,
)
descPersistentVolumeClaimResourceRequestsStorage = prometheus.NewDesc(
"kube_persistentvolumeclaim_resource_requests_storage_bytes",
"The capacity of storage requested by the persistent volume claim.",
[]string{
"namespace",
"persistentvolumeclaim",
}, nil,
)
)
type PersistentVolumeClaimLister func() (v1.PersistentVolumeClaimList, error)
@ -70,14 +87,16 @@ type persistentVolumeClaimCollector struct {
// Describe implements the prometheus.Collector interface.
func (collector *persistentVolumeClaimCollector) Describe(ch chan<- *prometheus.Desc) {
ch <- descPersistentVolumeClaimInfo
ch <- descPersistentVolumeClaimStatusPhase
ch <- descPersistentVolumeClaimResourceRequestsStorage
}
// Collect implements the prometheus.Collector interface.
func (collector *persistentVolumeClaimCollector) Collect(ch chan<- prometheus.Metric) {
persistentVolumeClaimCollector, err := collector.store.List()
if err != nil {
glog.Errorf("listing limit ranges failed: %s", err)
glog.Errorf("listing persistent volume claims failed: %s", err)
return
}
@ -86,16 +105,39 @@ func (collector *persistentVolumeClaimCollector) Collect(ch chan<- prometheus.Me
}
}
// getPersistentVolumeClaimClass returns StorageClassName. If no storage class was
// requested, it returns "".
func getPersistentVolumeClaimClass(claim *v1.PersistentVolumeClaim) string {
// Use beta annotation first
if class, found := claim.Annotations[v1.BetaStorageClassAnnotation]; found {
return class
}
if claim.Spec.StorageClassName != nil {
return *claim.Spec.StorageClassName
}
// Special non-empty string to indicate absence of storage class.
return "<none>"
}
func (collector *persistentVolumeClaimCollector) collectPersistentVolumeClaim(ch chan<- prometheus.Metric, pvc v1.PersistentVolumeClaim) {
addGauge := func(desc *prometheus.Desc, v float64, lv ...string) {
lv = append([]string{pvc.Namespace, pvc.Name}, lv...)
ch <- prometheus.MustNewConstMetric(desc, prometheus.GaugeValue, v, lv...)
}
storageClassName := getPersistentVolumeClaimClass(&pvc)
addGauge(descPersistentVolumeClaimInfo, 1, storageClassName)
// Set current phase to 1, others to 0 if it is set.
if p := pvc.Status.Phase; p != "" {
addGauge(descPersistentVolumeClaimStatusPhase, boolFloat64(p == v1.ClaimLost), string(v1.ClaimLost))
addGauge(descPersistentVolumeClaimStatusPhase, boolFloat64(p == v1.ClaimBound), string(v1.ClaimBound))
addGauge(descPersistentVolumeClaimStatusPhase, boolFloat64(p == v1.ClaimPending), string(v1.ClaimPending))
}
if storage, ok := pvc.Spec.Resources.Requests[v1.ResourceStorage]; ok {
addGauge(descPersistentVolumeClaimResourceRequestsStorage, float64(storage.Value()))
}
}

View File

@ -19,6 +19,7 @@ package collectors
import (
"testing"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/pkg/api/v1"
)
@ -35,9 +36,14 @@ func TestPersistentVolumeClaimCollector(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_persistentvolumeclaim_status_phase The phase the claim is currently in.
# HELP kube_persistentvolumeclaim_info Information about persistent volume claim.
# TYPE kube_persistentvolumeclaim_info gauge
# HELP kube_persistentvolumeclaim_status_phase The phase the persistent volume claim is currently in.
# TYPE kube_persistentvolumeclaim_status_phase gauge
# HELP kube_persistentvolumeclaim_resource_requests_storage_bytes The capacity of storage requested by the persistent volume claim.
# TYPE kube_persistentvolumeclaim_resource_requests_storage_bytes gauge
`
storageClassName := "rbd"
cases := []struct {
pvcs []v1.PersistentVolumeClaim
metrics []string // which metrics should be checked
@ -51,6 +57,14 @@ func TestPersistentVolumeClaimCollector(t *testing.T) {
Name: "mysql-data",
Namespace: "default",
},
Spec: v1.PersistentVolumeClaimSpec{
StorageClassName: &storageClassName,
Resources: v1.ResourceRequirements{
Requests: v1.ResourceList{
v1.ResourceStorage: resource.MustParse("1Gi"),
},
},
},
Status: v1.PersistentVolumeClaimStatus{
Phase: v1.ClaimBound,
},
@ -60,6 +74,9 @@ func TestPersistentVolumeClaimCollector(t *testing.T) {
Name: "prometheus-data",
Namespace: "default",
},
Spec: v1.PersistentVolumeClaimSpec{
StorageClassName: &storageClassName,
},
Status: v1.PersistentVolumeClaimStatus{
Phase: v1.ClaimPending,
},
@ -74,6 +91,9 @@ func TestPersistentVolumeClaimCollector(t *testing.T) {
},
},
want: metadata + `
kube_persistentvolumeclaim_info{namespace="",persistentvolumeclaim="mongo-data",storageclass="<none>"} 1
kube_persistentvolumeclaim_info{namespace="default",persistentvolumeclaim="mysql-data",storageclass="rbd"} 1
kube_persistentvolumeclaim_info{namespace="default",persistentvolumeclaim="prometheus-data",storageclass="rbd"} 1
kube_persistentvolumeclaim_status_phase{namespace="",persistentvolumeclaim="mongo-data",phase="Bound"} 0
kube_persistentvolumeclaim_status_phase{namespace="",persistentvolumeclaim="mongo-data",phase="Lost"} 1
kube_persistentvolumeclaim_status_phase{namespace="",persistentvolumeclaim="mongo-data",phase="Pending"} 0
@ -83,8 +103,9 @@ func TestPersistentVolumeClaimCollector(t *testing.T) {
kube_persistentvolumeclaim_status_phase{namespace="default",persistentvolumeclaim="prometheus-data",phase="Bound"} 0
kube_persistentvolumeclaim_status_phase{namespace="default",persistentvolumeclaim="prometheus-data",phase="Lost"} 0
kube_persistentvolumeclaim_status_phase{namespace="default",persistentvolumeclaim="prometheus-data",phase="Pending"} 1
kube_persistentvolumeclaim_resource_requests_storage_bytes{namespace="default",persistentvolumeclaim="mysql-data"} 1.073741824e+09
`,
metrics: []string{"kube_persistentvolumeclaim_status_phase"},
metrics: []string{"kube_persistentvolumeclaim_info", "kube_persistentvolumeclaim_status_phase", "kube_persistentvolumeclaim_resource_requests_storage_bytes"},
},
}
for _, c := range cases {