Skip to content
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

Feat/ PreSync mode #270

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

clementnuss
Copy link
Contributor

Adds a new feature to pvmigrate, which makes it possible to prepare a migration for RWX volumes by copying the data in advance, without actually moving to the new PV.

Then, when the proper migration actually happens, one only needs to run the command again, without the -pre-sync-mode flag, which will compare source and dest, update the files that were modified, and finally complete the migration.

cmd/main.go Outdated Show resolved Hide resolved
@laverya
Copy link
Member

laverya commented Oct 14, 2024

This is a pretty interesting proposal to me, but I'm not sure it needs to be a "run twice" type of thing - it could easily be something we do for every migration (with pod placement restrictions to ensure that RWX volumes aren't required)

If this is something we want to keep as a "run twice" solution, it would absolutely need a expanded unit test and ideally an integration test too covering that workflow.

@clementnuss clementnuss force-pushed the feat/pre-sync-mode branch 7 times, most recently from 696a8ce to b691ac2 Compare October 18, 2024 12:37
permits to reduce the downtime for the actual migration: we create the
destination PVCs and already rsync the data, without having to scale
down the pods/deployments/statefulsets.
once the copy/rsync stage is complete, we pursue by scaling down pods,
doing another copy/rsync (to ensure data consistency), finally swapping
the PVCs and scaling up

fix: proper matching PVCs count
feat:  add max-pvs=n flags
feat(pre-sync-mode): run a "prefetch" copy before actually migrating

Signed-off-by: Clément Nussbaumer <[email protected]>
@clementnuss
Copy link
Contributor Author

can you take another look ?

I modified the code: the behaviour isn't depending on RWX vs RWO now, it always works the same, and does the migration in one go, which is much simpler 🙃

the change makes it so that if the --pre-sync-mode flag is set, we add an additional copyAllPVCs stage before the scaleDown function. I've tested it with a RWO and it worked well 👍🏼

laverya
laverya previously approved these changes Oct 21, 2024
flag.BoolVar(&options.SkipSourceValidation, "skip-source-validation", false, "migrate from PVCs using a particular StorageClass name, even if that StorageClass does not exist")
flag.IntVar(&options.MaxPVs, "max-pvs", 0, "maximum number of PVs to process. default to 0 (unlimited)")
Copy link
Member

Choose a reason for hiding this comment

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

I would like an explanation in this as to what happens if the max is exceeded - do you process that number of PVs and then come back for the rest? Do you process that many PVs and then leave the rest? Do you just exit early?

It looks like it's the second option right now but that needs to be communicated

Comment on lines -678 to -680
func scaleDownPods(ctx context.Context, w *log.Logger, clientset k8sclient.Interface, matchingPVCs map[string][]*corev1.PersistentVolumeClaim, checkInterval time.Duration) (map[string][]*corev1.PersistentVolumeClaim, error) {
// build new map with complete pvcCtx
updatedPVCs := matchingPVCs
Copy link
Member

Choose a reason for hiding this comment

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

well, thank you for removing this unneeded variable!

@@ -2796,7 +2797,6 @@ func Test_scaleDownPods(t *testing.T) {
req.Equal(tt.wantPods, actualPods)
req.Equal(tt.wantDeployments, actualDeployments)
req.Equal(tt.wantSS, actualSS)
req.Equal(tt.wantMatchingPVCs, actualMatchingPVCs)
Copy link
Member

Choose a reason for hiding this comment

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

it might be good to remove the test entries for wantMatchingPVCs too since they're not used elsewhere

@laverya
Copy link
Member

laverya commented Oct 21, 2024

I added an integration test, and that adds a few worries for me (logs here):

Running pvmigrate build:
version=(devel)
sha=5e8688de96c58ac46c41e1fc256a83cc6320bd37
time=2024-10-21T00:22:00Z

Found 3 StorageClasses:
int-dest
int-source
standard

Migrating data from int-source to int-dest

Running in pre-sync-mode: we first copy the PVC live, without scaling down pods. Once that pre-sync is completed, we scale down, do another copy/sync and finally swap the PVCs.

Found 4 matching PVCs to migrate across 1 namespaces:
namespace: pvc:                                                                                         pv:                                      size: 
default    www-web-1                                                                                    pvc-3c7f06d5-d090-4fe2-942c-5489cb565385 1Gi   
default    www-web-0                                                                                    pvc-66f87da1-9bf4-4a9b-9de0-5c634cd3e6b9 1Gi   
default    prometheus-kube-prometheus-stack-prometheus-db-prometheus-kube-prometheus-stack-prometheus-0 pvc-e39569d7-f90e-4471-bdff-6d673cca5d6d 1Gi   
default    deployment-pvc                                                                               pvc-ef331a48-da64-4c31-afa2-60d23b02bfd1 1Gi   

Creating new PVCs to migrate data to using the int-dest StorageClass
created new PVC www-web-1-pvcmigrate with size 1Gi in default
created new PVC www-web-0-pvcmigrate with size 1Gi in default
created new PVC prometheus-kube-prometheus-stack-prometheus-db-prometheus-kube-prometheus-stack-prometheus-0-pvcmigrate with size 1Gi in default
created new PVC deployment-pvc-pvcmigrate with size 1Gi in default

Copying data from int-source PVCs to int-dest PVCs
Copying data from www-web-1 (pvc-3c7f06d5-d090-4fe2-942c-5489cb565385) to www-web-1-pvcmigrate in default
Determining the node to migrate PVC www-web-1 on
Creating pvc migrator pod on node 
waiting for pod migrate-www-web-1 to start in default
migrating PVC www-web-1:
..done!
finished migrating PVC www-web-1
Copying data from www-web-0 (pvc-66f87da1-9bf4-4a9b-9de0-5c634cd3e6b9) to www-web-0-pvcmigrate in default
Determining the node to migrate PVC www-web-0 on
Creating pvc migrator pod on node 
waiting for pod migrate-www-web-0 to start in default
migrating PVC www-web-0:
..done!
finished migrating PVC www-web-0
Copying data from prometheus-kube-prometheus-stack-prometheus-db-prometheus-kube-prometheus-stack-prometheus-0 (pvc-e39569d7-f90e-4471-bdff-6d673cca5d6d) to prometheus-kube-prometheus-stack-prometheus-db-prometheus-kube-prometheus-stack-prometheus-0-pvcmigrate in default
Determining the node to migrate PVC prometheus-kube-prometheus-stack-prometheus-db-prometheus-kube-prometheus-stack-prometheus-0 on
Creating pvc migrator pod on node 
waiting for pod migrate-prometheus-kube-promethbe-prometheus-stack-prometheus-0 to start in default
migrating PVC prometheus-kube-prometheus-stack-prometheus-db-prometheus-kube-prometheus-stack-prometheus-0:
..done!
finished migrating PVC prometheus-kube-prometheus-stack-prometheus-db-prometheus-kube-prometheus-stack-prometheus-0
Copying data from deployment-pvc (pvc-ef331a48-da64-4c31-afa2-60d23b02bfd1) to deployment-pvc-pvcmigrate in default
Determining the node to migrate PVC deployment-pvc on
Creating pvc migrator pod on node 
waiting for pod migrate-deployment-pvc to start in default
migrating PVC deployment-pvc:
...done!
finished migrating PVC deployment-pvc

Found 4 matching pods to migrate across 1 namespaces:
namespace: pod:                                           
default    short-pvc-name-8479ff7c7c-pqctc                
default    very-long-prometheus-pvc-name-6d64945cd8-hpjvg 
default    web-0                                          
default    web-1                                          

Scaling down StatefulSets and Deployments with matching PVCs
scaling Deployment short-pvc-name-8479ff7c7c from 1 to 0 in default
scaling Deployment very-long-prometheus-pvc-name-6d64945cd8 from 1 to 0 in default
scaling StatefulSet web from 2 to 0 in default

Waiting for pods with mounted PVCs to be cleaned up
Found pod short-pvc-name-8479ff7c7c-pqctc in default mounting to-be-migrated PVC deployment-pvc, waiting
All pods removed successfully

Copying data from int-source PVCs to int-dest PVCs
Copying data from www-web-1 (pvc-3c7f06d5-d090-4fe2-942c-5489cb565385) to www-web-1-pvcmigrate in default
Determining the node to migrate PVC www-web-1 on
Creating pvc migrator pod on node chart-testing-control-plane
waiting for pod migrate-www-web-1 to start in default
migrating PVC www-web-1:
.done!
finished migrating PVC www-web-1
Copying data from www-web-0 (pvc-66f87da1-9bf4-4a9b-9de0-5c634cd3e6b9) to www-web-0-pvcmigrate in default
Determining the node to migrate PVC www-web-0 on
Creating pvc migrator pod on node chart-testing-control-plane
waiting for pod migrate-www-web-0 to start in default
migrating PVC www-web-0:
..done!
finished migrating PVC www-web-0
Copying data from prometheus-kube-prometheus-stack-prometheus-db-prometheus-kube-prometheus-stack-prometheus-0 (pvc-e39569d7-f90e-4471-bdff-6d673cca5d6d) to prometheus-kube-prometheus-stack-prometheus-db-prometheus-kube-prometheus-stack-prometheus-0-pvcmigrate in default
Determining the node to migrate PVC prometheus-kube-prometheus-stack-prometheus-db-prometheus-kube-prometheus-stack-prometheus-0 on
Creating pvc migrator pod on node chart-testing-control-plane
waiting for pod migrate-prometheus-kube-promethbe-prometheus-stack-prometheus-0 to start in default
migrating PVC prometheus-kube-prometheus-stack-prometheus-db-prometheus-kube-prometheus-stack-prometheus-0:
...done!
finished migrating PVC prometheus-kube-prometheus-stack-prometheus-db-prometheus-kube-prometheus-stack-prometheus-0
Copying data from deployment-pvc (pvc-ef331a48-da64-4c31-afa2-60d23b02bfd1) to deployment-pvc-pvcmigrate in default
Determining the node to migrate PVC deployment-pvc on
Creating pvc migrator pod on node chart-testing-control-plane
waiting for pod migrate-deployment-pvc to start in default
migrating PVC deployment-pvc:
.done!
finished migrating PVC deployment-pvc

Swapping PVC www-web-1 in default to the new StorageClass
Marking original PV pvc-3c7f06d5-d090-4fe2-942c-5489cb565385 as to-be-retained
Marking migrated-to PV pvc-bcba3559-c367-41a2-8c5f-819ad0899215 as to-be-retained
Deleting original PVC www-web-1 in default to free up the name
Deleting migrated-to PVC www-web-1-pvcmigrate in default to release the PV
Waiting for original PVC www-web-1 in default to finish deleting
Waiting for migrated-to PVC www-web-1-pvcmigrate in default to finish deleting
Removing claimref from original PV pvc-3c7f06d5-d090-4fe2-942c-5489cb565385
Removing claimref from migrated-to PV pvc-bcba3559-c367-41a2-8c5f-819ad0899215
Creating new PVC www-web-1 with migrated-to PV pvc-bcba3559-c367-41a2-8c5f-819ad0899215
Resetting migrated-to PV pvc-bcba3559-c367-41a2-8c5f-819ad0899215 reclaim policy
Failed to determine new PV pvc-bcba3559-c367-41a2-8c5f-819ad0899215, waiting 5s to retry
Deleting original, now redundant, PV pvc-3c7f06d5-d090-4fe2-942c-5489cb565385
Successfully migrated PVC www-web-1 in default from PV pvc-3c7f06d5-d090-4fe2-942c-5489cb565385 to pvc-bcba3559-c367-41a2-8c5f-819ad0899215

Swapping PVC www-web-0 in default to the new StorageClass
Marking original PV pvc-66f87da1-9bf4-4a9b-9de0-5c634cd3e6b9 as to-be-retained
Marking migrated-to PV pvc-7cf79e76-c6d2-4126-aca6-60a075dc148b as to-be-retained
Deleting original PVC www-web-0 in default to free up the name
Deleting migrated-to PVC www-web-0-pvcmigrate in default to release the PV
Waiting for original PVC www-web-0 in default to finish deleting
Waiting for migrated-to PVC www-web-0-pvcmigrate in default to finish deleting
Removing claimref from original PV pvc-66f87da1-9bf4-4a9b-9de0-5c634cd3e6b9
Removing claimref from migrated-to PV pvc-7cf79e76-c6d2-4126-aca6-60a075dc148b
Creating new PVC www-web-0 with migrated-to PV pvc-7cf79e76-c6d2-4126-aca6-60a075dc148b
Resetting migrated-to PV pvc-7cf79e76-c6d2-4126-aca6-60a075dc148b reclaim policy
Failed to determine new PV pvc-7cf79e76-c6d2-4126-aca6-60a075dc148b, waiting 5s to retry
Deleting original, now redundant, PV pvc-66f87da1-9bf4-4a9b-9de0-5c634cd3e6b9
Successfully migrated PVC www-web-0 in default from PV pvc-66f87da1-9bf4-4a9b-9de0-5c634cd3e6b9 to pvc-7cf79e76-c6d2-4126-aca6-60a075dc148b

Swapping PVC prometheus-kube-prometheus-stack-prometheus-db-prometheus-kube-prometheus-stack-prometheus-0 in default to the new StorageClass
Marking original PV pvc-e39569d7-f90e-4471-bdff-6d673cca5d6d as to-be-retained
Marking migrated-to PV pvc-ebfef82f-b102-4494-ae1a-42f45d5e501e as to-be-retained
Deleting original PVC prometheus-kube-prometheus-stack-prometheus-db-prometheus-kube-prometheus-stack-prometheus-0 in default to free up the name
Deleting migrated-to PVC prometheus-kube-prometheus-stack-prometheus-db-prometheus-kube-prometheus-stack-prometheus-0-pvcmigrate in default to release the PV
Waiting for original PVC prometheus-kube-prometheus-stack-prometheus-db-prometheus-kube-prometheus-stack-prometheus-0 in default to finish deleting
Waiting for migrated-to PVC prometheus-kube-prometheus-stack-prometheus-db-prometheus-kube-prometheus-stack-prometheus-0-pvcmigrate in default to finish deleting
Removing claimref from original PV pvc-e39569d7-f90e-4471-bdff-6d673cca5d6d
Removing claimref from migrated-to PV pvc-ebfef82f-b102-4494-ae1a-42f45d5e501e
Creating new PVC prometheus-kube-prometheus-stack-prometheus-db-prometheus-kube-prometheus-stack-prometheus-0 with migrated-to PV pvc-ebfef82f-b102-4494-ae1a-42f45d5e501e
Resetting migrated-to PV pvc-ebfef82f-b102-4494-ae1a-42f45d5e501e reclaim policy
Failed to determine new PV pvc-ebfef82f-b102-4494-ae1a-42f45d5e501e, waiting 5s to retry
Deleting original, now redundant, PV pvc-e39569d7-f90e-4471-bdff-6d673cca5d6d
Successfully migrated PVC prometheus-kube-prometheus-stack-prometheus-db-prometheus-kube-prometheus-stack-prometheus-0 in default from PV pvc-e39569d7-f90e-4471-bdff-6d673cca5d6d to pvc-ebfef82f-b102-4494-ae1a-42f45d5e501e

Swapping PVC deployment-pvc in default to the new StorageClass
Marking original PV pvc-ef331a48-da64-4c31-afa2-60d23b02bfd1 as to-be-retained
Marking migrated-to PV pvc-dd14067b-922c-459b-a74f-9c41e20969d3 as to-be-retained
Deleting original PVC deployment-pvc in default to free up the name
Deleting migrated-to PVC deployment-pvc-pvcmigrate in default to release the PV
Waiting for original PVC deployment-pvc in default to finish deleting
Waiting for migrated-to PVC deployment-pvc-pvcmigrate in default to finish deleting
Removing claimref from original PV pvc-ef331a48-da64-4c31-afa2-60d23b02bfd1
Removing claimref from migrated-to PV pvc-dd14067b-922c-459b-a74f-9c41e20969d3
Creating new PVC deployment-pvc with migrated-to PV pvc-dd14067b-922c-459b-a74f-9c41e20969d3
Resetting migrated-to PV pvc-dd14067b-922c-459b-a74f-9c41e20969d3 reclaim policy
Failed to determine new PV pvc-dd14067b-922c-459b-a74f-9c41e20969d3, waiting 5s to retry
Deleting original, now redundant, PV pvc-ef331a48-da64-4c31-afa2-60d23b02bfd1
Successfully migrated PVC deployment-pvc in default from PV pvc-ef331a48-da64-4c31-afa2-60d23b02bfd1 to pvc-dd14067b-922c-459b-a74f-9c41e20969d3

Scaling back StatefulSets and Deployments with matching PVCs
scaling StatefulSet web from 0 to 2 in default
scaling Deployment short-pvc-name from 0 to 1 in default
scaling Deployment very-long-prometheus-pvc-name from 0 to 1 in default

Success!

The first concern is the logging. This says Copying data from int-source PVCs to int-dest PVCs twice, for instance - and that's not ideal, it should be explicit that this is the presync phase. We also have logs like finished migrating PVC www-web-0 in the presync phase that should be clearer.

The second concern comes from the data within the logging, particularly the lines Creating pvc migrator pod on node in the pre-sync phase. The fact that this doesn't include the node name means that no node was determined, and so the migration doesn't run on a specified node, which happens to work in the integration test environment (it's a single node) but will fail in real environments. I believe this is because we determine the node to run this on from annotations added to the PVC in question, and those annotations are only created upon scaling down the pod. This may require splitting the scaleDownPods into two functions, one to add the PVC annotation (to be run before the pre-sync step) and another to actually scale down pods.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants