This document outlines the steps to migrate PersistentVolumeClaims (PVCs) between two Kubernetes clusters that share the same VAST backend storage. It also includes steps to validate that the application functions correctly post-migration.
Since the PVCs are provisioned by the VAST CSI driver, it's crucial to ensure the Helm chart configuration (used to deploy the CSI plugin) is identical across both clusters to ensure consistent behavior.
Additionally, the StorageClass definitions and associated secrets (e.g., secret.yaml used by the CSI driver) must also be identical across clusters to avoid binding or mounting issues.
Benefits of This Approach
No data copying: Leverages shared backend storage for instant access.
Minimal downtime: Simply detaches and reattaches the volume.
Reversible: Original data remains intact in VAST if rollback is needed.
Instructions
PVC migration steps:
On the Source Kubernetes Cluster :
Identify the PVC and PV in use:
kubectl get pvc <pvc-name> -n <namespace> -o yaml
kubectl get pv <pv-name> -o yamlTake Note:
Volume ID/Handle (e.g., the backend storage identifier, disk name, volume ID, or NFS path).
StorageClass used.
Delete the PVC from the source cluster (without deleting the actual backend volume!):
Before deleting, ensure the PV has apersistentVolumeReclaimPolicyset to Retain, not Delete.If it's not,
Retain, edit, and patch the PV first.
Then, safely delete the PVC:kubectl delete pvc <pvc-name> -n <namespace>Prepare the PV for the Destination Cluster:
On the source cluster, mark the PV as released by removing any claimRef (necessary step):
TheclaimReffield in a PV is what binds a PersistentVolumeClaim (PVC) to a specific PersistentVolume (PV).
When you try to reuse the PV manifest in another cluster, and it contains aclaimRef, Kubernetes will reject it (or consider it already bound and unusable), especially since the target PVC probably doesn’t exist yet in the new cluster.Export the YAML definitions of the PVC and its associated PV.
kubectl get pvc -n ns1 -o yaml > pvc_backup.yamlkubectl get pv -n ns1 -o yaml > pv_backup.yamlCopy the generated YAML to a system with access to the destination cluster.
On the destination cluster
Restore on the Destination Cluster
Import the PV into the Destination Cluster:
kubectl_second apply -f pv_backup.yamlRecreate PVC in Destination Cluster:
kubectl_second apply -f pvc_backup.yamlRun the following to make sure everything is in place:
kubectl get pvc -n ns1
kubectl get pvkubectl_second get pvc -n ns1
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE
vast-pvc-1 Bound pvc-8ef55295-bfca-4d33-816d-3d48238f8a4b 1Gi RWX vastdata-filesystem <unset> 3d20hkubectl_second get pv -n ns1
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS VOLUMEATTRIBUTESCLASS REASON AGE
pvc-8ef55295-bfca-4d33-816d-3d48238f8a4b 1Gi RWX Delete Bound ns1/vast-pvc-1 vastdata-filesystem <unset> 3d20hPVC bound successfully, mount the PVC successfully, and verified the existing data was not damaged.
sudo mount -t nfs -o vers=3 -vvv 172.21.241.1:/k8s/pvc-8ef55295-bfca-4d33-816d-3d48238f8a4b /mnt/pvc/ls -ltrh /mnt/pvc/
total 42M
-rw-r--r-- 1 nobody nogroup 8.3M Apr 7 09:06 test-app-1-1
-rw-r--r-- 1 nobody nogroup 8.3M Apr 7 09:06 test-app-1-4
-rw-r--r-- 1 nobody nogroup 8.3M Apr 7 09:06 test-app-1-0
-rw-r--r-- 1 nobody nogroup 8.3M Apr 7 09:06 test-app-1-3
-rw-r--r-- 1 nobody nogroup 8.3M Apr 7 09:06 test-app-1-2
Stop the application on the source side and enable it on the destination side - the application worked as expected.
The test application writes timestamped log files (e.g., test-app-1-0, test-app-1-1, etc.) to the mounted PVC every second.
The volume was mounted correctly after migration
Data was preserved during the move
The application resumed logging without reconfiguration
kubectl_second apply -f app.yaml -n ns1kubectl_second get pods -n ns1
NAME READY STATUS RESTARTS AGE
csi-vast-controller-669c57699c-5hvzk 5/5 Running 3 (3d21h ago) 3d21h
csi-vast-node-r59zv 2/2 Running 1 (3d21h ago) 3d21h
test-app-1-0 1/1 Running 0 3d20h
test-app-1-1 1/1 Running 0 3d20h
test-app-1-2 1/1 Running 0 3d20h
test-app-1-3 1/1 Running 0 3d20h
test-app-1-4 1/1 Running 0 3d20htail /mnt/pvc/test-app-1-1
2025-04-07T09:05:57+00:00
2025-04-07T09:05:58+00:00
2025-04-07T09:05:59+00:00
2025-04-07T09:06:00+00:00
2025-04-07T09:06:01+00:00
2025-04-07T09:06:02+00:00
2025-04-07T09:06:03+00:00
2025-04-07T09:06:04+00:00
2025-04-07T09:06:05+00:00
2025-04-07T09:06:06+00:00Additional Resources
Create a Kubernetes Secret with VMS User Credentials for VAST CSI Driver