Skip to content

[snapshot-controller] Retry PVC finalizer removal on conflict #1133

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
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
28 changes: 16 additions & 12 deletions pkg/common-controller/snapshot_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
"k8s.io/apimachinery/pkg/labels"
"k8s.io/client-go/kubernetes/scheme"
ref "k8s.io/client-go/tools/reference"
"k8s.io/client-go/util/retry"
corev1helpers "k8s.io/component-helpers/scheduling/corev1"
klog "k8s.io/klog/v2"

Expand Down Expand Up @@ -930,19 +931,22 @@ func (ctrl *csiSnapshotCommonController) ensurePVCFinalizer(snapshot *crdv1.Volu

// removePVCFinalizer removes a Finalizer for VolumeSnapshot Source PVC.
func (ctrl *csiSnapshotCommonController) removePVCFinalizer(pvc *v1.PersistentVolumeClaim) error {
// Get snapshot source which is a PVC
// TODO(xyang): We get PVC from informer but it may be outdated
// Should get it from API server directly before removing finalizer
pvcClone := pvc.DeepCopy()
pvcClone.ObjectMeta.Finalizers = utils.RemoveString(pvcClone.ObjectMeta.Finalizers, utils.PVCFinalizer)

_, err := ctrl.client.CoreV1().PersistentVolumeClaims(pvcClone.Namespace).Update(context.TODO(), pvcClone, metav1.UpdateOptions{})
if err != nil {
return newControllerUpdateError(pvcClone.Name, err.Error())
}
return retry.RetryOnConflict(retry.DefaultRetry, func() error {
// Get snapshot source which is a PVC
newPvc, err := ctrl.client.CoreV1().PersistentVolumeClaims(pvc.Namespace).Get(context.TODO(), pvc.Name, metav1.GetOptions{})
if err != nil {
return err
}
newPvc = newPvc.DeepCopy()
newPvc.ObjectMeta.Finalizers = utils.RemoveString(newPvc.ObjectMeta.Finalizers, utils.PVCFinalizer)
_, err = ctrl.client.CoreV1().PersistentVolumeClaims(newPvc.Namespace).Update(context.TODO(), newPvc, metav1.UpdateOptions{})
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using a "patch" instead of an "update" can reduce the conflicts.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do agree that a using a "patch" would get rid of all the conflicts however since the finalizers are stored in a list, using a patch seems dangerous to me because if the finalizer list changes between the get and update calls (because another controller removed its finalizer for instance), it means that we would end up removing the wrong finalizer (since we need the index to remove an element from a list using a patch).

Is there something I'm missing that could let us use a patch instead without the drawback above?

if err != nil {
return newControllerUpdateError(newPvc.Name, err.Error())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

folks, I suspect generating a new error here (newControllerUpdateError) results in IsConflict never evaluating to true, and thus the original problem still existing. I hit this on an environment with 8.2.0 which contains this commit.

I can open a PR to tackle

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @akalenyu sorry about this! I actually did notice it a while back and made a PR in our fork to make sure this fixed the behavior for good (which it did) but I forgot to upstream it :(

}

klog.V(5).Infof("Removed protection finalizer from persistent volume claim %s", pvc.Name)
return nil
klog.V(5).Infof("Removed protection finalizer from persistent volume claim %s", pvc.Name)
return nil
})
}

// isPVCBeingUsed checks if a PVC is being used as a source to create a snapshot.
Expand Down
4 changes: 4 additions & 0 deletions vendor/k8s.io/client-go/util/retry/OWNERS

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

105 changes: 105 additions & 0 deletions vendor/k8s.io/client-go/util/retry/util.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions vendor/modules.txt
Original file line number Diff line number Diff line change
Expand Up @@ -770,6 +770,7 @@ k8s.io/client-go/util/consistencydetector
k8s.io/client-go/util/flowcontrol
k8s.io/client-go/util/homedir
k8s.io/client-go/util/keyutil
k8s.io/client-go/util/retry
k8s.io/client-go/util/watchlist
k8s.io/client-go/util/workqueue
# k8s.io/component-base v0.31.0-rc.0 => k8s.io/component-base v0.31.0-rc.0
Expand Down