Change PV StorageClass

How to migrate from between storageclasses

This guide details all steps to change storage class of a volume. The instruction can be used to migrate from one storage class to another, while retaining data. For example from 8kto v2-4k.

Prerequisites

  • Access to the kubernetes cluster
  • Access to Openstack kubernetes Project

Preparation steps

  1. Populate variables

    Complete with relevant names for your setup. Then copy/paste them into the terminal to set them as environment variables that will be used throughout the guide. PVC is the

    PVC=test1
    NAMESPACE=default
    NEWSTORAGECLASS=v2-1k
    
  2. Fetch and populate the PV name by running:

    PV=$(kubectl get pvc -n $NAMESPACE $PVC -o go-template='{{.spec.volumeName}}')
    
  3. Create backup of PVC and PV configurations

    Fetch the PVC and PV configurations and store in /tmp/ for later use:

    kubectl get pvc -n $NAMESPACE $PVC -o yaml | tee /tmp/pvc.yaml
    kubectl get pv  $PV -o yaml | tee /tmp/pv.yaml
    
  4. Change VolumeReclaimPolicy

    To avoid deletion of the PV when deleting the PVC, the volume needs to have VolumeReclaimPolicy set to Retain.

    Patch:

    kubectl patch pv $PV -p '{"spec":{"persistentVolumeReclaimPolicy":"Retain"}}'
    
  5. Stop pods from accessing the mounted volume (ie kill pods/scale statefulset/etc..).

  6. Delete the PVC.

    kubectl delete pvc -n "$NAMESPACE" "$PVC"
    

Login to Openstack

  1. Navigate to: Volumes -> Volumes

  2. Make a backup of the volume From the drop-down to the right, select backup. The backup is good practice, not used in the following steps.

  3. Change the storage type to desired type. The volume should now or shortly have status Available. Dropdown to the right, Edit volume -> Change volume type:

    • Select your desired storage type
    • Select Migration policy=Ondemand

    The window will close, and the volume will be updated and migrated (to the v2 storage platform) if necessary, by the backend. The status becomes “Volume retyping”. Wait until completed.

    We have a complementary guide here.

Back to kubernetes

  1. Release the tie between PVC and PV

    The PV is still referencing its old PVC, in the claimRef, found under spec.claimRef.uid. This UID needs to be nullified to release the PV, allowing it to be adopted by a PVC with correct storageClass.

    Patch claimRef to null:

    kubectl patch pv "$PV" -p '{"spec":{"claimRef":{"namespace":"'$NAMESPACE'","name":"'$PVC'","uid":null}}}'
    
  2. The PV StorageClass in kubernetes does not match to its counterpart in Openstack.

    We need to patch the storageClassName reference in the PV:

    kubectl patch pv "$PV" -p '{"spec":{"storageClassName":"'$NEWSTORAGECLASS'"}}'
    
  3. Prepare a new PVC with the updated storageClass

    We need to modify the saved /tmp/pvc.yaml.

    1. Remove “last-applied-configuration”:

      sed -i '/kubectl.kubernetes.io\/last-applied-configuration: |/ { N; d; }' /tmp/pvc.yaml
      
    2. Update existing storageClassName to the new one:

      sed -i 's/storageClassName: .*/storageClassName: '$NEWSTORAGECLASS'/g' /tmp/pvc.yaml
      
  4. Apply the updated /tmp/pvc.yaml

    kubectl apply -f /tmp/pvc.yaml
    
  5. Update the PV to bind with the new PVC

    We must allow the new PVC to bind correctly to the old PV. We need to first fetch the new PVC UID, then patch the PV with the PVC UID so kubernetes understands what PVC the PV belongs to.

    1. Retrieve the new PVC UID:

      PVCUID=$(kubectl get -n "$NAMESPACE" pvc "$PVC" -o custom-columns=UID:.metadata.uid --no-headers)
      
    2. Patch the PV with the new UID of the PVC:

      kubectl patch pv "$PV" -p '{"spec":{"claimRef":{"uid":"'$PVCUID'"}}}'
      
  6. Reset the Reclaim Policy of the volume to Delete:

    kubectl patch pv $PV -p '{"spec":{"persistentVolumeReclaimPolicy":"Delete"}}'
    
  7. Completed.

    • Verify the volume works healthily.
    • Update your manifests to reflect the new storageClassName.
Last modified May 15, 2024: merge-k8s-guide-and-kb (#178) (ac3936f)