CSI Volume Snapshots and Restore
Create and restore volume snapshots using CSI VolumeSnapshot API. Configure VolumeSnapshotClass, take point-in-time backups, and clone PVCs from snapshots.
π‘ Quick Answer: Create a
VolumeSnapshotreferencing a PVC to take a point-in-time backup. Restore by creating a new PVC withdataSource: {kind: VolumeSnapshot, name: my-snapshot}. Requires CSI driver with snapshot support and the snapshot controller installed.
The Problem
You need point-in-time backups of persistent volumes for disaster recovery, pre-upgrade snapshots, or cloning data to new environments β without stopping your application.
The Solution
Prerequisites
# Install snapshot CRDs and controller (if not already present)
kubectl apply -f https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/master/client/config/crd/snapshot.storage.k8s.io_volumesnapshotclasses.yaml
kubectl apply -f https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/master/client/config/crd/snapshot.storage.k8s.io_volumesnapshotcontents.yaml
kubectl apply -f https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/master/client/config/crd/snapshot.storage.k8s.io_volumesnapshots.yaml
kubectl apply -f https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/master/deploy/kubernetes/snapshot-controller/setup-snapshot-controller.yamlVolumeSnapshotClass
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshotClass
metadata:
name: csi-snapclass
annotations:
snapshot.storage.kubernetes.io/is-default-class: "true"
driver: ebs.csi.aws.com # or your CSI driver
deletionPolicy: Delete
parameters:
# Driver-specific parameters
encrypted: "true"Take a Snapshot
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshot
metadata:
name: db-snapshot-20260420
namespace: production
spec:
volumeSnapshotClassName: csi-snapclass
source:
persistentVolumeClaimName: postgres-dataRestore from Snapshot
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: postgres-data-restored
namespace: production
spec:
accessModes:
- ReadWriteOnce
storageClassName: gp3-encrypted
resources:
requests:
storage: 100Gi
dataSource:
name: db-snapshot-20260420
kind: VolumeSnapshot
apiGroup: snapshot.storage.k8s.ioAutomated Snapshot CronJob
apiVersion: batch/v1
kind: CronJob
metadata:
name: daily-db-snapshot
namespace: production
spec:
schedule: "0 2 * * *"
jobTemplate:
spec:
template:
spec:
serviceAccountName: snapshot-creator
containers:
- name: snapshot
image: bitnami/kubectl:1.30
command:
- /bin/sh
- -c
- |
SNAP_NAME="db-snap-$(date +%Y%m%d-%H%M%S)"
cat <<EOF | kubectl apply -f -
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshot
metadata:
name: $SNAP_NAME
namespace: production
labels:
app: postgres
type: scheduled
spec:
volumeSnapshotClassName: csi-snapclass
source:
persistentVolumeClaimName: postgres-data
EOF
# Clean up snapshots older than 7 days
kubectl get volumesnapshot -n production -l app=postgres \
--sort-by=.metadata.creationTimestamp -o name | \
head -n -7 | xargs -r kubectl delete -n production
restartPolicy: OnFailureClone a PVC (Without Snapshot)
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: postgres-data-clone
spec:
accessModes:
- ReadWriteOnce
storageClassName: gp3-encrypted
resources:
requests:
storage: 100Gi
dataSource:
name: postgres-data # Source PVC
kind: PersistentVolumeClaimVerify Snapshot Status
# Check snapshot is ready
kubectl get volumesnapshot db-snapshot-20260420 -o jsonpath='{.status.readyToUse}'
# true
# Check snapshot size
kubectl get volumesnapshot db-snapshot-20260420 -o jsonpath='{.status.restoreSize}'
# 100Gi
# List all snapshots
kubectl get volumesnapshot -A --sort-by=.metadata.creationTimestampCommon Issues
| Issue | Cause | Fix |
|---|---|---|
snapshot controller not found | CRDs/controller not installed | Install snapshot-controller |
driver does not support snapshots | CSI driver limitation | Check driver capabilities |
Snapshot stuck in pending | Driver canβt snapshot mounted volume | Some drivers require unmount |
| Restore PVC wrong size | Must match or exceed snapshot size | Set storage β₯ restoreSize |
VolumeSnapshotClass not found | No default class set | Create and annotate as default |
Best Practices
- Automate with CronJobs β Schedule daily snapshots for critical data
- Implement retention β Delete old snapshots to save storage costs
- Test restores regularly β A snapshot you canβt restore is worthless
- Label snapshots β Add app, environment, and date labels for management
- Use
deletionPolicy: Retainβ For critical snapshots that must survive class deletion
Key Takeaways
- VolumeSnapshot provides native K8s point-in-time backup
- Requires CSI driver support + snapshot controller + CRDs
- Restore creates a new PVC pre-populated with snapshot data
- Automate with CronJobs and implement retention policies
- PVC cloning (dataSource: PVC) works without snapshots but is less flexible

Recommended
Kubernetes Recipes β The Complete Book100+ production-ready patterns with detailed explanations, best practices, and copy-paste YAML. Everything in one place.
Get the Book βLearn by Doing
CopyPasteLearn β Hands-on Cloud & DevOps CoursesMaster Kubernetes, Ansible, Terraform, and MLOps with interactive, copy-paste-run lessons. Start free.
Browse Courses βπ Deepen Your Skills β Hands-on Courses
Courses by CopyPasteLearn.com β Learn IT by Doing
