Skip to content

Instantly share code, notes, and snippets.

@pschichtel
Created May 13, 2024 00:49
Show Gist options
  • Save pschichtel/578822f83535172230e315fd9ced2bd5 to your computer and use it in GitHub Desktop.
Save pschichtel/578822f83535172230e315fd9ced2bd5 to your computer and use it in GitHub Desktop.
A small script to migrate PVCs and their data to a new storage class. It requires bash, kubectl, yq, jq and [pv-migrate](https://github.com/utkuozdemir/pv-migrate).
#!/usr/bin/env bash
set -euo pipefail
namespace="${1?no namespace}"
source_pvc="${2?no source pvc}"
target_sc="${3?no target SC}"
tmp_pvc_name="${source_pvc}-tmp"
echo "Exporting the current PVC..."
manifest="$(mktemp --suffix=.yaml)"
kubectl -n "$namespace" get pvc "$source_pvc" -o yaml > "$manifest"
echo "Deriving template for new temporary PVC..."
# cleanup stuff
yq eval -i 'del(.metadata.annotations) | del(.metadata.creationTimestamp) | del(.metadata.finalizers) | del(.metadata.uid) | del(.status) | del(.metadata.resourceVersion) | del(.spec.volumeName) ' "$manifest"
# patch the SC name and pvc-name
SC_NAME="$target_sc" PVC_NAME="$tmp_pvc_name" yq eval -i '.spec.storageClassName = env(SC_NAME) | .metadata.name = env(PVC_NAME)' "$manifest"
if [ -n "${PVC_OVERRIDE_SIZE:-}" ]
then
yq eval -i '.spec.resources.requests.storage = env(PVC_OVERRIDE_SIZE)' "$manifest"
fi
echo "Creating temporary new PVC for data migration..."
kubectl -n "$namespace" create -f "$manifest"
echo "Migrating the data from the old to the temporary PVC..."
pv-migrate migrate \
--source-namespace "$namespace" \
--dest-namespace "$namespace" \
"$source_pvc" \
"$tmp_pvc_name"
pv="$(kubectl -n "$namespace" get pvc "$tmp_pvc_name" -o json | jq -r .spec.volumeName)"
reclaimPolicy="$(kubectl get pv "$pv" -o json | jq -r .spec.persistentVolumeReclaimPolicy)"
if [ "$reclaimPolicy" != "Retain" ]
then
echo "Switch the new PV's reclaim policy to Retain for the PVC swap..."
kubectl patch pv "$pv" -p '{"spec":{"persistentVolumeReclaimPolicy":"Retain"}}'
fi
echo "Deleting the current PVCs..."
kubectl -n "$namespace" delete pvc "$source_pvc" "$tmp_pvc_name"
echo "Creating the final PVC with the old name..."
PV="$pv" PVC_NAME="$source_pvc" yq eval -i '.metadata.name = env(PVC_NAME) | .spec.volumeName = env(PV)' "$manifest"
kubectl -n "$namespace" create -f "$manifest"
echo "Patching the PV to reference the final PVC..."
claim_ref_patch="$(kubectl -n "$namespace" get pvc "$source_pvc" -o json | jq -c '{spec: {claimRef: {apiVersion: .apiVersion, kind: .kind, name: .metadata.name, namespace: .metadata.namespace, resourceVersion: .metadata.resourceVersion, uid: .metadata.uid}}}')"
kubectl patch pv "$pv" -p "$claim_ref_patch"
if [ "$reclaimPolicy" != "Retain" ]
then
echo "Reset the PV's reclaim policy to its original value..."
kubectl patch pv "$pv" -p '{"spec":{"persistentVolumeReclaimPolicy":"'"$reclaimPolicy"'"}}'
fi
echo "Done!"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment