Skip to content

Commit 99f2e78

Browse files
authored
Merge pull request kubernetes#77755 from gnufied/onlineresize-beta
Move online volume expansion to Beta
2 parents acb321e + 0f62e3f commit 99f2e78

File tree

7 files changed

+63
-20
lines changed

7 files changed

+63
-20
lines changed

pkg/features/kube_features.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ const (
106106
ExpandPersistentVolumes featuregate.Feature = "ExpandPersistentVolumes"
107107

108108
// owner: @mlmhl
109-
// alpha: v1.11
109+
// beta: v1.15
110110
// Ability to expand persistent volumes' file system without unmounting volumes.
111111
ExpandInUsePersistentVolumes featuregate.Feature = "ExpandInUsePersistentVolumes"
112112

@@ -507,7 +507,7 @@ var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureS
507507
TaintNodesByCondition: {Default: true, PreRelease: featuregate.Beta},
508508
QOSReserved: {Default: false, PreRelease: featuregate.Alpha},
509509
ExpandPersistentVolumes: {Default: true, PreRelease: featuregate.Beta},
510-
ExpandInUsePersistentVolumes: {Default: false, PreRelease: featuregate.Alpha},
510+
ExpandInUsePersistentVolumes: {Default: true, PreRelease: featuregate.Beta},
511511
ExpandCSIVolumes: {Default: false, PreRelease: featuregate.Alpha},
512512
AttachVolumeLimit: {Default: true, PreRelease: featuregate.Beta},
513513
CPUManager: {Default: true, PreRelease: featuregate.Beta},

pkg/kubelet/volumemanager/reconciler/reconciler.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -252,19 +252,19 @@ func (rc *reconciler) reconcile() {
252252
}
253253
} else if cache.IsFSResizeRequiredError(err) &&
254254
utilfeature.DefaultFeatureGate.Enabled(features.ExpandInUsePersistentVolumes) {
255-
klog.V(4).Infof(volumeToMount.GenerateMsgDetailed("Starting operationExecutor.ExpandVolumeFSWithoutUnmounting", ""))
256-
err := rc.operationExecutor.ExpandVolumeFSWithoutUnmounting(
255+
klog.V(4).Infof(volumeToMount.GenerateMsgDetailed("Starting operationExecutor.ExpandInUseVolume", ""))
256+
err := rc.operationExecutor.ExpandInUseVolume(
257257
volumeToMount.VolumeToMount,
258258
rc.actualStateOfWorld)
259259
if err != nil &&
260260
!nestedpendingoperations.IsAlreadyExists(err) &&
261261
!exponentialbackoff.IsExponentialBackoff(err) {
262262
// Ignore nestedpendingoperations.IsAlreadyExists and exponentialbackoff.IsExponentialBackoff errors, they are expected.
263263
// Log all other errors.
264-
klog.Errorf(volumeToMount.GenerateErrorDetailed("operationExecutor.ExpandVolumeFSWithoutUnmounting failed", err).Error())
264+
klog.Errorf(volumeToMount.GenerateErrorDetailed("operationExecutor.ExpandInUseVolume failed", err).Error())
265265
}
266266
if err == nil {
267-
klog.V(4).Infof(volumeToMount.GenerateMsgDetailed("operationExecutor.ExpandVolumeFSWithoutUnmounting started", ""))
267+
klog.V(4).Infof(volumeToMount.GenerateMsgDetailed("operationExecutor.ExpandInUseVolume started", ""))
268268
}
269269
}
270270
}

pkg/volume/util/operationexecutor/fakegenerator.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,8 +99,8 @@ func (f *fakeOGCounter) GenerateExpandVolumeFunc(*v1.PersistentVolumeClaim, *v1.
9999
return f.recordFuncCall("GenerateExpandVolumeFunc"), nil
100100
}
101101

102-
func (f *fakeOGCounter) GenerateExpandVolumeFSWithoutUnmountingFunc(volumeToMount VolumeToMount, actualStateOfWorld ActualStateOfWorldMounterUpdater) (volumetypes.GeneratedOperations, error) {
103-
return f.recordFuncCall("GenerateExpandVolumeFSWithoutUnmountingFunc"), nil
102+
func (f *fakeOGCounter) GenerateExpandInUseVolumeFunc(volumeToMount VolumeToMount, actualStateOfWorld ActualStateOfWorldMounterUpdater) (volumetypes.GeneratedOperations, error) {
103+
return f.recordFuncCall("GenerateExpandInUseVolumeFunc"), nil
104104
}
105105

106106
func (f *fakeOGCounter) recordFuncCall(name string) volumetypes.GeneratedOperations {

pkg/volume/util/operationexecutor/operation_executor.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -140,8 +140,8 @@ type OperationExecutor interface {
140140
// IsOperationPending returns true if an operation for the given volumeName and podName is pending,
141141
// otherwise it returns false
142142
IsOperationPending(volumeName v1.UniqueVolumeName, podName volumetypes.UniquePodName) bool
143-
// ExpandVolumeFSWithoutUnmounting will resize volume's file system to expected size without unmounting the volume.
144-
ExpandVolumeFSWithoutUnmounting(volumeToMount VolumeToMount, actualStateOfWorld ActualStateOfWorldMounterUpdater) error
143+
// ExpandInUseVolume will resize volume's file system to expected size without unmounting the volume.
144+
ExpandInUseVolume(volumeToMount VolumeToMount, actualStateOfWorld ActualStateOfWorldMounterUpdater) error
145145
// ReconstructVolumeOperation construct a new volumeSpec and returns it created by plugin
146146
ReconstructVolumeOperation(volumeMode v1.PersistentVolumeMode, plugin volume.VolumePlugin, mapperPlugin volume.BlockVolumePlugin, uid types.UID, podName volumetypes.UniquePodName, volumeSpecName string, volumePath string, pluginName string) (*volume.Spec, error)
147147
// CheckVolumeExistenceOperation checks volume existence
@@ -820,8 +820,8 @@ func (oe *operationExecutor) UnmountDevice(
820820
deviceToDetach.VolumeName, podName, generatedOperations)
821821
}
822822

823-
func (oe *operationExecutor) ExpandVolumeFSWithoutUnmounting(volumeToMount VolumeToMount, actualStateOfWorld ActualStateOfWorldMounterUpdater) error {
824-
generatedOperations, err := oe.operationGenerator.GenerateExpandVolumeFSWithoutUnmountingFunc(volumeToMount, actualStateOfWorld)
823+
func (oe *operationExecutor) ExpandInUseVolume(volumeToMount VolumeToMount, actualStateOfWorld ActualStateOfWorldMounterUpdater) error {
824+
generatedOperations, err := oe.operationGenerator.GenerateExpandInUseVolumeFunc(volumeToMount, actualStateOfWorld)
825825
if err != nil {
826826
return err
827827
}

pkg/volume/util/operationexecutor/operation_executor_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -462,7 +462,7 @@ func (fopg *fakeOperationGenerator) GenerateExpandVolumeFunc(pvc *v1.PersistentV
462462
}, nil
463463
}
464464

465-
func (fopg *fakeOperationGenerator) GenerateExpandVolumeFSWithoutUnmountingFunc(volumeToMount VolumeToMount, actualStateOfWorld ActualStateOfWorldMounterUpdater) (volumetypes.GeneratedOperations, error) {
465+
func (fopg *fakeOperationGenerator) GenerateExpandInUseVolumeFunc(volumeToMount VolumeToMount, actualStateOfWorld ActualStateOfWorldMounterUpdater) (volumetypes.GeneratedOperations, error) {
466466
opFunc := func() (error, error) {
467467
startOperationAndBlock(fopg.ch, fopg.quit)
468468
return nil, nil

pkg/volume/util/operationexecutor/operation_generator.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ type OperationGenerator interface {
131131
GenerateExpandVolumeFunc(*v1.PersistentVolumeClaim, *v1.PersistentVolume) (volumetypes.GeneratedOperations, error)
132132

133133
// Generates the volume file system resize function, which can resize volume's file system to expected size without unmounting the volume.
134-
GenerateExpandVolumeFSWithoutUnmountingFunc(volumeToMount VolumeToMount, actualStateOfWorld ActualStateOfWorldMounterUpdater) (volumetypes.GeneratedOperations, error)
134+
GenerateExpandInUseVolumeFunc(volumeToMount VolumeToMount, actualStateOfWorld ActualStateOfWorldMounterUpdater) (volumetypes.GeneratedOperations, error)
135135
}
136136

137137
func (og *operationGenerator) GenerateVolumesAreAttachedFunc(
@@ -1578,7 +1578,7 @@ func (og *operationGenerator) GenerateExpandVolumeFunc(
15781578
}, nil
15791579
}
15801580

1581-
func (og *operationGenerator) GenerateExpandVolumeFSWithoutUnmountingFunc(
1581+
func (og *operationGenerator) GenerateExpandInUseVolumeFunc(
15821582
volumeToMount VolumeToMount,
15831583
actualStateOfWorld ActualStateOfWorldMounterUpdater) (volumetypes.GeneratedOperations, error) {
15841584

test/e2e/storage/volume_expand.go

Lines changed: 48 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ var _ = utils.SIGDescribe("Volume expand", func() {
104104
framework.ExpectError(err, "While updating non-expandable PVC")
105105
})
106106

107-
ginkgo.It("Verify if editing PVC allows resize", func() {
107+
ginkgo.It("Verify if offline PVC expansion works", func() {
108108
pvc, storageClassVar, err = setupFunc(true /* allowExpansion */, false /*BlockVolume*/)
109109
framework.ExpectNoError(err, "Error creating non-expandable PVC")
110110

@@ -122,6 +122,11 @@ var _ = utils.SIGDescribe("Volume expand", func() {
122122
framework.ExpectNoError(err, "while cleaning up pod already deleted in resize test")
123123
}()
124124

125+
ginkgo.By("Deleting the previously created pod")
126+
err = framework.DeletePodWithWait(f, c, pod)
127+
framework.ExpectNoError(err, "while deleting pod for resizing")
128+
129+
// We expand the PVC while no pod is using it to ensure offline expansion
125130
ginkgo.By("Expanding current pvc")
126131
newSize := resource.MustParse("6Gi")
127132
pvc, err = expandPVCSize(pvc, newSize, c)
@@ -145,10 +150,6 @@ var _ = utils.SIGDescribe("Volume expand", func() {
145150
gomega.Expect(len(inProgressConditions)).To(gomega.Equal(1), "pvc must have file system resize pending condition")
146151
gomega.Expect(inProgressConditions[0].Type).To(gomega.Equal(v1.PersistentVolumeClaimFileSystemResizePending), "pvc must have fs resizing condition")
147152

148-
ginkgo.By("Deleting the previously created pod")
149-
err = framework.DeletePodWithWait(f, c, pod)
150-
framework.ExpectNoError(err, "while deleting pod for resizing")
151-
152153
ginkgo.By("Creating a new pod with same volume")
153154
pod2, err := framework.CreatePod(c, ns, nil, pvcClaims, false, "")
154155
framework.ExpectNoError(err, "while recreating pod for resizing")
@@ -165,6 +166,48 @@ var _ = utils.SIGDescribe("Volume expand", func() {
165166
gomega.Expect(len(pvcConditions)).To(gomega.Equal(0), "pvc should not have conditions")
166167
})
167168

169+
ginkgo.It("should resize volume when PVC is edited while pod is using it", func() {
170+
pvc, storageClassVar, err = setupFunc(true /* allowExpansion */, false /*BlockVolume*/)
171+
framework.ExpectNoError(err, "Error creating non-expandable PVC")
172+
173+
ginkgo.By("Waiting for pvc to be in bound phase")
174+
pvcClaims := []*v1.PersistentVolumeClaim{pvc}
175+
pvs, err := framework.WaitForPVClaimBoundPhase(c, pvcClaims, framework.ClaimProvisionTimeout)
176+
framework.ExpectNoError(err, "Failed waiting for PVC to be bound %v", err)
177+
gomega.Expect(len(pvs)).To(gomega.Equal(1))
178+
179+
ginkgo.By("Creating a pod with dynamically provisioned volume")
180+
pod, err := framework.CreatePod(c, ns, nil, pvcClaims, false, "")
181+
framework.ExpectNoError(err, "While creating pods for resizing")
182+
defer func() {
183+
err = framework.DeletePodWithWait(f, c, pod)
184+
framework.ExpectNoError(err, "while cleaning up pod already deleted in resize test")
185+
}()
186+
187+
// We expand the PVC while no pod is using it to ensure online expansion
188+
ginkgo.By("Expanding current pvc")
189+
newSize := resource.MustParse("6Gi")
190+
pvc, err = expandPVCSize(pvc, newSize, c)
191+
framework.ExpectNoError(err, "While updating pvc for more size")
192+
gomega.Expect(pvc).NotTo(gomega.BeNil())
193+
194+
pvcSize := pvc.Spec.Resources.Requests[v1.ResourceStorage]
195+
if pvcSize.Cmp(newSize) != 0 {
196+
framework.Failf("error updating pvc size %q", pvc.Name)
197+
}
198+
199+
ginkgo.By("Waiting for cloudprovider resize to finish")
200+
err = waitForControllerVolumeResize(pvc, c, totalResizeWaitPeriod)
201+
framework.ExpectNoError(err, "While waiting for pvc resize to finish")
202+
203+
ginkgo.By("Waiting for file system resize to finish")
204+
pvc, err = waitForFSResize(pvc, c)
205+
framework.ExpectNoError(err, "while waiting for fs resize to finish")
206+
207+
pvcConditions := pvc.Status.Conditions
208+
gomega.Expect(len(pvcConditions)).To(gomega.Equal(0), "pvc should not have conditions")
209+
})
210+
168211
ginkgo.It("should allow expansion of block volumes", func() {
169212
pvc, storageClassVar, err = setupFunc(true /*allowExpansion*/, true /*blockVolume*/)
170213

0 commit comments

Comments
 (0)