πŸ“šBook Signing at KubeCon EU 2026Meet us at Booking.com HQ (Mon 18:30-21:00) & vCluster booth #521 (Tue 24 Mar, 12:30-1:30pm) β€” free book giveaway!RSVP Booking.com Event
Storage intermediate ⏱ 15 minutes K8s 1.28+

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.

By Luca Berton β€’ β€’ πŸ“– 5 min read

πŸ’‘ Quick Answer: Create a VolumeSnapshot referencing a PVC to take a point-in-time backup. Restore by creating a new PVC with dataSource: {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.yaml

VolumeSnapshotClass

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-data

Restore 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.io

Automated 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: OnFailure

Clone 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: PersistentVolumeClaim

Verify 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.creationTimestamp

Common Issues

IssueCauseFix
snapshot controller not foundCRDs/controller not installedInstall snapshot-controller
driver does not support snapshotsCSI driver limitationCheck driver capabilities
Snapshot stuck in pendingDriver can’t snapshot mounted volumeSome drivers require unmount
Restore PVC wrong sizeMust match or exceed snapshot sizeSet storage β‰₯ restoreSize
VolumeSnapshotClass not foundNo default class setCreate and annotate as default

Best Practices

  1. Automate with CronJobs β€” Schedule daily snapshots for critical data
  2. Implement retention β€” Delete old snapshots to save storage costs
  3. Test restores regularly β€” A snapshot you can’t restore is worthless
  4. Label snapshots β€” Add app, environment, and date labels for management
  5. 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
#csi #snapshots #storage #backup #restore
Luca Berton
Written by Luca Berton

Principal Solutions Architect specializing in Kubernetes, AI/GPU infrastructure, and cloud-native platforms. Author of Kubernetes Recipes and creator of CopyPasteLearn courses.

Kubernetes Recipes book cover

Want More Kubernetes Recipes?

This recipe is from Kubernetes Recipes, our 750-page practical guide with hundreds of production-ready patterns.

Luca Berton Ansible Pilot Ansible by Example Open Empower K8s Recipes Terraform Pilot CopyPasteLearn ProteinLens