mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-01 07:47:56 +00:00
Merge pull request #95719 from tsmetana/add-pv_collector-provisioner-metric
PV Controller: Add plugin name and volume mode to PV metrics
This commit is contained in:
commit
423f8731ef
@ -6,6 +6,7 @@ go_library(
|
||||
importpath = "k8s.io/kubernetes/pkg/controller/volume/persistentvolume/metrics",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//pkg/volume:go_default_library",
|
||||
"//pkg/volume/util:go_default_library",
|
||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||
"//staging/src/k8s.io/component-base/metrics:go_default_library",
|
||||
|
@ -23,6 +23,7 @@ import (
|
||||
v1 "k8s.io/api/core/v1"
|
||||
"k8s.io/component-base/metrics"
|
||||
"k8s.io/component-base/metrics/legacyregistry"
|
||||
"k8s.io/kubernetes/pkg/volume"
|
||||
metricutil "k8s.io/kubernetes/pkg/volume/util"
|
||||
)
|
||||
|
||||
@ -31,6 +32,7 @@ const (
|
||||
pvControllerSubsystem = "pv_collector"
|
||||
|
||||
// Metric names.
|
||||
totalPVKey = "total_pv_count"
|
||||
boundPVKey = "bound_pv_count"
|
||||
unboundPVKey = "unbound_pv_count"
|
||||
boundPVCKey = "bound_pvc_count"
|
||||
@ -39,6 +41,11 @@ const (
|
||||
// Label names.
|
||||
namespaceLabel = "namespace"
|
||||
storageClassLabel = "storage_class"
|
||||
pluginNameLabel = "plugin_name"
|
||||
volumeModeLabel = "volume_mode"
|
||||
|
||||
// String to use when plugin name cannot be determined
|
||||
pluginNameNotAvailable = "N/A"
|
||||
)
|
||||
|
||||
var registerMetrics sync.Once
|
||||
@ -54,15 +61,15 @@ type PVCLister interface {
|
||||
}
|
||||
|
||||
// Register all metrics for pv controller.
|
||||
func Register(pvLister PVLister, pvcLister PVCLister) {
|
||||
func Register(pvLister PVLister, pvcLister PVCLister, pluginMgr *volume.VolumePluginMgr) {
|
||||
registerMetrics.Do(func() {
|
||||
legacyregistry.CustomMustRegister(newPVAndPVCCountCollector(pvLister, pvcLister))
|
||||
legacyregistry.CustomMustRegister(newPVAndPVCCountCollector(pvLister, pvcLister, pluginMgr))
|
||||
legacyregistry.MustRegister(volumeOperationErrorsMetric)
|
||||
})
|
||||
}
|
||||
|
||||
func newPVAndPVCCountCollector(pvLister PVLister, pvcLister PVCLister) *pvAndPVCCountCollector {
|
||||
return &pvAndPVCCountCollector{pvLister: pvLister, pvcLister: pvcLister}
|
||||
func newPVAndPVCCountCollector(pvLister PVLister, pvcLister PVCLister, pluginMgr *volume.VolumePluginMgr) *pvAndPVCCountCollector {
|
||||
return &pvAndPVCCountCollector{pvLister: pvLister, pvcLister: pvcLister, pluginMgr: pluginMgr}
|
||||
}
|
||||
|
||||
// Custom collector for current pod and container counts.
|
||||
@ -73,12 +80,19 @@ type pvAndPVCCountCollector struct {
|
||||
pvLister PVLister
|
||||
// Cache for accessing information about PersistentVolumeClaims.
|
||||
pvcLister PVCLister
|
||||
// Volume plugin manager
|
||||
pluginMgr *volume.VolumePluginMgr
|
||||
}
|
||||
|
||||
// Check if our collector implements necessary collector interface
|
||||
var _ metrics.StableCollector = &pvAndPVCCountCollector{}
|
||||
|
||||
var (
|
||||
totalPVCountDesc = metrics.NewDesc(
|
||||
metrics.BuildFQName("", pvControllerSubsystem, totalPVKey),
|
||||
"Gauge measuring total number of persistent volumes",
|
||||
[]string{pluginNameLabel, volumeModeLabel}, nil,
|
||||
metrics.ALPHA, "")
|
||||
boundPVCountDesc = metrics.NewDesc(
|
||||
metrics.BuildFQName("", pvControllerSubsystem, boundPVKey),
|
||||
"Gauge measuring number of persistent volume currently bound",
|
||||
@ -110,7 +124,20 @@ var (
|
||||
[]string{"plugin_name", "operation_name"})
|
||||
)
|
||||
|
||||
// volumeCount counts by PluginName and VolumeMode.
|
||||
type volumeCount map[string]map[string]int
|
||||
|
||||
func (v volumeCount) add(pluginName string, volumeMode string) {
|
||||
count, ok := v[pluginName]
|
||||
if !ok {
|
||||
count = map[string]int{}
|
||||
}
|
||||
count[volumeMode]++
|
||||
v[pluginName] = count
|
||||
}
|
||||
|
||||
func (collector *pvAndPVCCountCollector) DescribeWithStability(ch chan<- *metrics.Desc) {
|
||||
ch <- totalPVCountDesc
|
||||
ch <- boundPVCountDesc
|
||||
ch <- unboundPVCountDesc
|
||||
ch <- boundPVCCountDesc
|
||||
@ -122,14 +149,26 @@ func (collector *pvAndPVCCountCollector) CollectWithStability(ch chan<- metrics.
|
||||
collector.pvcCollect(ch)
|
||||
}
|
||||
|
||||
func (collector *pvAndPVCCountCollector) getPVPluginName(pv *v1.PersistentVolume) string {
|
||||
spec := volume.NewSpecFromPersistentVolume(pv, true)
|
||||
fullPluginName := pluginNameNotAvailable
|
||||
if plugin, err := collector.pluginMgr.FindPluginBySpec(spec); err == nil {
|
||||
fullPluginName = metricutil.GetFullQualifiedPluginNameForVolume(plugin.GetPluginName(), spec)
|
||||
}
|
||||
return fullPluginName
|
||||
}
|
||||
|
||||
func (collector *pvAndPVCCountCollector) pvCollect(ch chan<- metrics.Metric) {
|
||||
boundNumberByStorageClass := make(map[string]int)
|
||||
unboundNumberByStorageClass := make(map[string]int)
|
||||
totalCount := make(volumeCount)
|
||||
for _, pvObj := range collector.pvLister.List() {
|
||||
pv, ok := pvObj.(*v1.PersistentVolume)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
pluginName := collector.getPVPluginName(pv)
|
||||
totalCount.add(pluginName, string(*pv.Spec.VolumeMode))
|
||||
if pv.Status.Phase == v1.VolumeBound {
|
||||
boundNumberByStorageClass[pv.Spec.StorageClassName]++
|
||||
} else {
|
||||
@ -150,6 +189,16 @@ func (collector *pvAndPVCCountCollector) pvCollect(ch chan<- metrics.Metric) {
|
||||
float64(number),
|
||||
storageClassName)
|
||||
}
|
||||
for pluginName, volumeModeCount := range totalCount {
|
||||
for volumeMode, number := range volumeModeCount {
|
||||
ch <- metrics.NewLazyConstMetric(
|
||||
totalPVCountDesc,
|
||||
metrics.GaugeValue,
|
||||
float64(number),
|
||||
pluginName,
|
||||
volumeMode)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (collector *pvAndPVCCountCollector) pvcCollect(ch chan<- metrics.Metric) {
|
||||
|
@ -317,7 +317,7 @@ 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)
|
||||
metrics.Register(ctrl.volumes.store, ctrl.claims, &ctrl.volumePluginMgr)
|
||||
|
||||
<-stopCh
|
||||
}
|
||||
|
@ -381,9 +381,12 @@ var _ = utils.SIGDescribe("[Serial] Volume metrics", func() {
|
||||
// Test for pv controller metrics, concretely: bound/unbound pv/pvc count.
|
||||
ginkgo.Describe("PVController", func() {
|
||||
const (
|
||||
classKey = "storage_class"
|
||||
namespaceKey = "namespace"
|
||||
classKey = "storage_class"
|
||||
namespaceKey = "namespace"
|
||||
pluginNameKey = "plugin_name"
|
||||
volumeModeKey = "volume_mode"
|
||||
|
||||
totalPVKey = "pv_collector_total_pv_count"
|
||||
boundPVKey = "pv_collector_bound_pv_count"
|
||||
unboundPVKey = "pv_collector_unbound_pv_count"
|
||||
boundPVCKey = "pv_collector_bound_pvc_count"
|
||||
@ -506,6 +509,18 @@ var _ = utils.SIGDescribe("[Serial] Volume metrics", func() {
|
||||
validator([]map[string]int64{{className: 1}, nil, {ns: 1}, nil})
|
||||
|
||||
})
|
||||
ginkgo.It("should create total pv count metrics for with plugin and volume mode labels after creating pv",
|
||||
func() {
|
||||
var err error
|
||||
dimensions := []string{pluginNameKey, volumeModeKey}
|
||||
pv, err = e2epv.CreatePV(c, pv)
|
||||
framework.ExpectNoError(err, "Error creating pv: %v", err)
|
||||
waitForPVControllerSync(metricsGrabber, totalPVKey, pluginNameKey)
|
||||
controllerMetrics, err := metricsGrabber.GrabFromControllerManager()
|
||||
framework.ExpectNoError(err, "Error getting c-m metricValues: %v", err)
|
||||
err = testutil.ValidateMetrics(testutil.Metrics(controllerMetrics), totalPVKey, dimensions...)
|
||||
framework.ExpectNoError(err, "Invalid metric in Controller Manager metrics: %q", totalPVKey)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user