Skip to content

Commit

Permalink
fix: add annotation to pv after resize if filesystem resize is
Browse files Browse the repository at this point in the history
necessary. delete when pvc.status.capacity >= pv.spec.capacity
  • Loading branch information
sunpa93 committed Feb 23, 2021
1 parent 132dd95 commit 024a4c3
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 17 deletions.
64 changes: 51 additions & 13 deletions pkg/controller/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,8 +172,11 @@ func (ctrl *resizeController) updatePVC(oldObj, newObj interface{}) {
return
}

newSize := newPVC.Spec.Resources.Requests[v1.ResourceStorage]
oldSize := oldPVC.Spec.Resources.Requests[v1.ResourceStorage]
newReq := newPVC.Spec.Resources.Requests[v1.ResourceStorage]
oldReq := oldPVC.Spec.Resources.Requests[v1.ResourceStorage]

newCap := newPVC.Status.Capacity[v1.ResourceStorage]
oldCap := oldPVC.Status.Capacity[v1.ResourceStorage]

newResizerName := newPVC.Annotations[util.VolumeResizerKey]
oldResizerName := oldPVC.Annotations[util.VolumeResizerKey]
Expand All @@ -192,23 +195,27 @@ func (ctrl *resizeController) updatePVC(oldObj, newObj interface{}) {
// know how to support resizing of a "un-annotated" in-tree PVC. When in-tree resizer does add the annotation, a second
// update even will be received and we add the pvc to workqueue. If annotation matches the registered driver name in
// csi_resizer object, we proceeds with expansion internally or we discard the PVC.
// 2. An already expanded in-tree PVC:
// 3. An already expanded in-tree PVC:
// An in-tree PVC is resized with in-tree resizer. And later, CSI migration is turned on and resizer name is updated from
// in-tree resizer name to CSI driver name.
if newSize.Cmp(oldSize) > 0 || newResizerName != oldResizerName {
if newReq.Cmp(oldReq) > 0 || newResizerName != oldResizerName {
ctrl.addPVC(newObj)
} else {
// PVC's size not changed, so this Update event maybe caused by:
//
// 1. Administrators or users introduce other changes(such as add labels, modify annotations, etc.)
// unrelated to volume resize.
// 2. Informer resynced the PVC and send this Update event without any changes.
// 3. PV's filesystem has recently been resized and requires removal of its resize annotation
//
// If it is case 1, we can just discard this event. If case 2, we need to put it into the queue to
// If it is case 1, we can just discard this event. If case 2 or 3, we need to put it into the queue to
// perform a resync operation.
if newPVC.ResourceVersion == oldPVC.ResourceVersion {
// This is case 2.
ctrl.addPVC(newObj)
} else if newCap.Cmp(oldCap) > 0 {
// This is case 3
ctrl.addPVC(newObj)
}
}
}
Expand Down Expand Up @@ -300,16 +307,10 @@ func (ctrl *resizeController) syncPVC(key string) error {
return fmt.Errorf("expected PVC got: %v", pvcObject)
}

if !ctrl.pvcNeedResize(pvc) {
klog.V(4).Infof("No need to resize PVC %q", util.PVCKey(pvc))
return nil
}

volumeObj, exists, err := ctrl.volumes.GetByKey(pvc.Spec.VolumeName)
if err != nil {
return fmt.Errorf("Get PV %q of pvc %q failed: %v", pvc.Spec.VolumeName, util.PVCKey(pvc), err)
}

if !exists {
klog.Warningf("PV %q bound to PVC %s not found", pvc.Spec.VolumeName, util.PVCKey(pvc))
return nil
Expand All @@ -320,6 +321,16 @@ func (ctrl *resizeController) syncPVC(key string) error {
return fmt.Errorf("expected volume but got %+v", volumeObj)
}

if ctrl.isFsResizeComplete(pvc, pv) && metav1.HasAnnotation(pv.ObjectMeta, util.AnnPreResizeCapacity) {
if err := ctrl.deletePreResizeCapAnnotation(pv); err != nil {
return fmt.Errorf("Failed removing annotation %s from pv %q: %v", util.AnnPreResizeCapacity, pv.Name, err)
}
}

if !ctrl.pvcNeedResize(pvc) {
klog.V(4).Infof("No need to resize PVC %q", util.PVCKey(pvc))
return nil
}
if !ctrl.pvNeedResize(pvc, pv) {
klog.V(4).Infof("No need to resize PV %q", pv.Name)
return nil
Expand Down Expand Up @@ -376,6 +387,13 @@ func (ctrl *resizeController) pvNeedResize(pvc *v1.PersistentVolumeClaim, pv *v1
return true
}

// isFsResizeComplete returns true if pvc.Status.Capacity >= pv.Spec.Capacity
func (ctrl *resizeController) isFsResizeComplete(pvc *v1.PersistentVolumeClaim, pv *v1.PersistentVolume) bool {
klog.V(4).Infof("pv %q capacity = %v, pvc %s capacity = %v", pv.Name, pv.Spec.Capacity[v1.ResourceStorage], util.PVCKey(pvc), pvc.Status.Capacity[v1.ResourceStorage])
pvcCap, pvCap := pvc.Status.Capacity[v1.ResourceStorage], pv.Spec.Capacity[v1.ResourceStorage]
return pvcCap.Cmp(pvCap) >= 0
}

// resizePVC will:
// 1. Mark pvc as resizing.
// 2. Resize the volume and the pv object.
Expand Down Expand Up @@ -446,7 +464,7 @@ func (ctrl *resizeController) resizeVolume(
}
klog.V(4).Infof("Resize volume succeeded for volume %q, start to update PV's capacity", pv.Name)

err = ctrl.updatePVCapacity(pv, newSize)
err = ctrl.updatePVCapacity(pv, pvc.Status.Capacity[v1.ResourceStorage], newSize, fsResizeRequired)
if err != nil {
return newSize, fsResizeRequired, err
}
Expand Down Expand Up @@ -533,11 +551,31 @@ func (ctrl *resizeController) patchClaim(oldPVC, newPVC *v1.PersistentVolumeClai
return updatedClaim, nil
}

func (ctrl *resizeController) updatePVCapacity(pv *v1.PersistentVolume, newCapacity resource.Quantity) error {
func (ctrl *resizeController) deletePreResizeCapAnnotation(pv *v1.PersistentVolume) error {
// if the pv does not have a resize annotation skip the entire process
if !metav1.HasAnnotation(pv.ObjectMeta, util.AnnPreResizeCapacity) {
return nil
}
pvClone := pv.DeepCopy()
delete(pvClone.ObjectMeta.Annotations, util.AnnPreResizeCapacity)

_, err := ctrl.patchPersistentVolume(pv, pvClone)
return err
}

func (ctrl *resizeController) updatePVCapacity(pv *v1.PersistentVolume, oldCapacity, newCapacity resource.Quantity, fsResizeRequired bool) error {
klog.V(4).Infof("Resize volume succeeded for volume %q, start to update PV's capacity", pv.Name)
newPV := pv.DeepCopy()
newPV.Spec.Capacity[v1.ResourceStorage] = newCapacity

if fsResizeRequired {
// if the pv already has a resize annotation skip
if metav1.HasAnnotation(pv.ObjectMeta, util.AnnPreResizeCapacity) {
return nil
}
newPV.ObjectMeta.Annotations[util.AnnPreResizeCapacity] = (&oldCapacity).String()
}

_, err := ctrl.patchPersistentVolume(pv, newPV)
if err != nil {
return fmt.Errorf("updating capacity of PV %q to %s failed: %v", pv.Name, newCapacity.String(), err)
Expand Down
11 changes: 7 additions & 4 deletions pkg/util/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,13 @@ import (
"k8s.io/apimachinery/pkg/util/strategicpatch"
)

var knownResizeConditions = map[v1.PersistentVolumeClaimConditionType]bool{
v1.PersistentVolumeClaimResizing: true,
v1.PersistentVolumeClaimFileSystemResizePending: true,
}
var (
knownResizeConditions = map[v1.PersistentVolumeClaimConditionType]bool{
v1.PersistentVolumeClaimResizing: true,
v1.PersistentVolumeClaimFileSystemResizePending: true,
}
AnnPreResizeCapacity = "volume.kubernetes.io/pre-resize-capacity"
)

// PVCKey returns an unique key of a PVC object,
func PVCKey(pvc *v1.PersistentVolumeClaim) string {
Expand Down

0 comments on commit 024a4c3

Please sign in to comment.