Skip to content

Disable node expansion if not required #496

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions pkg/controller/expand_and_recover.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"github.com/kubernetes-csi/external-resizer/pkg/util"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/klog/v2"
)

Expand Down Expand Up @@ -196,6 +197,27 @@ func (ctrl *resizeController) expandAndRecover(pvc *v1.PersistentVolumeClaim, pv
return pvc, pv, nil, true
}

func (ctrl *resizeController) removeNodeExpansionNotRequiredAnnotation(pvc *v1.PersistentVolumeClaim) *v1.PersistentVolumeClaim {
if !metav1.HasAnnotation(pvc.ObjectMeta, util.NodeExpansionNotRequired) {
return pvc
}

delete(pvc.Annotations, util.NodeExpansionNotRequired)
return pvc
}

func (ctrl *resizeController) addNodeExpansionNotRequiredAnnotation(pvc *v1.PersistentVolumeClaim) *v1.PersistentVolumeClaim {
if metav1.HasAnnotation(pvc.ObjectMeta, util.NodeExpansionNotRequired) {
return pvc
}

if pvc.Annotations == nil {
pvc.Annotations = make(map[string]string)
}
pvc.Annotations[util.NodeExpansionNotRequired] = "true"
return pvc
}

func (ctrl *resizeController) markForSlowRetry(pvcKey string, resizeStatus v1.ClaimResourceStatus) {
if resizeStatus == v1.PersistentVolumeClaimControllerResizeInfeasible {
ctrl.slowSet.Add(pvcKey)
Expand Down
48 changes: 29 additions & 19 deletions pkg/controller/expand_and_recover_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@ import (
"github.com/kubernetes-csi/external-resizer/pkg/features"
"github.com/kubernetes-csi/external-resizer/pkg/resizer"
"github.com/kubernetes-csi/external-resizer/pkg/testutil"
"github.com/kubernetes-csi/external-resizer/pkg/util"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/sets"
utilfeature "k8s.io/apiserver/pkg/util/feature"
Expand All @@ -29,21 +31,24 @@ func TestExpandAndRecover(t *testing.T) {
pv *v1.PersistentVolume
disableNodeExpansion bool
disableControllerExpansion bool

// expectations of test
expectedResizeStatus v1.ClaimResourceStatus
expectedAllocatedSize resource.Quantity
pvcWithFinalErrors sets.Set[string]
expansionError error
expectResizeCall bool
expectedConditions []v1.PersistentVolumeClaimConditionType
expectedResizeStatus v1.ClaimResourceStatus
expectedAllocatedSize resource.Quantity
expectNodeExpansionNotRequiredAnnotation bool
pvcWithFinalErrors sets.Set[string]
expansionError error
expectResizeCall bool
expectedConditions []v1.PersistentVolumeClaimConditionType
}{
{
name: "pvc.spec.size > pv.spec.size, resize_status=node_expansion_inprogress",
pvc: testutil.GetTestPVC("test-vol0", "2G", "1G", "", ""),
pv: createPV(1, "claim01", defaultNS, "test-uid", &fsVolumeMode),
expectedResizeStatus: v1.PersistentVolumeClaimNodeResizePending,
expectedAllocatedSize: resource.MustParse("2G"),
expectResizeCall: true,
name: "pvc.spec.size > pv.spec.size, resize_status=node_expansion_inprogress",
pvc: testutil.GetTestPVC("test-vol0", "2G", "1G", "", ""),
pv: createPV(1, "claim01", defaultNS, "test-uid", &fsVolumeMode),
expectedResizeStatus: v1.PersistentVolumeClaimNodeResizePending,
expectNodeExpansionNotRequiredAnnotation: false,
expectedAllocatedSize: resource.MustParse("2G"),
expectResizeCall: true,
},
{
name: "pvc.spec.size = pv.spec.size, resize_status=no_expansion_inprogress",
Expand Down Expand Up @@ -116,13 +121,14 @@ func TestExpandAndRecover(t *testing.T) {
expectResizeCall: false,
},
{
name: "pvc.spec.size > pv.spec.size, disable_node_expansion=true, resize_status=no_expansion_inprogress",
pvc: testutil.GetTestPVC("test-vol0", "2G", "1G", "", ""),
pv: createPV(1, "claim01", defaultNS, "test-uid", &fsVolumeMode),
disableNodeExpansion: true,
expectedResizeStatus: "",
expectedAllocatedSize: resource.MustParse("2G"),
expectResizeCall: true,
name: "pvc.spec.size > pv.spec.size, disable_node_expansion=true, resize_status=no_expansion_inprogress",
pvc: testutil.GetTestPVC("test-vol0", "2G", "1G", "", ""),
pv: createPV(1, "claim01", defaultNS, "test-uid", &fsVolumeMode),
disableNodeExpansion: true,
expectedResizeStatus: "",
expectNodeExpansionNotRequiredAnnotation: true,
expectedAllocatedSize: resource.MustParse("2G"),
expectResizeCall: true,
},
{
name: "pv.spec.size >= pvc.spec.size, resize_status=node_expansion_failed",
Expand Down Expand Up @@ -193,6 +199,10 @@ func TestExpandAndRecover(t *testing.T) {
t.Fatalf("expected resize status to be %s, got %s", test.expectedResizeStatus, actualResizeStatus)
}

if test.expectNodeExpansionNotRequiredAnnotation != metav1.HasAnnotation(pvc.ObjectMeta, util.NodeExpansionNotRequired) {
t.Fatalf("expected node expansion not required annotation to be %t, got %t", test.expectNodeExpansionNotRequiredAnnotation, metav1.HasAnnotation(pvc.ObjectMeta, util.NodeExpansionNotRequired))
}

actualAllocatedSize := pvc.Status.AllocatedResources.Storage()

if test.expectedAllocatedSize.Cmp(*actualAllocatedSize) != 0 {
Expand Down
8 changes: 8 additions & 0 deletions pkg/controller/resize_status.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ func (ctrl *resizeController) markControllerResizeInProgress(
newPVC.Status.Conditions = util.MergeResizeConditionsOfPVC(newPVC.Status.Conditions, conditions, true /*keepOldResizeConditions*/)
}

newPVC = ctrl.removeNodeExpansionNotRequiredAnnotation(newPVC)

if updateStatus {
newPVC = mergeStorageResourceStatus(newPVC, v1.PersistentVolumeClaimControllerResizeInProgress)
}
Expand Down Expand Up @@ -78,6 +80,9 @@ func (ctrl *resizeController) markForPendingNodeExpansion(pvc *v1.PersistentVolu
newPVC.Status.Conditions = util.MergeResizeConditionsOfPVC(newPVC.Status.Conditions,
[]v1.PersistentVolumeClaimCondition{pvcCondition}, true /*keepOldResizeConditions*/)

// make sure if any annotation was previously added is removed here
newPVC = ctrl.removeNodeExpansionNotRequiredAnnotation(newPVC)

newPVC = mergeStorageResourceStatus(newPVC, v1.PersistentVolumeClaimNodeResizePending)
updatedPVC, err := util.PatchClaim(ctrl.kubeClient, pvc, newPVC, true /* addResourceVersionCheck */)

Expand Down Expand Up @@ -173,6 +178,9 @@ func (ctrl *resizeController) markOverallExpansionAsFinished(
newPVC.Status.AllocatedResourceStatuses = resourceStatusMap
}

// this will ensure that kubelet does not try to resize volume again
newPVC = ctrl.addNodeExpansionNotRequiredAnnotation(newPVC)

updatedPVC, err := util.PatchClaim(ctrl.kubeClient, pvc, newPVC, true /* addResourceVersionCheck */)
if err != nil {
return pvc, fmt.Errorf("mark PVC %q as resize finished failed: %v", klog.KObj(pvc), err)
Expand Down
2 changes: 2 additions & 0 deletions pkg/util/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ var (
// Its value will be set by the external-resizer when it deems that filesystem resize is required after resizing volume.
// Its value will be used by pv_controller to determine pvc's status capacity when binding pvc and pv.
AnnPreResizeCapacity = "volume.alpha.kubernetes.io/pre-resize-capacity"

NodeExpansionNotRequired = "volume.kubernetes.io/node-expansion-not-required"
)

// MergeResizeConditionsOfPVC updates pvc with requested resize conditions
Expand Down