From f2cf5099599de03aad42cc2ed086804851595dc0 Mon Sep 17 00:00:00 2001 From: Hemant Kumar Date: Wed, 7 May 2025 10:06:26 -0400 Subject: [PATCH] UPSTREAM: 131495: Handle unsupported node expansion for RWX volumes Co-authored-by: Hemant Kumar Signed-off-by: carlory --- .../util/operationexecutor/node_expander.go | 20 +++++++++++++++++++ .../operationexecutor/node_expander_test.go | 12 +++++++++++ 2 files changed, 32 insertions(+) diff --git a/pkg/volume/util/operationexecutor/node_expander.go b/pkg/volume/util/operationexecutor/node_expander.go index fb4366df0601b..a7c98725543db 100644 --- a/pkg/volume/util/operationexecutor/node_expander.go +++ b/pkg/volume/util/operationexecutor/node_expander.go @@ -144,6 +144,26 @@ func (ne *NodeExpander) expandOnPlugin() (bool, resource.Quantity, error) { } _, resizeErr := ne.volumePlugin.NodeExpand(ne.pluginResizeOpts) if resizeErr != nil { + // In order to support node volume expansion for RWX volumes on different nodes, + // we bypass the check for VolumeExpansionPendingOnNode state during the pre-check + // and then directly call the NodeExpandVolume method on the plugin. + // + // However, it does not make sense where the csi driver does not support node expansion. + // We should not treat this as a failure. It is a workaround for this issue: + // https://github.com/kubernetes/kubernetes/issues/131381. + // + // For other access modes, we should not hit this state, because we will wait for + // VolumeExpansionPendingOnNode before trying to expand volume in kubelet. + // See runPreCheck() above. + // + // If volume is already expanded, then we should not retry expansion on the node if + // driver returns OperationNotSupportedError. + if volumetypes.IsOperationNotSupportedError(resizeErr) && ne.pvcAlreadyUpdated { + klog.V(4).InfoS(ne.vmt.GenerateMsgDetailed("MountVolume.NodeExpandVolume failed", "NodeExpandVolume not supported"), "pod", klog.KObj(ne.vmt.Pod)) + ne.testStatus = testResponseData{assumeResizeFinished: true, resizeCalledOnPlugin: false} + return true, ne.pluginResizeOpts.NewSize, nil + } + if volumetypes.IsOperationFinishedError(resizeErr) { var markFailedError error ne.actualStateOfWorld.MarkVolumeExpansionFailedWithFinalError(ne.vmt.VolumeName) diff --git a/pkg/volume/util/operationexecutor/node_expander_test.go b/pkg/volume/util/operationexecutor/node_expander_test.go index 01c3f75253f93..0d307150e41b1 100644 --- a/pkg/volume/util/operationexecutor/node_expander_test.go +++ b/pkg/volume/util/operationexecutor/node_expander_test.go @@ -139,6 +139,18 @@ func TestNodeExpander(t *testing.T) { expectFinalErrors: false, expectedStatusSize: resource.MustParse("2G"), }, + { + name: "RWX pv.spec.cap = pvc.status.cap, resizeStatus='', desiredSize > actualSize, reize_op=unsupported", + pvc: addAccessMode(getTestPVC(volumetesting.FailWithUnSupportedVolumeName, "2G", "2G", "2G", nil), v1.ReadWriteMany), + pv: getTestPV(volumetesting.FailWithUnSupportedVolumeName, "2G"), + recoverVolumeExpansionFailure: true, + expectError: false, + expectedResizeStatus: "", + expectResizeCall: false, + assumeResizeOpAsFinished: true, + expectFinalErrors: false, + expectedStatusSize: resource.MustParse("2G"), + }, { name: "pv.spec.cap > pvc.status.cap, resizeStatus=node_expansion_pending, featuregate=disabled", pvc: getTestPVC("test-vol0", "2G", "1G", "2G", &nodeResizePending),