From 925013f0c6b32077f1dc7ae9e7d3aa1831d90af3 Mon Sep 17 00:00:00 2001 From: mlmhl Date: Fri, 5 Jan 2018 13:41:29 +0800 Subject: [PATCH] add number measurement for bound/unbound pv/pvc --- pkg/controller/volume/persistentvolume/BUILD | 2 + .../volume/persistentvolume/metrics/BUILD | 30 +++ .../persistentvolume/metrics/metrics.go | 184 ++++++++++++++++++ .../persistentvolume/pv_controller_base.go | 3 + 4 files changed, 219 insertions(+) create mode 100644 pkg/controller/volume/persistentvolume/metrics/BUILD create mode 100644 pkg/controller/volume/persistentvolume/metrics/metrics.go diff --git a/pkg/controller/volume/persistentvolume/BUILD b/pkg/controller/volume/persistentvolume/BUILD index eaef2490e52..748f89a380d 100644 --- a/pkg/controller/volume/persistentvolume/BUILD +++ b/pkg/controller/volume/persistentvolume/BUILD @@ -24,6 +24,7 @@ go_library( "//pkg/cloudprovider:go_default_library", "//pkg/controller:go_default_library", "//pkg/controller/volume/events:go_default_library", + "//pkg/controller/volume/persistentvolume/metrics:go_default_library", "//pkg/features:go_default_library", "//pkg/util/goroutinemap:go_default_library", "//pkg/util/goroutinemap/exponentialbackoff:go_default_library", @@ -114,6 +115,7 @@ filegroup( name = "all-srcs", srcs = [ ":package-srcs", + "//pkg/controller/volume/persistentvolume/metrics:all-srcs", "//pkg/controller/volume/persistentvolume/options:all-srcs", ], tags = ["automanaged"], diff --git a/pkg/controller/volume/persistentvolume/metrics/BUILD b/pkg/controller/volume/persistentvolume/metrics/BUILD new file mode 100644 index 00000000000..e5a37cbfd42 --- /dev/null +++ b/pkg/controller/volume/persistentvolume/metrics/BUILD @@ -0,0 +1,30 @@ +package(default_visibility = ["//visibility:public"]) + +load( + "@io_bazel_rules_go//go:def.bzl", + "go_library", +) + +go_library( + name = "go_default_library", + srcs = ["metrics.go"], + importpath = "k8s.io/kubernetes/pkg/controller/volume/persistentvolume/metrics", + deps = [ + "//vendor/github.com/golang/glog:go_default_library", + "//vendor/github.com/prometheus/client_golang/prometheus:go_default_library", + "//vendor/k8s.io/api/core/v1:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], +) diff --git a/pkg/controller/volume/persistentvolume/metrics/metrics.go b/pkg/controller/volume/persistentvolume/metrics/metrics.go new file mode 100644 index 00000000000..5035b1bb9e0 --- /dev/null +++ b/pkg/controller/volume/persistentvolume/metrics/metrics.go @@ -0,0 +1,184 @@ +/* +Copyright 2017 The Kubernetes Authors. + +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 metrics + +import ( + "sync" + + "k8s.io/api/core/v1" + + "github.com/golang/glog" + "github.com/prometheus/client_golang/prometheus" +) + +const ( + // Subsystem names. + pvControllerSubsystem = "pv_collector" + + // Metric names. + boundPVKey = "bound_pv_count" + unboundPVKey = "unbound_pv_count" + boundPVCKey = "bound_pvc_count" + unboundPVCKey = "unbound_pvc_count" + + // Label names. + namespaceLabel = "namespace" + storageClassLabel = "storage_class" +) + +var registerMetrics sync.Once + +// PVLister used to list persistent volumes. +type PVLister interface { + List() []interface{} +} + +// PVCLister used to list persistent volume claims. +type PVCLister interface { + List() []interface{} +} + +// Register all metrics for pv controller. +func Register(pvLister PVLister, pvcLister PVCLister) { + registerMetrics.Do(func() { + prometheus.MustRegister(newPVAndPVCCountCollector(pvLister, pvcLister)) + }) +} + +func newPVAndPVCCountCollector(pvLister PVLister, pvcLister PVCLister) *pvAndPVCCountCollector { + return &pvAndPVCCountCollector{pvLister, pvcLister} +} + +// Custom collector for current pod and container counts. +type pvAndPVCCountCollector struct { + // Cache for accessing information about PersistentVolumes. + pvLister PVLister + // Cache for accessing information about PersistentVolumeClaims. + pvcLister PVCLister +} + +var ( + boundPVCountDesc = prometheus.NewDesc( + prometheus.BuildFQName("", pvControllerSubsystem, boundPVKey), + "Gauge measuring number of persistent volume currently bound", + []string{storageClassLabel}, nil) + unboundPVCountDesc = prometheus.NewDesc( + prometheus.BuildFQName("", pvControllerSubsystem, unboundPVKey), + "Gauge measuring number of persistent volume currently unbound", + []string{storageClassLabel}, nil) + + boundPVCCountDesc = prometheus.NewDesc( + prometheus.BuildFQName("", pvControllerSubsystem, boundPVCKey), + "Gauge measuring number of persistent volume claim currently bound", + []string{namespaceLabel}, nil) + unboundPVCCountDesc = prometheus.NewDesc( + prometheus.BuildFQName("", pvControllerSubsystem, unboundPVCKey), + "Gauge measuring number of persistent volume claim currently unbound", + []string{namespaceLabel}, nil) +) + +func (collector *pvAndPVCCountCollector) Describe(ch chan<- *prometheus.Desc) { + ch <- boundPVCountDesc + ch <- unboundPVCountDesc + ch <- boundPVCCountDesc + ch <- unboundPVCCountDesc +} + +func (collector *pvAndPVCCountCollector) Collect(ch chan<- prometheus.Metric) { + collector.pvCollect(ch) + collector.pvcCollect(ch) +} + +func (collector *pvAndPVCCountCollector) pvCollect(ch chan<- prometheus.Metric) { + boundNumberByStorageClass := make(map[string]int) + unboundNumberByStorageClass := make(map[string]int) + for _, pvObj := range collector.pvLister.List() { + pv, ok := pvObj.(*v1.PersistentVolume) + if !ok { + continue + } + if pv.Status.Phase == v1.VolumeBound { + boundNumberByStorageClass[pv.Spec.StorageClassName]++ + } else { + unboundNumberByStorageClass[pv.Spec.StorageClassName]++ + } + } + for storageClassName, number := range boundNumberByStorageClass { + metric, err := prometheus.NewConstMetric( + boundPVCountDesc, + prometheus.GaugeValue, + float64(number), + storageClassName) + if err != nil { + glog.Warningf("Create bound pv number metric failed: %v", err) + continue + } + ch <- metric + } + for storageClassName, number := range unboundNumberByStorageClass { + metric, err := prometheus.NewConstMetric( + unboundPVCountDesc, + prometheus.GaugeValue, + float64(number), + storageClassName) + if err != nil { + glog.Warningf("Create unbound pv number metric failed: %v", err) + continue + } + ch <- metric + } +} + +func (collector *pvAndPVCCountCollector) pvcCollect(ch chan<- prometheus.Metric) { + boundNumberByNamespace := make(map[string]int) + unboundNumberByNamespace := make(map[string]int) + for _, pvcObj := range collector.pvcLister.List() { + pvc, ok := pvcObj.(*v1.PersistentVolumeClaim) + if !ok { + continue + } + if pvc.Status.Phase == v1.ClaimBound { + boundNumberByNamespace[pvc.Namespace]++ + } else { + unboundNumberByNamespace[pvc.Namespace]++ + } + } + for namespace, number := range boundNumberByNamespace { + metric, err := prometheus.NewConstMetric( + boundPVCCountDesc, + prometheus.GaugeValue, + float64(number), + namespace) + if err != nil { + glog.Warningf("Create bound pvc number metric failed: %v", err) + continue + } + ch <- metric + } + for namespace, number := range unboundNumberByNamespace { + metric, err := prometheus.NewConstMetric( + unboundPVCCountDesc, + prometheus.GaugeValue, + float64(number), + namespace) + if err != nil { + glog.Warningf("Create unbound pvc number metric failed: %v", err) + continue + } + ch <- metric + } +} diff --git a/pkg/controller/volume/persistentvolume/pv_controller_base.go b/pkg/controller/volume/persistentvolume/pv_controller_base.go index 2ba5d831cbd..135c7b55be2 100644 --- a/pkg/controller/volume/persistentvolume/pv_controller_base.go +++ b/pkg/controller/volume/persistentvolume/pv_controller_base.go @@ -40,6 +40,7 @@ import ( "k8s.io/client-go/util/workqueue" "k8s.io/kubernetes/pkg/cloudprovider" "k8s.io/kubernetes/pkg/controller" + "k8s.io/kubernetes/pkg/controller/volume/persistentvolume/metrics" "k8s.io/kubernetes/pkg/util/goroutinemap" vol "k8s.io/kubernetes/pkg/volume" @@ -274,6 +275,8 @@ func (ctrl *PersistentVolumeController) Run(stopCh <-chan struct{}) { go wait.Until(ctrl.volumeWorker, time.Second, stopCh) go wait.Until(ctrl.claimWorker, time.Second, stopCh) + metrics.Register(ctrl.volumes.store, ctrl.claims) + <-stopCh }