Skip to content

Commit 757e6a0

Browse files
authored
Merge pull request #1442 from k8s-infra-cherrypick-robot/cherry-pick-1440-to-release-1.24
[release-1.24] fix: add VolumeStats cache to avoid massive statfs calls
2 parents 08a7433 + 8da08c7 commit 757e6a0

File tree

3 files changed

+60
-2
lines changed

3 files changed

+60
-2
lines changed

pkg/azurefile/azurefile.go

+10
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,7 @@ type DriverOptions struct {
199199
KubeAPIBurst int
200200
AppendNoShareSockOption bool
201201
SkipMatchingTagCacheExpireInMinutes int
202+
VolStatsCacheExpireInMinutes int
202203
}
203204

204205
// Driver implements all interfaces of CSI drivers
@@ -243,6 +244,8 @@ type Driver struct {
243244
skipMatchingTagCache *azcache.TimedCache
244245
// a timed cache when resize file share failed due to account limit exceeded
245246
resizeFileShareFailureCache *azcache.TimedCache
247+
// a timed cache storing volume stats <volumeID, volumeStats>
248+
volStatsCache *azcache.TimedCache
246249
}
247250

248251
// NewDriver Creates a NewCSIDriver object. Assumes vendor version is equal to driver version &
@@ -299,6 +302,13 @@ func NewDriver(options *DriverOptions) *Driver {
299302
klog.Fatalf("%v", err)
300303
}
301304

305+
if options.VolStatsCacheExpireInMinutes <= 0 {
306+
options.VolStatsCacheExpireInMinutes = 10 // default expire in 10 minutes
307+
}
308+
if driver.volStatsCache, err = azcache.NewTimedcache(time.Duration(options.VolStatsCacheExpireInMinutes)*time.Minute, getter); err != nil {
309+
klog.Fatalf("%v", err)
310+
}
311+
302312
return &driver
303313
}
304314

pkg/azurefile/nodeserver.go

+48-2
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ import (
3737
"google.golang.org/grpc/status"
3838

3939
"golang.org/x/net/context"
40+
41+
azcache "sigs.k8s.io/cloud-provider-azure/pkg/cache"
4042
)
4143

4244
// NodePublishVolume mount the volume from staging to target path
@@ -422,13 +424,48 @@ func (d *Driver) NodeGetVolumeStats(ctx context.Context, req *csi.NodeGetVolumeS
422424
return nil, status.Error(codes.InvalidArgument, "NodeGetVolumeStats volume path was empty")
423425
}
424426

427+
// check if the volume stats is cached
428+
cache, err := d.volStatsCache.Get(req.VolumeId, azcache.CacheReadTypeDefault)
429+
if err != nil {
430+
return nil, status.Errorf(codes.Internal, err.Error())
431+
}
432+
if cache != nil {
433+
resp := cache.(csi.NodeGetVolumeStatsResponse)
434+
klog.V(6).Infof("NodeGetVolumeStats: volume stats for volume %s path %s is cached", req.VolumeId, req.VolumePath)
435+
return &resp, nil
436+
}
437+
438+
// fileShareName in volumeID may contain subPath, e.g. csi-shared-config/ASCP01/certs
439+
// get the file share name without subPath from volumeID and check the cache again using new volumeID
440+
var newVolID string
441+
if _, accountName, fileShareName, _, secretNamespace, _, err := GetFileShareInfo(req.VolumeId); err == nil {
442+
if splitStr := strings.Split(fileShareName, "/"); len(splitStr) > 1 {
443+
fileShareName = splitStr[0]
444+
}
445+
// get new volumeID
446+
if accountName != "" && fileShareName != "" {
447+
newVolID = fmt.Sprintf(volumeIDTemplate, "", accountName, fileShareName, "", "", secretNamespace)
448+
}
449+
}
450+
451+
if cache, err = d.volStatsCache.Get(newVolID, azcache.CacheReadTypeDefault); err != nil {
452+
return nil, status.Errorf(codes.Internal, err.Error())
453+
}
454+
if cache != nil {
455+
resp := cache.(csi.NodeGetVolumeStatsResponse)
456+
klog.V(6).Infof("NodeGetVolumeStats: volume stats for volume %s path %s is cached", req.VolumeId, req.VolumePath)
457+
return &resp, nil
458+
}
459+
425460
if _, err := os.Lstat(req.VolumePath); err != nil {
426461
if os.IsNotExist(err) {
427462
return nil, status.Errorf(codes.NotFound, "path %s does not exist", req.VolumePath)
428463
}
429464
return nil, status.Errorf(codes.Internal, "failed to stat file %s: %v", req.VolumePath, err)
430465
}
431466

467+
klog.V(6).Infof("NodeGetVolumeStats: begin to get VolumeStats on volume %s path %s", req.VolumeId, req.VolumePath)
468+
432469
volumeMetrics, err := volume.NewMetricsStatFS(req.VolumePath).GetMetrics()
433470
if err != nil {
434471
return nil, status.Errorf(codes.Internal, "failed to get metrics: %v", err)
@@ -460,7 +497,7 @@ func (d *Driver) NodeGetVolumeStats(ctx context.Context, req *csi.NodeGetVolumeS
460497
return nil, status.Errorf(codes.Internal, "failed to transform disk inodes used(%v)", volumeMetrics.InodesUsed)
461498
}
462499

463-
return &csi.NodeGetVolumeStatsResponse{
500+
resp := &csi.NodeGetVolumeStatsResponse{
464501
Usage: []*csi.VolumeUsage{
465502
{
466503
Unit: csi.VolumeUsage_BYTES,
@@ -475,7 +512,16 @@ func (d *Driver) NodeGetVolumeStats(ctx context.Context, req *csi.NodeGetVolumeS
475512
Used: inodesUsed,
476513
},
477514
},
478-
}, nil
515+
}
516+
517+
klog.V(6).Infof("NodeGetVolumeStats: volume stats for volume %s path %s is %v", req.VolumeId, req.VolumePath, resp)
518+
// cache the volume stats per volume
519+
d.volStatsCache.Set(req.VolumeId, *resp)
520+
if newVolID != "" {
521+
d.volStatsCache.Set(newVolID, *resp)
522+
}
523+
524+
return resp, nil
479525
}
480526

481527
// NodeExpandVolume node expand volume

pkg/azurefileplugin/main.go

+2
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ var (
5656
kubeAPIBurst = flag.Int("kube-api-burst", 50, "Burst to use while communicating with the kubernetes apiserver.")
5757
appendNoShareSockOption = flag.Bool("append-nosharesock-option", true, "Whether appending nosharesock option to smb mount command")
5858
skipMatchingTagCacheExpireInMinutes = flag.Int("skip-matching-tag-cache-expire-in-minutes", 30, "The cache expire time in minutes for skipMatchingTagCache")
59+
volStatsCacheExpireInMinutes = flag.Int("vol-stats-cache-expire-in-minutes", 10, "The cache expire time in minutes for volume stats cache")
5960
)
6061

6162
func main() {
@@ -97,6 +98,7 @@ func handle() {
9798
KubeAPIBurst: *kubeAPIBurst,
9899
AppendNoShareSockOption: *appendNoShareSockOption,
99100
SkipMatchingTagCacheExpireInMinutes: *skipMatchingTagCacheExpireInMinutes,
101+
VolStatsCacheExpireInMinutes: *volStatsCacheExpireInMinutes,
100102
}
101103
driver := azurefile.NewDriver(&driverOptions)
102104
if driver == nil {

0 commit comments

Comments
 (0)