Skip to content

Commit 90906ab

Browse files
committed
Reduce memory usage/allocations during wait for volume attachment
After a node restart kubelet tries to (re)attach all volumes to the pods. We poll the `verifyVolumesMountedFunc` every 300ms to check whether the mount has succeeded. This function called the `GetMountedVolumesForPod` function that allocates memory for every volumes on every pod (`len(asw.attachedVolumes)`). Because this function is executed for every pod simultaneously, this results in exponential memory usage and high cpu usage due to garbage collection. We already know the exact volume names and pod name and are able to completly remove the slice allocation. Signed-off-by: Luca Berneking <[email protected]>
1 parent 60c4c2b commit 90906ab

File tree

2 files changed

+45
-3
lines changed

2 files changed

+45
-3
lines changed

pkg/kubelet/volumemanager/cache/actual_state_of_world.go

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,9 @@ type ActualStateOfWorld interface {
120120
// and false is returned.
121121
PodRemovedFromVolume(podName volumetypes.UniquePodName, volumeName v1.UniqueVolumeName) bool
122122

123+
// PodHasMountedVolumes returns true if any volume is mounted on the given pod
124+
PodHasMountedVolumes(podName volumetypes.UniquePodName) bool
125+
123126
// VolumeExistsWithSpecName returns true if the given volume specified with the
124127
// volume spec name (a.k.a., InnerVolumeSpecName) exists in the list of
125128
// volumes that should be attached to this node.
@@ -146,6 +149,10 @@ type ActualStateOfWorld interface {
146149
// current actual state of the world.
147150
GetMountedVolumesForPod(podName volumetypes.UniquePodName) []MountedVolume
148151

152+
// GetMountedVolumeForPodByOuterVolumeSpecName returns the volume and true if
153+
// the given outerVolumeSpecName is mounted on the given pod.
154+
GetMountedVolumeForPodByOuterVolumeSpecName(podName volumetypes.UniquePodName, outerVolumeSpecName string) (MountedVolume, bool)
155+
149156
// GetPossiblyMountedVolumesForPod generates and returns a list of volumes for
150157
// the specified pod that either are attached and mounted or are "uncertain",
151158
// i.e. a volume plugin may be mounting the volume right now.
@@ -948,6 +955,20 @@ func (asw *actualStateOfWorld) PodExistsInVolume(podName volumetypes.UniquePodNa
948955
return podExists, volumeObj.devicePath, nil
949956
}
950957

958+
func (asw *actualStateOfWorld) PodHasMountedVolumes(podName volumetypes.UniquePodName) bool {
959+
asw.RLock()
960+
defer asw.RUnlock()
961+
for _, volumeObj := range asw.attachedVolumes {
962+
if podObj, hasPod := volumeObj.mountedPods[podName]; hasPod {
963+
if podObj.volumeMountStateForPod == operationexecutor.VolumeMounted {
964+
return true
965+
}
966+
}
967+
}
968+
969+
return false
970+
}
971+
951972
func (asw *actualStateOfWorld) volumeNeedsExpansion(volumeObj attachedVolume, desiredVolumeSize resource.Quantity) (resource.Quantity, bool) {
952973
currentSize := resource.Quantity{}
953974
if volumeObj.persistentVolumeSize != nil {
@@ -1061,7 +1082,7 @@ func (asw *actualStateOfWorld) GetMountedVolumesForPod(
10611082
podName volumetypes.UniquePodName) []MountedVolume {
10621083
asw.RLock()
10631084
defer asw.RUnlock()
1064-
mountedVolume := make([]MountedVolume, 0 /* len */, len(asw.attachedVolumes) /* cap */)
1085+
mountedVolume := make([]MountedVolume, 0 /* len */)
10651086
for _, volumeObj := range asw.attachedVolumes {
10661087
for mountedPodName, podObj := range volumeObj.mountedPods {
10671088
if mountedPodName == podName && podObj.volumeMountStateForPod == operationexecutor.VolumeMounted {
@@ -1075,6 +1096,21 @@ func (asw *actualStateOfWorld) GetMountedVolumesForPod(
10751096
return mountedVolume
10761097
}
10771098

1099+
func (asw *actualStateOfWorld) GetMountedVolumeForPodByOuterVolumeSpecName(
1100+
podName volumetypes.UniquePodName, outerVolumeSpecName string) (MountedVolume, bool) {
1101+
asw.RLock()
1102+
defer asw.RUnlock()
1103+
for _, volumeObj := range asw.attachedVolumes {
1104+
if podObj, hasPod := volumeObj.mountedPods[podName]; hasPod {
1105+
if podObj.volumeMountStateForPod == operationexecutor.VolumeMounted && podObj.outerVolumeSpecName == outerVolumeSpecName {
1106+
return getMountedVolume(&podObj, &volumeObj), true
1107+
}
1108+
}
1109+
}
1110+
1111+
return MountedVolume{}, false
1112+
}
1113+
10781114
func (asw *actualStateOfWorld) GetPossiblyMountedVolumesForPod(
10791115
podName volumetypes.UniquePodName) []MountedVolume {
10801116
asw.RLock()

pkg/kubelet/volumemanager/volume_manager.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -514,7 +514,13 @@ func (vm *volumeManager) verifyVolumesMountedFunc(podName types.UniquePodName, e
514514
if errs := vm.desiredStateOfWorld.PopPodErrors(podName); len(errs) > 0 {
515515
return true, errors.New(strings.Join(errs, "; "))
516516
}
517-
return len(vm.getUnmountedVolumes(podName, expectedVolumes)) == 0, nil
517+
for _, expectedVolume := range expectedVolumes {
518+
_, found := vm.actualStateOfWorld.GetMountedVolumeForPodByOuterVolumeSpecName(podName, expectedVolume)
519+
if !found {
520+
return false, nil
521+
}
522+
}
523+
return true, nil
518524
}
519525
}
520526

@@ -525,7 +531,7 @@ func (vm *volumeManager) verifyVolumesUnmountedFunc(podName types.UniquePodName)
525531
if errs := vm.desiredStateOfWorld.PopPodErrors(podName); len(errs) > 0 {
526532
return true, errors.New(strings.Join(errs, "; "))
527533
}
528-
return len(vm.actualStateOfWorld.GetMountedVolumesForPod(podName)) == 0, nil
534+
return !vm.actualStateOfWorld.PodHasMountedVolumes(podName), nil
529535
}
530536
}
531537

0 commit comments

Comments
 (0)