diff --git a/pkg/kubelet/volumemanager/cache/actual_state_of_world.go b/pkg/kubelet/volumemanager/cache/actual_state_of_world.go index 61ddf9d7d36..b048cf0ecd9 100644 --- a/pkg/kubelet/volumemanager/cache/actual_state_of_world.go +++ b/pkg/kubelet/volumemanager/cache/actual_state_of_world.go @@ -171,6 +171,10 @@ type ActualStateOfWorld interface { // to the node. This list can be used to determine volumes that are either in-use // or have a mount/unmount operation pending. GetAttachedVolumes() []AttachedVolume + + // SyncReconstructedVolume check the volume.outerVolumeSpecName in asw and + // the one populated from dsw , if they do not match, update this field from the value from dsw. + SyncReconstructedVolume(volumeName v1.UniqueVolumeName, podName volumetypes.UniquePodName, outerVolumeSpecName string) } // MountedVolume represents a volume that has successfully been mounted to a pod. @@ -885,6 +889,19 @@ func (asw *actualStateOfWorld) GetUnmountedVolumes() []AttachedVolume { return unmountedVolumes } +func (asw *actualStateOfWorld) SyncReconstructedVolume(volumeName v1.UniqueVolumeName, podName volumetypes.UniquePodName, outerVolumeSpecName string) { + asw.Lock() + defer asw.Unlock() + if volumeObj, volumeExists := asw.attachedVolumes[volumeName]; volumeExists { + if podObj, podExists := volumeObj.mountedPods[podName]; podExists { + if podObj.outerVolumeSpecName != outerVolumeSpecName { + podObj.outerVolumeSpecName = outerVolumeSpecName + asw.attachedVolumes[volumeName].mountedPods[podName] = podObj + } + } + } +} + func (asw *actualStateOfWorld) newAttachedVolume( attachedVolume *attachedVolume) AttachedVolume { return AttachedVolume{ diff --git a/pkg/kubelet/volumemanager/populator/desired_state_of_world_populator.go b/pkg/kubelet/volumemanager/populator/desired_state_of_world_populator.go index d9f6c1026b6..2e4d0e4148c 100644 --- a/pkg/kubelet/volumemanager/populator/desired_state_of_world_populator.go +++ b/pkg/kubelet/volumemanager/populator/desired_state_of_world_populator.go @@ -306,7 +306,7 @@ func (dswp *desiredStateOfWorldPopulator) processPodVolumes( } // Add volume to desired state of world - _, err = dswp.desiredStateOfWorld.AddPodToVolume( + uniqueVolumeName, err := dswp.desiredStateOfWorld.AddPodToVolume( uniquePodName, pod, volumeSpec, podVolume.Name, volumeGidValue) if err != nil { klog.ErrorS(err, "Failed to add volume to desiredStateOfWorld", "pod", klog.KObj(pod), "volumeName", podVolume.Name, "volumeSpecName", volumeSpec.Name()) @@ -315,6 +315,8 @@ func (dswp *desiredStateOfWorldPopulator) processPodVolumes( } else { klog.V(4).InfoS("Added volume to desired state", "pod", klog.KObj(pod), "volumeName", podVolume.Name, "volumeSpecName", volumeSpec.Name()) } + // sync reconstructed volume + dswp.actualStateOfWorld.SyncReconstructedVolume(uniqueVolumeName, uniquePodName, podVolume.Name) if expandInUsePV { dswp.checkVolumeFSResize(pod, podVolume, pvc, volumeSpec, diff --git a/pkg/kubelet/volumemanager/populator/desired_state_of_world_populator_test.go b/pkg/kubelet/volumemanager/populator/desired_state_of_world_populator_test.go index 1691b57c195..793b5111e45 100644 --- a/pkg/kubelet/volumemanager/populator/desired_state_of_world_populator_test.go +++ b/pkg/kubelet/volumemanager/populator/desired_state_of_world_populator_test.go @@ -83,6 +83,72 @@ func prepareDswpWithVolume(t *testing.T) (*desiredStateOfWorldPopulator, kubepod return dswp, fakePodManager } +func TestFindAndAddNewPods_WithRescontructedVolume(t *testing.T) { + // create dswp + dswp, fakePodManager := prepareDswpWithVolume(t) + + // create pod + fakeOuterVolumeName := "dswp-test-volume-name" + containers := []v1.Container{ + { + VolumeMounts: []v1.VolumeMount{ + { + Name: fakeOuterVolumeName, + MountPath: "/mnt", + }, + }, + }, + } + pod := createPodWithVolume("dswp-test-pod", fakeOuterVolumeName, "file-bound", containers) + + fakePodManager.AddPod(pod) + + podName := util.GetUniquePodName(pod) + + mode := v1.PersistentVolumeFilesystem + pv := &v1.PersistentVolume{ + ObjectMeta: metav1.ObjectMeta{ + Name: fakeOuterVolumeName, + }, + Spec: v1.PersistentVolumeSpec{ + ClaimRef: &v1.ObjectReference{Namespace: "ns", Name: "file-bound"}, + VolumeMode: &mode, + }, + } + generatedVolumeName := "fake-plugin/" + pod.Spec.Volumes[0].Name + uniqueVolumeName := v1.UniqueVolumeName(generatedVolumeName) + expectedOuterVolumeName := "dswp-test-volume-name" + + opts := operationexecutor.MarkVolumeOpts{ + PodName: podName, + PodUID: pod.UID, + VolumeName: uniqueVolumeName, + OuterVolumeSpecName: generatedVolumeName, // fake reconstructed volume + VolumeGidVolume: "", + VolumeSpec: volume.NewSpecFromPersistentVolume(pv, false), + VolumeMountState: operationexecutor.VolumeMounted, + } + dswp.actualStateOfWorld.MarkVolumeAsAttached(opts.VolumeName, opts.VolumeSpec, "fake-node", "") + dswp.actualStateOfWorld.MarkVolumeAsMounted(opts) + + dswp.findAndAddNewPods() + + mountedVolumes := dswp.actualStateOfWorld.GetMountedVolumesForPod(podName) + found := false + for _, volume := range mountedVolumes { + if volume.OuterVolumeSpecName == expectedOuterVolumeName { + found = true + break + } + } + if !found { + t.Fatalf( + "Could not found pod volume %v in the list of actual state of world volumes to mount.", + expectedOuterVolumeName) + } + +} + func TestFindAndAddNewPods_WithReprocessPodAndVolumeRetrievalError(t *testing.T) { // create dswp dswp, fakePodManager := prepareDswpWithVolume(t) diff --git a/pkg/kubelet/volumemanager/reconciler/reconciler.go b/pkg/kubelet/volumemanager/reconciler/reconciler.go index 5966cd969d9..8736c22c4b3 100644 --- a/pkg/kubelet/volumemanager/reconciler/reconciler.go +++ b/pkg/kubelet/volumemanager/reconciler/reconciler.go @@ -579,7 +579,8 @@ func (rc *reconciler) reconstructVolume(volume podVolume) (*reconstructedVolume, volumeSpec: volumeSpec, // volume.volumeSpecName is actually InnerVolumeSpecName. It will not be used // for volume cleanup. - // TODO: in case pod is added back before reconciler starts to unmount, we can update this field from desired state information + // in case pod is added back to desired state, outerVolumeSpecName will be updated from dsw information. + // See issue #103143 and its fix for details. outerVolumeSpecName: volume.volumeSpecName, pod: pod, deviceMounter: deviceMounter,