mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-23 19:56:01 +00:00
Merge pull request #103181 from 249043822/bugfix-volumemanager
Add sync reconstructed volume from desired state of world for volumemanager
This commit is contained in:
commit
6aa160f3ba
@ -171,6 +171,10 @@ type ActualStateOfWorld interface {
|
|||||||
// to the node. This list can be used to determine volumes that are either in-use
|
// to the node. This list can be used to determine volumes that are either in-use
|
||||||
// or have a mount/unmount operation pending.
|
// or have a mount/unmount operation pending.
|
||||||
GetAttachedVolumes() []AttachedVolume
|
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.
|
// MountedVolume represents a volume that has successfully been mounted to a pod.
|
||||||
@ -885,6 +889,19 @@ func (asw *actualStateOfWorld) GetUnmountedVolumes() []AttachedVolume {
|
|||||||
return unmountedVolumes
|
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(
|
func (asw *actualStateOfWorld) newAttachedVolume(
|
||||||
attachedVolume *attachedVolume) AttachedVolume {
|
attachedVolume *attachedVolume) AttachedVolume {
|
||||||
return AttachedVolume{
|
return AttachedVolume{
|
||||||
|
@ -306,7 +306,7 @@ func (dswp *desiredStateOfWorldPopulator) processPodVolumes(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add volume to desired state of world
|
// Add volume to desired state of world
|
||||||
_, err = dswp.desiredStateOfWorld.AddPodToVolume(
|
uniqueVolumeName, err := dswp.desiredStateOfWorld.AddPodToVolume(
|
||||||
uniquePodName, pod, volumeSpec, podVolume.Name, volumeGidValue)
|
uniquePodName, pod, volumeSpec, podVolume.Name, volumeGidValue)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.ErrorS(err, "Failed to add volume to desiredStateOfWorld", "pod", klog.KObj(pod), "volumeName", podVolume.Name, "volumeSpecName", volumeSpec.Name())
|
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 {
|
} else {
|
||||||
klog.V(4).InfoS("Added volume to desired state", "pod", klog.KObj(pod), "volumeName", podVolume.Name, "volumeSpecName", volumeSpec.Name())
|
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 {
|
if expandInUsePV {
|
||||||
dswp.checkVolumeFSResize(pod, podVolume, pvc, volumeSpec,
|
dswp.checkVolumeFSResize(pod, podVolume, pvc, volumeSpec,
|
||||||
|
@ -83,6 +83,72 @@ func prepareDswpWithVolume(t *testing.T) (*desiredStateOfWorldPopulator, kubepod
|
|||||||
return dswp, fakePodManager
|
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) {
|
func TestFindAndAddNewPods_WithReprocessPodAndVolumeRetrievalError(t *testing.T) {
|
||||||
// create dswp
|
// create dswp
|
||||||
dswp, fakePodManager := prepareDswpWithVolume(t)
|
dswp, fakePodManager := prepareDswpWithVolume(t)
|
||||||
|
@ -579,7 +579,8 @@ func (rc *reconciler) reconstructVolume(volume podVolume) (*reconstructedVolume,
|
|||||||
volumeSpec: volumeSpec,
|
volumeSpec: volumeSpec,
|
||||||
// volume.volumeSpecName is actually InnerVolumeSpecName. It will not be used
|
// volume.volumeSpecName is actually InnerVolumeSpecName. It will not be used
|
||||||
// for volume cleanup.
|
// 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,
|
outerVolumeSpecName: volume.volumeSpecName,
|
||||||
pod: pod,
|
pod: pod,
|
||||||
deviceMounter: deviceMounter,
|
deviceMounter: deviceMounter,
|
||||||
|
Loading…
Reference in New Issue
Block a user