Pvc migration testing

From UVOO Tech Wiki
Jump to navigation Jump to search

Migrate many PVCs from one storage class to another in same namespace

Use these scripts for migration and testing

create-test-pvc.sh

#!/bin/bash
set -eu

NS=${1:-default}
SC=${2:-managed-csi-hdd}
PVC_NAME=test-pvc
POD_NAME=test-pod

cat <<EOF | kubectl apply -n $NS -f -
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: $PVC_NAME
spec:
  accessModes: [ReadWriteOnce]
  resources:
    requests:
      storage: 1Gi
EOF

cat <<EOF | kubectl apply -n $NS -f -
apiVersion: v1
kind: Pod
metadata:
  name: $POD_NAME
spec:
  containers:
  - name: busybox
    image: busybox
    command: ["sleep", "3600"]
    volumeMounts:
    - name: vol
      mountPath: /data
  volumes:
  - name: vol
    persistentVolumeClaim:
      claimName: $PVC_NAME
EOF

kubectl wait --for=condition=Ready pod/$POD_NAME -n $NS --timeout=60s
kubectl exec -n $NS $POD_NAME -- sh -c 'echo "This is a test." > /data/test.txt'

# kubectl delete pod/$POD_NAME pvc/$PVC_NAME -n $NS
kubectl delete pod/$POD_NAME -n $NS

swap-storage-class.sh

#!/bin/bash
set -euo pipefail

NS="${1:?Namespace required}"
SRC_SC="${2:?Source storage class required}"
DEST_SC="${3:?Destination storage class required}"
SINGLE_PVC="${4:-}" # optional fourth arg

get_matching_pvcs() {
  if [[ -n "$SINGLE_PVC" ]]; then
    size=$(kubectl get pvc "$SINGLE_PVC" -n "$NS" -o jsonpath='{.spec.resources.requests.storage}')
    sc=$(kubectl get pvc "$SINGLE_PVC" -n "$NS" -o jsonpath='{.spec.storageClassName}')
    if [[ "$sc" == "$SRC_SC" ]]; then
      echo "$SINGLE_PVC|$size"
    else
      echo "❌ PVC '$SINGLE_PVC' does not use storageClass '$SRC_SC'" >&2
      exit 1
    fi
  else
    kubectl get pvc -n "$NS" -o jsonpath='{range .items[*]}{.metadata.name}{"|"}{.spec.storageClassName}{"|"}{.spec.resources.requests.storage}{"\n"}{end}' |
      awk -F'|' -v sc="$SRC_SC" '$2==sc{print $1 "|" $3}'
  fi
}

pvcs=$(get_matching_pvcs)

if [[ -z "$pvcs" ]]; then
  echo "No matching PVCs found"
  exit 0
fi

for line in $pvcs; do
  pvc=$(cut -d'|' -f1 <<<"$line")
  size=$(cut -d'|' -f2 <<<"$line")
  tmp_pvc="${pvc}-tmp"

  echo "🔷 Scaling down workloads using PVC $pvc..."
  scaled_objects=()
  for obj in $(kubectl get deploy,sts -n "$NS" -o name); do
    if kubectl get "$obj" -n "$NS" -o json | grep -q "$pvc"; then
      echo "Scaling $obj to 0"
      kubectl scale "$obj" -n "$NS" --replicas=0
      scaled_objects+=("$obj")
    fi
  done

  echo "🔷 Creating temporary PVC $tmp_pvc with $DEST_SC..."
  cat <<EOF | kubectl apply -n "$NS" -f -
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: $tmp_pvc
spec:
  accessModes: [ReadWriteOnce]
  resources:
    requests:
      storage: $size
  storageClassName: $DEST_SC
EOF

  echo "🔷 Migrating data from $pvc -> $tmp_pvc..."
  pv-migrate \
    --source "$pvc" \
    -n "$NS" \
    --dest "$tmp_pvc" \
    -N "$NS" \
    --strategies mnt2,svc \
    --compress \
    --ignore-mounted

  echo "🔷 Deleting original PVC $pvc..."
  kubectl delete pvc "$pvc" -n "$NS"

  echo "🔷 Re-creating original PVC $pvc with $DEST_SC..."
  cat <<EOF | kubectl apply -n "$NS" -f -
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: $pvc
spec:
  accessModes: [ReadWriteOnce]
  resources:
    requests:
      storage: $size
  storageClassName: $DEST_SC
EOF

  echo "🔷 Migrating data back from $tmp_pvc -> $pvc..."
  pv-migrate \
    --source "$tmp_pvc" \
    -n "$NS" \
    --dest "$pvc" \
    -N "$NS" \
    --compress \
    --ignore-mounted

  echo "🔷 Deleting temporary PVC $tmp_pvc..."
  kubectl delete pvc "$tmp_pvc" -n "$NS"

  echo "🔷 Scaling workloads back up..."
  for obj in "${scaled_objects[@]}"; do
    echo "Scaling $obj to 1"
    kubectl scale "$obj" -n "$NS" --replicas=1
  done

  echo "✅ Migration of PVC $pvc complete."
done

example

./swap-storage-class.sh prometheus managed-csi-hdd standardssd-zrs prometheus-server

create-test-pod-and-mount.yaml

apiVersion: v1
kind: Pod
metadata:
  name: ubuntu-pvc-pod
spec:
  volumes:
    - name: my-pvc-storage
      persistentVolumeClaim:
        claimName: test-pvc # Replace with the name of your existing PVC
  containers:
    - name: ubuntu-container
      image: ubuntu:latest
      command: ["sleep", "infinity"]
      volumeMounts:
        - name: my-pvc-storage
          mountPath: /data # Replace with the desired mount path inside the container (e.g., /mnt/data)