add volume type and seperated histogram for volume stat collection

This commit is contained in:
Paco Xu 2022-01-06 09:49:01 +08:00 committed by -e
parent c5d8354e0e
commit 6611c36372
6 changed files with 30 additions and 13 deletions

View File

@ -68,14 +68,13 @@ var (
// this metric is mainly for comparison between fsquota monitoring and `du` for disk usage. // this metric is mainly for comparison between fsquota monitoring and `du` for disk usage.
VolumeStatCalDuration = metrics.NewHistogramVec( VolumeStatCalDuration = metrics.NewHistogramVec(
&metrics.HistogramOpts{ &metrics.HistogramOpts{
Subsystem: kubeletSubsystem, Subsystem: kubeletSubsystem,
Name: "volume_stat_cal_duration_seconds", Name: "volume_metric_collection_duration_seconds",
Help: "Duration in seconds to calculate volume stats", Help: "Duration in seconds to calculate volume stats",
// Use DefBuckets for now, will customize the buckets if necessary.
Buckets: metrics.DefBuckets, Buckets: metrics.DefBuckets,
StabilityLevel: metrics.ALPHA, StabilityLevel: metrics.ALPHA,
}, },
[]string{}, []string{"metric_source"},
) )
) )
@ -95,3 +94,8 @@ func Register() {
func SinceInSeconds(start time.Time) float64 { func SinceInSeconds(start time.Time) float64 {
return time.Since(start).Seconds() return time.Since(start).Seconds()
} }
// CollectVolumeStatCalDuration collects the duration in seconds to calculate volume stats.
func CollectVolumeStatCalDuration(metricSource string, start time.Time) {
VolumeStatCalDuration.WithLabelValues(metricSource).Observe(SinceInSeconds(start))
}

View File

@ -30,7 +30,6 @@ import (
"k8s.io/klog/v2" "k8s.io/klog/v2"
stats "k8s.io/kubelet/pkg/apis/stats/v1alpha1" stats "k8s.io/kubelet/pkg/apis/stats/v1alpha1"
"k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/features"
servermetrics "k8s.io/kubernetes/pkg/kubelet/server/metrics"
"k8s.io/kubernetes/pkg/volume" "k8s.io/kubernetes/pkg/volume"
"k8s.io/kubernetes/pkg/volume/util" "k8s.io/kubernetes/pkg/volume/util"
) )
@ -134,13 +133,7 @@ func (s *volumeStatCalculator) calcAndStoreStats() {
var ephemeralStats []stats.VolumeStats var ephemeralStats []stats.VolumeStats
var persistentStats []stats.VolumeStats var persistentStats []stats.VolumeStats
for name, v := range metricVolumes { for name, v := range metricVolumes {
metric, err := func() (*volume.Metrics, error) { metric, err := v.GetMetrics()
startTime := time.Now()
defer func() {
servermetrics.VolumeStatCalDuration.WithLabelValues().Observe(servermetrics.SinceInSeconds(startTime))
}()
return v.GetMetrics()
}()
if err != nil { if err != nil {
// Expected for Volumes that don't support Metrics // Expected for Volumes that don't support Metrics
if !volume.IsNotSupported(err) { if !volume.IsNotSupported(err) {

View File

@ -23,6 +23,7 @@ import (
"google.golang.org/grpc" "google.golang.org/grpc"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
servermetrics "k8s.io/kubernetes/pkg/kubelet/server/metrics"
"k8s.io/kubernetes/pkg/volume" "k8s.io/kubernetes/pkg/volume"
volumeutil "k8s.io/kubernetes/pkg/volume/util" volumeutil "k8s.io/kubernetes/pkg/volume/util"
) )
@ -51,6 +52,8 @@ func NewMetricsCsi(volumeID string, targetPath string, driverName csiDriverName)
} }
func (mc *metricsCsi) GetMetrics() (*volume.Metrics, error) { func (mc *metricsCsi) GetMetrics() (*volume.Metrics, error) {
startTime := time.Now()
defer servermetrics.CollectVolumeStatCalDuration(string(mc.csiClientGetter.driverName), startTime)
currentTime := metav1.Now() currentTime := metav1.Now()
ctx, cancel := context.WithTimeout(context.Background(), csiTimeout) ctx, cancel := context.WithTimeout(context.Background(), csiTimeout)
defer cancel() defer cancel()

View File

@ -21,9 +21,11 @@ import (
"io" "io"
"os" "os"
"runtime" "runtime"
"time"
"k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
servermetrics "k8s.io/kubernetes/pkg/kubelet/server/metrics"
) )
var _ MetricsProvider = &metricsBlock{} var _ MetricsProvider = &metricsBlock{}
@ -49,6 +51,9 @@ func NewMetricsBlock(device string) MetricsProvider {
// tools. Storage systems may have more information that they can provide by // tools. Storage systems may have more information that they can provide by
// going through specialized APIs. // going through specialized APIs.
func (mb *metricsBlock) GetMetrics() (*Metrics, error) { func (mb *metricsBlock) GetMetrics() (*Metrics, error) {
startTime := time.Now()
defer servermetrics.CollectVolumeStatCalDuration("block", startTime)
// TODO: Windows does not yet support VolumeMode=Block // TODO: Windows does not yet support VolumeMode=Block
if runtime.GOOS == "windows" { if runtime.GOOS == "windows" {
return nil, NewNotImplementedError("Windows does not support Block volumes") return nil, NewNotImplementedError("Windows does not support Block volumes")

View File

@ -17,8 +17,11 @@ limitations under the License.
package volume package volume
import ( import (
"time"
"k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
servermetrics "k8s.io/kubernetes/pkg/kubelet/server/metrics"
"k8s.io/kubernetes/pkg/volume/util/fs" "k8s.io/kubernetes/pkg/volume/util/fs"
) )
@ -41,6 +44,9 @@ func NewMetricsDu(path string) MetricsProvider {
// and gathering filesystem info for the Volume path. // and gathering filesystem info for the Volume path.
// See MetricsProvider.GetMetrics // See MetricsProvider.GetMetrics
func (md *metricsDu) GetMetrics() (*Metrics, error) { func (md *metricsDu) GetMetrics() (*Metrics, error) {
startTime := time.Now()
defer servermetrics.CollectVolumeStatCalDuration("du", startTime)
metrics := &Metrics{Time: metav1.Now()} metrics := &Metrics{Time: metav1.Now()}
if md.path == "" { if md.path == "" {
return metrics, NewNoPathDefinedError() return metrics, NewNoPathDefinedError()

View File

@ -17,8 +17,11 @@ limitations under the License.
package volume package volume
import ( import (
"time"
"k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
servermetrics "k8s.io/kubernetes/pkg/kubelet/server/metrics"
"k8s.io/kubernetes/pkg/volume/util/fs" "k8s.io/kubernetes/pkg/volume/util/fs"
) )
@ -40,6 +43,9 @@ func NewMetricsStatFS(path string) MetricsProvider {
// GetMetrics calculates the volume usage and device free space by executing "du" // GetMetrics calculates the volume usage and device free space by executing "du"
// and gathering filesystem info for the Volume path. // and gathering filesystem info for the Volume path.
func (md *metricsStatFS) GetMetrics() (*Metrics, error) { func (md *metricsStatFS) GetMetrics() (*Metrics, error) {
startTime := time.Now()
defer servermetrics.CollectVolumeStatCalDuration("statfs", startTime)
metrics := &Metrics{Time: metav1.Now()} metrics := &Metrics{Time: metav1.Now()}
if md.path == "" { if md.path == "" {
return metrics, NewNoPathDefinedError() return metrics, NewNoPathDefinedError()