# Design Doc for Auto ReclaimSpace
## Current Solution
Currently, users can annotate the PVCs or the Namespace of the PVCs for which ReclaimSpaceCronJob has to be created.
## Problem
- Annotating hundreds of PVCs is not a good solution. Having a centralized control would be a better option.
- Annotating Namespace is not a good practice as Namespace are used for logical organization of resources, not configuration.
- deleting/modifying annotation on Namespace will require admin to do same operation on PVCs within that Namespace.
## Approach
### 1. CSIDriver annotation
This approach involves annotating the CSIDriver object and PVCs provisioned by these drivers will be annotated for auto ReclaimSpace.
:+1: simple configuration, centralized control and consistent reclaim space schedules for all PVCs provisioned by same provisioner.
:-1: this does not provide fine-grained control over a group of PVCs provisioned by a particular SC.
### 2. StorageClass annotation
This approach involves annotating the StorageClass, whereby PVCs associated with this StorageClass will be annotated for ReclaimSpace, and a respective ReclaimSpace CronJob will be created.
It would still require admins to modify/delete annotations for each PVCs. This can be solved by watching the SC objects and reconciling the PVCs if annotations are modified/deleted on SC.
:::danger
In current implementation of PVC controller, SC annotations are superseded by PVC annotations. So, add/modify/delete annotations on SC will have no impact on the PVCs RS Jobs.
:::
One way of modifying the annotations on PVC would be,
1. add the `/remove` annotation on the SC, which will remove all `reclaimspace.` annotations from associated PVCs
2. remove the `/remove` annotation from the SC and add the updated `/schedule` annotation, which will then add the updated annotation to PVCs of this SC.
:+1: consistent RS for PVCs of same SC, control schedule at SC level instead at provisioner level.
:-1: admins still need to manager annotations for each SC
### 3. ReclaimSpace ConfigMap
This approach involves having a new CM for ReclaimSpace configuration.
For example,
```
apiVersion: v1
kind: ConfigMap
metadata:
name: csi-addons-reclaim-config
namespace: csi-addons-system
data:
config.json: |
{
"timeout": "10m",
"auto-reclaim-storageclass": {
"rbd-sc": "daily",
"rbd1-sc": "weekly",
...
},
"reclaim-space-enable": "true"
}
```
- `auto-reclaim-storageclass` option to provide maps of `<sc-name>:<schedule>` entries for auto reclaimspace
- `reclaim-space-enable` can help admins to enable/disable the RS incase needed instead of adding/deleting the annotating from multiple resource objects.
:+1: easy to manager and update configuration from single place.
:-1: controller need to watch for CM and handle the changes.
<hr>
# Handle existing PVCs
## Problem
## Solution
## Testing
```yaml
$ k get sc rook-ceph-block -oyaml
allowVolumeExpansion: true
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
creationTimestamp: "2024-07-08T06:48:23Z"
name: rook-ceph-block
resourceVersion: "1879671"
uid: 8e8e36e4-f0fb-460c-b352-3efd8799479e
parameters:
clusterID: rook-ceph
csi.storage.k8s.io/controller-expand-secret-name: rook-csi-rbd-provisioner
csi.storage.k8s.io/controller-expand-secret-namespace: rook-ceph
csi.storage.k8s.io/fstype: ext4
csi.storage.k8s.io/node-stage-secret-name: rook-csi-rbd-node
csi.storage.k8s.io/node-stage-secret-namespace: rook-ceph
csi.storage.k8s.io/provisioner-secret-name: rook-csi-rbd-provisioner
csi.storage.k8s.io/provisioner-secret-namespace: rook-ceph
encrypted: "true"
encryptionKMSID: azure-test
imageFeatures: layering
imageFormat: "2"
pool: replicapool
provisioner: rook-ceph.rbd.csi.ceph.com
reclaimPolicy: Delete
volumeBindingMode: Immediate
```
```yaml
$ k get pvc rbd-pvc -oyaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
annotations:
pv.kubernetes.io/bind-completed: "yes"
pv.kubernetes.io/bound-by-controller: "yes"
volume.beta.kubernetes.io/storage-provisioner: rook-ceph.rbd.csi.ceph.com
volume.kubernetes.io/storage-provisioner: rook-ceph.rbd.csi.ceph.com
creationTimestamp: "2024-07-11T07:09:18Z"
finalizers:
- kubernetes.io/pvc-protection
name: rbd-pvc
namespace: test
resourceVersion: "2311226"
uid: 7388ae15-3ee4-4051-90d5-0661181b36d6
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
storageClassName: rook-ceph-block
volumeMode: Block
volumeName: pvc-7388ae15-3ee4-4051-90d5-0661181b36d6
status:
accessModes:
- ReadWriteOnce
capacity:
storage: 1Gi
phase: Bound
```
```yaml
$ k annotate sc rook-ceph-block "reclaimspace.csiaddons.openshift.io/schedule=@daily"
storageclass.storage.k8s.io/rook-ceph-block annotated
$ k get pvc rbd-pvc -oyaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
annotations:
pv.kubernetes.io/bind-completed: "yes"
pv.kubernetes.io/bound-by-controller: "yes"
reclaimspace.csiaddons.openshift.io/cronjob: rbd-pvc-1720682724
reclaimspace.csiaddons.openshift.io/schedule: '@daily'
volume.beta.kubernetes.io/storage-provisioner: rook-ceph.rbd.csi.ceph.com
volume.kubernetes.io/storage-provisioner: rook-ceph.rbd.csi.ceph.com
creationTimestamp: "2024-07-11T07:09:18Z"
finalizers:
- kubernetes.io/pvc-protection
name: rbd-pvc
namespace: test
resourceVersion: "2312547"
uid: 7388ae15-3ee4-4051-90d5-0661181b36d6
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
storageClassName: rook-ceph-block
volumeMode: Block
volumeName: pvc-7388ae15-3ee4-4051-90d5-0661181b36d6
status:
accessModes:
- ReadWriteOnce
capacity:
storage: 1Gi
phase: Bound
```
```
2024-07-11T07:11:04.520Z INFO Annotation not set, exiting reconcile {"controller": "persistentvolumeclaim", "controllerGroup": "", "controllerKind": "PersistentVolumeClaim", "PersistentVolumeClaim": {"name":"rbd-pvc","namespace":"test"}, "namespace": "test", "name": "rbd-pvc", "reconcileID": "8521eaa0-3fc1-4541-8214-c66d34003ecf"}
2024-07-11T07:25:24.966Z INFO Adding annotation {"controller": "persistentvolumeclaim", "controllerGroup": "", "controllerKind": "PersistentVolumeClaim", "PersistentVolumeClaim": {"name":"rbd-pvc","namespace":"test"}, "namespace": "test", "name": "rbd-pvc", "reconcileID": "477395f4-160d-4d0b-b67d-033d69aa20a9", "Schedule": "@daily", "ReclaimSpaceCronJobName": "rbd-pvc-1720682724", "Annotation": "{\"metadata\":{\"annotations\":{\"reclaimspace.csiaddons.openshift.io/cronjob\":\"rbd-pvc-1720682724\",\"reclaimspace.csiaddons.openshift.io/schedule\":\"@daily\"}}}"}
2024-07-11T07:25:24.996Z INFO KubeAPIWarningLogger unknown field "spec.jobTemplate.metadata.creationTimestamp"
2024-07-11T07:25:24.997Z INFO Successfully created reclaimSpaceCronJob {"controller": "persistentvolumeclaim", "controllerGroup": "", "controllerKind": "PersistentVolumeClaim", "PersistentVolumeClaim": {"name":"rbd-pvc","namespace":"test"}, "namespace": "test", "name": "rbd-pvc", "reconcileID": "477395f4-160d-4d0b-b67d-033d69aa20a9", "Schedule": "@daily", "ReclaimSpaceCronJobName": "rbd-pvc-1720682724"}
2024-07-11T07:25:25.017Z INFO No upcoming scheduled times, requeue with delay till next run {"controller": "reclaimspacecronjob", "controllerGroup": "csiaddons.openshift.io", "controllerKind": "ReclaimSpaceCronJob", "ReclaimSpaceCronJob": {"name":"rbd-pvc-1720682724","namespace":"test"}, "namespace": "test", "name": "rbd-pvc-1720682724", "reconcileID": "7761b968-0fda-4e2b-8abd-4bde8f3c3854", "now": "2024-07-11T07:25:25.017Z", "nextRun": "2024-07-12T00:00:00.000Z"}
2024-07-11T07:25:25.019Z ERROR Failed to update reclaimSpaceCronJob {"controller": "persistentvolumeclaim", "controllerGroup": "", "controllerKind": "PersistentVolumeClaim", "PersistentVolumeClaim": {"name":"rbd-pvc","namespace":"test"}, "namespace": "test", "name": "rbd-pvc", "reconcileID": "4ca1a3ee-7162-434e-9694-7295c5e3b939", "ReclaimSpaceCronJobName": "rbd-pvc-1720682724", "Schedule": "@daily", "error": "Operation cannot be fulfilled on reclaimspacecronjobs.csiaddons.openshift.io \"rbd-pvc-1720682724\": the object has been modified; please apply your changes to the latest version and try again"}
github.com/csi-addons/kubernetes-csi-addons/controllers/csiaddons.(*PersistentVolumeClaimReconciler).Reconcile
/workspace/go/src/github.com/csi-addons/kubernetes-csi-addons/controllers/csiaddons/persistentvolumeclaim_controller.go:173
sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).Reconcile
/workspace/go/src/github.com/csi-addons/kubernetes-csi-addons/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller/controller.go:114
sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).reconcileHandler
/workspace/go/src/github.com/csi-addons/kubernetes-csi-addons/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller/controller.go:311
sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).processNextWorkItem
/workspace/go/src/github.com/csi-addons/kubernetes-csi-addons/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller/controller.go:261
sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).Start.func2.2
/workspace/go/src/github.com/csi-addons/kubernetes-csi-addons/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller/controller.go:222
2024-07-11T07:25:25.021Z ERROR Reconciler error {"controller": "persistentvolumeclaim", "controllerGroup": "", "controllerKind": "PersistentVolumeClaim", "PersistentVolumeClaim": {"name":"rbd-pvc","namespace":"test"}, "namespace": "test", "name": "rbd-pvc", "reconcileID": "4ca1a3ee-7162-434e-9694-7295c5e3b939", "error": "Operation cannot be fulfilled on reclaimspacecronjobs.csiaddons.openshift.io \"rbd-pvc-1720682724\": the object has been modified; please apply your changes to the latest version and try again"}
sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).reconcileHandler
/workspace/go/src/github.com/csi-addons/kubernetes-csi-addons/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller/controller.go:324
sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).processNextWorkItem
/workspace/go/src/github.com/csi-addons/kubernetes-csi-addons/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller/controller.go:261
sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).Start.func2.2
/workspace/go/src/github.com/csi-addons/kubernetes-csi-addons/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller/controller.go:222
2024-07-11T07:25:25.030Z INFO No upcoming scheduled times, requeue with delay till next run {"controller": "reclaimspacecronjob", "controllerGroup": "csiaddons.openshift.io", "controllerKind": "ReclaimSpaceCronJob", "ReclaimSpaceCronJob": {"name":"rbd-pvc-1720682724","namespace":"test"}, "namespace": "test", "name": "rbd-pvc-1720682724", "reconcileID": "dd49f11d-a0d5-4349-9417-f0185933a84b", "now": "2024-07-11T07:25:25.030Z", "nextRun": "2024-07-12T00:00:00.000Z"}
2024-07-11T07:25:25.037Z INFO Successfully updated reclaimSpaceCronJob {"controller": "persistentvolumeclaim", "controllerGroup": "", "controllerKind": "PersistentVolumeClaim", "PersistentVolumeClaim": {"name":"rbd-pvc","namespace":"test"}, "namespace": "test", "name": "rbd-pvc", "reconcileID": "654882a0-7e69-4aa3-84b2-d5ab3668466e", "ReclaimSpaceCronJobName": "rbd-pvc-1720682724", "Schedule": "@daily"}
```
```yaml
$ k create -f pvc.yaml
persistentvolumeclaim/rbd-pvc-new created
$ k get pvc rbd-pvc-new -oyaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
annotations:
pv.kubernetes.io/bind-completed: "yes"
pv.kubernetes.io/bound-by-controller: "yes"
reclaimspace.csiaddons.openshift.io/cronjob: rbd-pvc-new-1720683030
reclaimspace.csiaddons.openshift.io/schedule: '@daily'
volume.beta.kubernetes.io/storage-provisioner: rook-ceph.rbd.csi.ceph.com
volume.kubernetes.io/storage-provisioner: rook-ceph.rbd.csi.ceph.com
creationTimestamp: "2024-07-11T07:30:24Z"
finalizers:
- kubernetes.io/pvc-protection
name: rbd-pvc-new
namespace: test
resourceVersion: "2313046"
uid: decb16c6-44be-45d2-ba75-7b4ab029be9d
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
storageClassName: rook-ceph-block
volumeMode: Block
volumeName: pvc-decb16c6-44be-45d2-ba75-7b4ab029be9d
status:
accessModes:
- ReadWriteOnce
capacity:
storage: 1Gi
phase: Bound
```
```
2024-07-11T07:30:27.566Z INFO PVC is not in bound state {"controller": "persistentvolumeclaim", "controllerGroup": "", "controllerKind": "PersistentVolumeClaim", "PersistentVolumeClaim": {"name":"rbd-pvc-new","namespace":"test"}, "namespace": "test", "name": "rbd-pvc-new", "reconcileID": "1d67ad16-003a-434a-a297-82877fa44f8d", "PVCPhase": "Pending"}
2024-07-11T07:30:30.128Z INFO Adding annotation {"controller": "persistentvolumeclaim", "controllerGroup": "", "controllerKind": "PersistentVolumeClaim", "PersistentVolumeClaim": {"name":"rbd-pvc-new","namespace":"test"}, "namespace": "test", "name": "rbd-pvc-new", "reconcileID": "43bae20b-8561-4e55-8769-9f8708fead39", "Schedule": "@daily", "ReclaimSpaceCronJobName": "rbd-pvc-new-1720683030", "Annotation": "{\"metadata\":{\"annotations\":{\"reclaimspace.csiaddons.openshift.io/cronjob\":\"rbd-pvc-new-1720683030\",\"reclaimspace.csiaddons.openshift.io/schedule\":\"@daily\"}}}"}
2024-07-11T07:30:30.150Z INFO Successfully created reclaimSpaceCronJob {"controller": "persistentvolumeclaim", "controllerGroup": "", "controllerKind": "PersistentVolumeClaim", "PersistentVolumeClaim": {"name":"rbd-pvc-new","namespace":"test"}, "namespace": "test", "name": "rbd-pvc-new", "reconcileID": "43bae20b-8561-4e55-8769-9f8708fead39", "Schedule": "@daily", "ReclaimSpaceCronJobName": "rbd-pvc-new-1720683030"}
2024-07-11T07:30:30.159Z INFO Successfully updated reclaimSpaceCronJob {"controller": "persistentvolumeclaim", "controllerGroup": "", "controllerKind": "PersistentVolumeClaim", "PersistentVolumeClaim": {"name":"rbd-pvc-new","namespace":"test"}, "namespace": "test", "name": "rbd-pvc-new", "reconcileID": "3fd51186-854a-445e-8a8c-88667e33e479", "ReclaimSpaceCronJobName": "rbd-pvc-new-1720683030", "Schedule": "@daily"}
2024-07-11T07:30:30.165Z INFO No upcoming scheduled times, requeue with delay till next run {"controller": "reclaimspacecronjob", "controllerGroup": "csiaddons.openshift.io", "controllerKind": "ReclaimSpaceCronJob", "ReclaimSpaceCronJob": {"name":"rbd-pvc-new-1720683030","namespace":"test"}, "namespace": "test", "name": "rbd-pvc-new-1720683030", "reconcileID": "e9c95d30-2f78-4625-a3b6-bf4c3c861c76", "now": "2024-07-11T07:30:30.165Z", "nextRun": "2024-07-12T00:00:00.000Z"}
2024-07-11T07:30:30.170Z ERROR Failed to update reclaimSpaceCronJob {"controller": "persistentvolumeclaim", "controllerGroup": "", "controllerKind": "PersistentVolumeClaim", "PersistentVolumeClaim": {"name":"rbd-pvc-new","namespace":"test"}, "namespace": "test", "name": "rbd-pvc-new", "reconcileID": "0b54e3b8-1c01-49dd-b571-ee7935c8c3b6", "ReclaimSpaceCronJobName": "rbd-pvc-new-1720683030", "Schedule": "@daily", "error": "Operation cannot be fulfilled on reclaimspacecronjobs.csiaddons.openshift.io \"rbd-pvc-new-1720683030\": the object has been modified; please apply your changes to the latest version and try again"}
github.com/csi-addons/kubernetes-csi-addons/controllers/csiaddons.(*PersistentVolumeClaimReconciler).Reconcile
/workspace/go/src/github.com/csi-addons/kubernetes-csi-addons/controllers/csiaddons/persistentvolumeclaim_controller.go:173
sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).Reconcile
/workspace/go/src/github.com/csi-addons/kubernetes-csi-addons/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller/controller.go:114
sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).reconcileHandler
/workspace/go/src/github.com/csi-addons/kubernetes-csi-addons/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller/controller.go:311
sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).processNextWorkItem
/workspace/go/src/github.com/csi-addons/kubernetes-csi-addons/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller/controller.go:261
sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).Start.func2.2
/workspace/go/src/github.com/csi-addons/kubernetes-csi-addons/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller/controller.go:222
2024-07-11T07:30:30.170Z ERROR Reconciler error {"controller": "persistentvolumeclaim", "controllerGroup": "", "controllerKind": "PersistentVolumeClaim", "PersistentVolumeClaim": {"name":"rbd-pvc-new","namespace":"test"}, "namespace": "test", "name": "rbd-pvc-new", "reconcileID": "0b54e3b8-1c01-49dd-b571-ee7935c8c3b6", "error": "Operation cannot be fulfilled on reclaimspacecronjobs.csiaddons.openshift.io \"rbd-pvc-new-1720683030\": the object has been modified; please apply your changes to the latest version and try again"}
sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).reconcileHandler
/workspace/go/src/github.com/csi-addons/kubernetes-csi-addons/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller/controller.go:324
sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).processNextWorkItem
/workspace/go/src/github.com/csi-addons/kubernetes-csi-addons/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller/controller.go:261
sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).Start.func2.2
/workspace/go/src/github.com/csi-addons/kubernetes-csi-addons/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller/controller.go:222
2024-07-11T07:30:30.176Z INFO No upcoming scheduled times, requeue with delay till next run {"controller": "reclaimspacecronjob", "controllerGroup": "csiaddons.openshift.io", "controllerKind": "ReclaimSpaceCronJob", "ReclaimSpaceCronJob": {"name":"rbd-pvc-new-1720683030","namespace":"test"}, "namespace": "test", "name": "rbd-pvc-new-1720683030", "reconcileID": "d269ebe5-1b02-4aba-b9c8-27d6655f3fc3", "now": "2024-07-11T07:30:30.175Z", "nextRun": "2024-07-12T00:00:00.000Z"}
2024-07-11T07:30:30.184Z INFO Successfully updated reclaimSpaceCronJob {"controller": "persistentvolumeclaim", "controllerGroup": "", "controllerKind": "PersistentVolumeClaim", "PersistentVolumeClaim": {"name":"rbd-pvc-new","namespace":"test"}, "namespace": "test", "name": "rbd-pvc-new", "reconcileID": "480a067e-56d5-4d9f-94db-7e8d6ea94706", "ReclaimSpaceCronJobName": "rbd-pvc-new-1720683030", "Schedule": "@daily"}
```
# Handle annotation modification on StorageClass.
## Problem
deleting/modifying annotation on StorageClas will require admin to do same operation on PVCs of that StorageClass.
## Solution
Watch for the ReclaimSpace annotations change on StorageClass and Enqueue all PVCs associated with this StorageClass for Reconcile.
### challenges
- We don't know which PVCs to be considered for annotation update. (since few PVCs will already be having annotations set and those might not be from its StorageClass, they might be added by user or namespace annotation.)
:::success
We could add one more annotation something like,
- reclaimspace.csiaddons.csi.com/owner:controller or
- reclaimspace.csiaddons.csi.com/added-by-controller: true
differentiating who added the annotations?
:::
### Scenarios
1. User adds the annotations to
- PVC - reconcile and create CronJob
- StorageClass - reconcile, add annotations to PVCs (schedule, added-by-controller) and create CronJob
2. User updates the annotations on
- PVC -
- If `added-by-controller` annotation is not set, update annotations
- else, remove `added-by-controller` annotation and update `schedule` annotation with user provided
- StorageClass - Reconcile all PVCs with annotations `added-by-controller` and without schedule annotation, update annotations on PVCs
3. User removes the annotations from
- PVC -
- If `added-by-controller` annotation not set, remove and exit
- else, remove `added-by-controller` and `schedule` annotations
- StorageClass - Reconcile all PVCs with annotations `added-by-controller` and remove annotations from PVCs
---