Skip to content

Commit aa71427

Browse files
authored
Merge pull request #4887 from reasonerjt/delete-orphan-vs
Delete orphan CSI snapshots in backup sync controller
2 parents 6281646 + 89e90d9 commit aa71427

File tree

7 files changed

+44
-4
lines changed

7 files changed

+44
-4
lines changed

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ all-containers: container-builder-env
125125
@$(MAKE) --no-print-directory container BIN=velero-restic-restore-helper
126126

127127
local: build-dirs
128+
# Add DEBUG=1 to enable debug locally
128129
GOOS=$(GOOS) \
129130
GOARCH=$(GOARCH) \
130131
VERSION=$(VERSION) \

changelogs/unreleased/4887-reasonerjt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Delete orphan CSI snapshots in backup sync controller

pkg/cmd/server/server.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,7 @@ func newServer(f client.Factory, config serverConfig, logger *logrus.Logger) (*s
302302
scheme := runtime.NewScheme()
303303
velerov1api.AddToScheme(scheme)
304304
corev1api.AddToScheme(scheme)
305+
snapshotv1api.AddToScheme(scheme)
305306

306307
ctrl.SetLogger(logrusr.NewLogger(logger))
307308

@@ -599,6 +600,7 @@ func (s *server) runControllers(defaultVolumeSnapshotLocations map[string]string
599600
s.mgr.GetClient(),
600601
s.veleroClient.VeleroV1(),
601602
s.sharedInformerFactory.Velero().V1().Backups().Lister(),
603+
csiVSLister,
602604
s.config.backupSyncPeriod,
603605
s.namespace,
604606
s.csiSnapshotClient,
@@ -863,7 +865,6 @@ func (s *server) runControllers(defaultVolumeSnapshotLocations map[string]string
863865
if err := s.mgr.Start(s.ctx); err != nil {
864866
s.logger.Fatal("Problem starting manager", err)
865867
}
866-
867868
return nil
868869
}
869870

pkg/controller/backup_controller.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -679,7 +679,7 @@ func (c *backupController) runBackup(backup *pkgbackup.Request) error {
679679

680680
backup.Status.CSIVolumeSnapshotsAttempted = len(backup.CSISnapshots)
681681
for _, vs := range backup.CSISnapshots {
682-
if *vs.Status.ReadyToUse {
682+
if vs.Status != nil && boolptr.IsSetToTrue(vs.Status.ReadyToUse) {
683683
backup.Status.CSIVolumeSnapshotsCompleted++
684684
}
685685
}

pkg/controller/backup_sync_controller.go

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ import (
2020
"context"
2121
"time"
2222

23+
snapshotv1api "github.com/kubernetes-csi/external-snapshotter/client/v4/apis/volumesnapshot/v1"
2324
snapshotterClientSet "github.com/kubernetes-csi/external-snapshotter/client/v4/clientset/versioned"
25+
snapshotv1listers "github.com/kubernetes-csi/external-snapshotter/client/v4/listers/volumesnapshot/v1"
2426
"github.com/pkg/errors"
2527
"github.com/sirupsen/logrus"
2628
kuberrs "k8s.io/apimachinery/pkg/api/errors"
@@ -29,6 +31,8 @@ import (
2931
"k8s.io/apimachinery/pkg/util/sets"
3032
"k8s.io/client-go/kubernetes"
3133

34+
"github.com/vmware-tanzu/velero/pkg/util/kube"
35+
3236
"github.com/vmware-tanzu/velero/internal/storage"
3337
velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1"
3438
"github.com/vmware-tanzu/velero/pkg/features"
@@ -48,6 +52,7 @@ type backupSyncController struct {
4852
kbClient client.Client
4953
podVolumeBackupClient velerov1client.PodVolumeBackupsGetter
5054
backupLister velerov1listers.BackupLister
55+
csiVSLister snapshotv1listers.VolumeSnapshotLister
5156
csiSnapshotClient *snapshotterClientSet.Clientset
5257
kubeClient kubernetes.Interface
5358
namespace string
@@ -62,6 +67,7 @@ func NewBackupSyncController(
6267
kbClient client.Client,
6368
podVolumeBackupClient velerov1client.PodVolumeBackupsGetter,
6469
backupLister velerov1listers.BackupLister,
70+
csiVSLister snapshotv1listers.VolumeSnapshotLister,
6571
syncPeriod time.Duration,
6672
namespace string,
6773
csiSnapshotClient *snapshotterClientSet.Clientset,
@@ -85,6 +91,7 @@ func NewBackupSyncController(
8591
defaultBackupLocation: defaultBackupLocation,
8692
defaultBackupSyncPeriod: syncPeriod,
8793
backupLister: backupLister,
94+
csiVSLister: csiVSLister,
8895
csiSnapshotClient: csiSnapshotClient,
8996
kubeClient: kubeClient,
9097

@@ -358,11 +365,34 @@ func (c *backupSyncController) deleteOrphanedBackups(locationName string, backup
358365
if backup.Status.Phase != velerov1api.BackupPhaseCompleted || backupStoreBackups.Has(backup.Name) {
359366
continue
360367
}
361-
362368
if err := c.backupClient.Backups(backup.Namespace).Delete(context.TODO(), backup.Name, metav1.DeleteOptions{}); err != nil {
363369
log.WithError(errors.WithStack(err)).Error("Error deleting orphaned backup from cluster")
364370
} else {
365371
log.Debug("Deleted orphaned backup from cluster")
372+
c.deleteCSISnapshotsByBackup(backup.Name, log)
373+
}
374+
}
375+
}
376+
377+
func (c *backupSyncController) deleteCSISnapshotsByBackup(backupName string, log logrus.FieldLogger) {
378+
if !features.IsEnabled(velerov1api.CSIFeatureFlag) {
379+
return
380+
}
381+
m := client.MatchingLabels{velerov1api.BackupNameLabel: label.GetValidName(backupName)}
382+
if vsList, err := c.csiVSLister.List(label.NewSelectorForBackup(label.GetValidName(backupName))); err != nil {
383+
log.WithError(err).Warnf("Failed to list volumesnapshots for backup: %s, the deletion will be skipped", backupName)
384+
} else {
385+
for _, vs := range vsList {
386+
name := kube.NamespaceAndName(vs.GetObjectMeta())
387+
log.Debugf("Deleting volumesnapshot %s", name)
388+
if err := c.kbClient.Delete(context.TODO(), vs); err != nil {
389+
log.WithError(err).Warnf("Failed to delete volumesnapshot %s", name)
390+
}
366391
}
367392
}
393+
vsc := &snapshotv1api.VolumeSnapshotContent{}
394+
log.Debugf("Deleting volumesnapshotcontents for backup: %s", backupName)
395+
if err := c.kbClient.DeleteAllOf(context.TODO(), vsc, m); err != nil {
396+
log.WithError(err).Warnf("Failed to delete volumesnapshotcontents for backup: %s", backupName)
397+
}
368398
}

pkg/controller/backup_sync_controller_test.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,7 @@ func TestBackupSyncControllerRun(t *testing.T) {
344344
fakeClient,
345345
client.VeleroV1(),
346346
sharedInformers.Velero().V1().Backups().Lister(),
347+
nil, // csiVSLister
347348
time.Duration(0),
348349
test.namespace,
349350
nil, // csiSnapshotClient
@@ -565,6 +566,7 @@ func TestDeleteOrphanedBackups(t *testing.T) {
565566
fakeClient,
566567
client.VeleroV1(),
567568
sharedInformers.Velero().V1().Backups().Lister(),
569+
nil, // csiVSLister
568570
time.Duration(0),
569571
test.namespace,
570572
nil, // csiSnapshotClient
@@ -659,6 +661,7 @@ func TestStorageLabelsInDeleteOrphanedBackups(t *testing.T) {
659661
fakeClient,
660662
client.VeleroV1(),
661663
sharedInformers.Velero().V1().Backups().Lister(),
664+
nil, // csiVSLister
662665
time.Duration(0),
663666
test.namespace,
664667
nil, // csiSnapshotClient

pkg/util/csi/reset.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ func ResetVolumeSnapshotContent(snapCont *snapshotv1api.VolumeSnapshotContent) e
3737
return fmt.Errorf("the volumesnapshotcontent '%s' does not have snapshothandle set", snapCont.Name)
3838
}
3939

40-
snapCont.Spec.VolumeSnapshotRef = corev1.ObjectReference{}
40+
// set the VolumeSnapshotRef to non-existing one to bypass the validation webhook
41+
snapCont.Spec.VolumeSnapshotRef = corev1.ObjectReference{
42+
Namespace: fmt.Sprintf("ns-%s", snapCont.UID),
43+
Name: fmt.Sprintf("name-%s", snapCont.UID),
44+
}
4145
return nil
4246
}

0 commit comments

Comments
 (0)