backube / volsync

Asynchronous data replication for Kubernetes volumes
https://volsync.readthedocs.io
GNU Affero General Public License v3.0
566 stars 65 forks source link

Using Volume Populator without the need for an additional PVC as source #1129

Open ansarhun opened 7 months ago

ansarhun commented 7 months ago

Describe the feature you'd like to have.

When provisioning a PVC the dataSourceRef refers to a ReplicationDestination and if I try to configure the ReplicationDestination with destinationPVC pointing to the newly created PVC with the dataSourceRef it will hang as both resource will depend on the other. Add an option where the dataSourceRef can provision the PVC without the need of an another PVC as a source (e.g. the one created by the ReplicationDestination).

What is the value to the end user? (why is it a priority?)

When creating a PVC with a Volume Populator there would be no need to have an additional PVC in place as a source of the new one. This can be troublesome for GitOps where the ReplicationDestination and PVC is committed to a git repository with the dataSourceRef and because of this the PVC for the ReplicationDestination will remain in the cluster even though it's not needed after the PVC provisioning.

How will we know we have a good solution? (acceptance criteria)

A PVC can be created and provisioned with a dataSourceRef without the need of additional PVC.

Additional context

I'm not sure if my original idea to let the ReplicationDestination point to the PVC with the dataSourceRef could work. Something like this:

---
apiVersion: volsync.backube/v1alpha1
kind: ReplicationDestination
metadata:
  name: datavol-dest
spec:
  trigger:
    manual: restore-once
  restic:
    repository: restic-config
    destinationPVC: pvc
    copyMethod: Snapshot #Direct
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 256Mi
  dataSourceRef:
    kind: ReplicationDestination
    apiGroup: volsync.backube
    name: "datavol-dest"
tesshuflower commented 7 months ago

Unfortunately, I'm not sure this is possible, assuming I understand your use-case correctly.

Essentially if you're using the VolumePopulator you cannot use this same PVC as the destinationPVC in your replicationdestination as the replicationdestination still needs a PVC to copy to. Steps are essentially this:

At this point you can delete your replicationdestination (which will also clean up the destinationPVC if it originally created it) as your vp-pvc is already provisioned

If you are looking to simply do a 1 time replication (such as a restore from restic) then you could look into using copyMode: Direct and not use the volume populator at all. This way the replication using the repicationdestination writes directly to your destinationPVC - and then you can simply use this destination PVC.

ansarhun commented 7 months ago

Thank you for the quick reply! Yes that summary is correct, I want to use this for a complete cluster reinstall. I wanted to go with the volume populator option because:

About removing the ReplicationDestination it seems that the dataSourceRef is an immutable field for PVC and I'm not sure if it could cause any issue if it refers to a non existing resource after it was provisioned https://github.com/kubernetes/kubernetes/issues/119451

If it not possible to provision the PVC directly from the backup (e.g. the restic destination), I will look into using the one of restore.

ansarhun commented 7 months ago

Would it be possible in this case if the destinationPVC of the ReplicationDestination is the same as the PVC with the volume populator to create a temporary PVC, restore the volume there, rebind the PV and drop the temporary PVC?

tesshuflower commented 7 months ago

About removing the ReplicationDestination it seems that the dataSourceRef is an immutable field for PVC and I'm not sure if it could cause any issue if it refers to a non existing resource after it was provisioned kubernetes/kubernetes#119451

You can remove the replication destination after your volume populator PVC has been populated. Once the PVC goes into bound state, volsync will not try to populate it again, essentially you can think of it as a one time operation.

Would it be possible in this case if the destinationPVC of the ReplicationDestination is the same as the PVC with the volume populator to create a temporary PVC, restore the volume there, rebind the PV and drop the temporary PVC?

I think this is getting overly complex - we might consider having some option to drop the temporary pvc after each replicationdestination sync cycle however? This does mean for repeated syncs to a destination with this option, a full copy of the data would need to be pulled down each time.

michaelbeaumont commented 1 month ago

If you are looking to simply do a 1 time replication (such as a restore from restic) then you could look into using copyMode: Direct and not use the volume populator at all. This way the replication using the repicationdestination writes directly to your destinationPVC - and then you can simply use this destination PVC.

The problem with this is that the destination PVC isn't immediately bound and has no dataSourceRef, so (I think) an application could start and bind to the PVC before the ReplicationDestination has a chance to start the restore Job and bind to the PVC. I think we basically just need a way to "flip the pointer" of destinationPVC so that the PVC points to a ReplicationDestination that "knows" to treat the PVC pointing to it as if its own destinationPVC field pointed to that PVC.

And maybe, and I don't know if this isn't feasible for CSI reasons, we could allow copyMethod: Direct as well. Or is there some hard requirement on the volume populator that it must create an additional PVC and snapshot?

tesshuflower commented 1 month ago

Allowing the volumepopulator to work with copyMethod: Direct is an interesting idea, but I think not something we want to pursue at this point.

Essentially if we rebind the direct destination PVC to a users' volume populator PVC, then we're breaking that original PVC. Using a snapshot gets around that problem, and also enables it to be a repeatable process (you can create another volume populator pvc pointing to the same replicationdestination and it should use the latest snapshot in your replicationdestination).