Velero is an open source tool for backing up and restoring Kubernetes cluster resources and persistent volumes. You can use it for disaster recovery, cluster migration, and replicating workloads to another cluster.
This guide is a lifecycle reference for common Velero CLI commands: creating and listing backups, scheduling backups, adding backup storage locations, restoring from a backup or schedule, and excluding resources. It also includes two worked examples: a basic backup/restore (no PersistentVolumes) and a snapshot-based backup/restore (with PVs).
Prerequisites: Velero must be installed and configured (e.g. with a GCP, AWS, or Azure provider). If you have not set it up yet, see How to Install Velero for Backups Using GCP Provider before proceeding.
Creating Backups
Create a one-off backup with velero backup create:
# velero backup create <backup-name> [options]
# Examples: backup specific namespaces
velero backup create backup1 --include-cluster-resources=true --include-namespaces=ns1
velero backup create backup2 --include-namespaces=ns1
To control the order in which resources of a given kind are backed up, use --ordered-resources. The value is a semicolon-separated list of Kind=resource1,resource2,.... Use namespace/resourcename for namespaced resources and the resource name only for cluster-scoped resources (e.g. PersistentVolumes). Kind names are plural (e.g. pods, statefulsets).
velero backup create backup1 --include-cluster-resources=true \
--ordered-resources 'pods=ns1/pod1,ns1/pod2;persistentvolumes=pv4,pv8' \
--include-namespaces=ns1
velero backup create backup2 --ordered-resources 'statefulsets=ns1/sts1,ns1/sts0' \
--include-namespaces=ns1
Listing and Inspecting Backups
List backups:
velero backup get
View logs for a specific backup (useful for troubleshooting):
velero backup logs <backup-name>
# Example
velero backup logs backup1
Deleting Backups
Remove a backup from the server and (if applicable) from object storage:
velero backup delete <backup-name>
# Example
velero backup delete backup1
Scheduling Backups
You can schedule backups so they run automatically (e.g. daily or every 6 hours). Use a cron expression or the @every syntax.
# velero schedule create <name> --schedule="<cron-or-@every>" [options]
# Every 6 hours (cron)
velero schedule create test1 --schedule="0 */6 * * *"
# Every 6 hours (@every)
velero schedule create test2 --schedule="@every 6h"
Example schedules with TTL and volume snapshots:
# Yearly: Jan 1st, TTL 10 years + 2 days
velero schedule create "full-yearly" --schedule "0 0 1 1 *" \
--volume-snapshot-locations default --ttl 87720h0m0s
# Monthly: 1st day of month, TTL 53 weeks
velero schedule create "full-monthly" --schedule "0 1 1 * *" \
--volume-snapshot-locations default --ttl 8904h0m0s
# Weekly: Sunday 02:00, TTL 8 weeks
velero schedule create "full-weekly" --schedule "0 2 * * 0" \
--volume-snapshot-locations default --ttl 1344h0m0s
# Daily: 06:00, TTL 14 days
velero schedule create "full-daily" --schedule "0 6 * * *" \
--volume-snapshot-locations default --ttl 336h0m0s
Trigger a backup manually from an existing schedule (without changing the schedule):
velero backup create --from-schedule <schedule-name>
# Example
velero backup create --from-schedule example-schedule
A new backup is created from that schedule’s template; the next run will still occur at the scheduled time.
Listing and Deleting Schedules
List schedules:
velero schedule get
Delete a schedule:
velero schedule delete <schedule-name>
# Example
velero schedule delete test1
Backup Storage Locations
You can add more backup storage locations (e.g. another bucket or prefix) so Velero can store backups in multiple places.
Create a secret with the credentials (e.g. GCP service account key):
kubectl create secret generic -n velero bsl-credentials --from-file=gcp=./credentials-veleroCreate the backup location (example: GCP bucket with a prefix):
velero backup-location create mnp-staging \ --provider gcp \ --bucket citizix-backups \ --prefix comms-live \ --credential=bsl-credentials=gcpList backup locations:
velero backup-location get
Restoring from a Backup
Restore from a specific backup:
# With an explicit restore name
velero restore create <restore-name> --from-backup <backup-name> [options]
# Example
velero restore create restore1 --from-backup backup1
# Let Velero generate a name (e.g. backup1-20230630120000)
velero restore create --from-backup backup1
Restore from the latest backup of a schedule:
velero restore create <restore-name> --from-schedule <schedule-name> [options]
# Example (name can be omitted)
velero restore create --from-schedule schedule-1
Listing and Inspecting Restores
List restores:
velero restore get
Describe one or more restores (detailed status and warnings):
velero restore describe <restore-name-1> [<restore-name-2> ...]
# Example
velero restore describe restore1 restore2
View restore logs (useful for troubleshooting):
velero restore logs <restore-name>
# Example
velero restore logs restore1
Excluding Resources from Backups
To exclude a resource from all Velero backups, add the label velero.io/exclude-from-backup=true:
kubectl label -n <namespace> <resource>/<name> velero.io/exclude-from-backup=true
# Example: exclude a specific ConfigMap
kubectl label -n myapp configmap/my-config velero.io/exclude-from-backup=true
Example: Basic Backup and Restore (No PersistentVolumes)
This example backs up a simple NGINX namespace (no PVs), simulates a disaster by deleting the namespace, then restores it.
1. Create nginx-base.yaml:
---
apiVersion: v1
kind: Namespace
metadata:
name: nginx-example
labels:
app: nginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
namespace: nginx-example
labels:
app: nginx
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- image: nginx:latest
name: nginx
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: my-nginx
namespace: nginx-example
labels:
app: nginx
spec:
type: LoadBalancer
ports:
- port: 80
targetPort: 80
selector:
app: nginx
2. Deploy, backup, delete namespace, then restore:
kubectl apply -f nginx-base.yaml
velero backup create nginx-backup --include-namespaces nginx-example
# Simulate disaster
kubectl delete namespace nginx-example
# Wait for the namespace to be fully deleted.
# Restore
velero restore create --from-backup nginx-backup
Example: Backup and Restore with PersistentVolumes
This example uses a namespace with a PersistentVolumeClaim. Velero snapshots the PV (where supported by your cloud provider); you then delete the namespace (and, with default reclaim policy, the disk) and restore from the backup.
Note: For Azure, Kubernetes 1.7.2+ is required for PV snapshotting of managed disks.
1. Create nginx-with-pv.yaml:
---
apiVersion: v1
kind: Namespace
metadata:
name: nginx-example
labels:
app: nginx
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nginx-logs
namespace: nginx-example
labels:
app: nginx
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 50Mi
# Optional: storageClassName: <YOUR_STORAGE_CLASS_NAME>
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
namespace: nginx-example
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
annotations:
pre.hook.backup.velero.io/container: fsfreeze
pre.hook.backup.velero.io/command: '["/sbin/fsfreeze", "--freeze", "/var/log/nginx"]'
post.hook.backup.velero.io/container: fsfreeze
post.hook.backup.velero.io/command: '["/sbin/fsfreeze", "--unfreeze", "/var/log/nginx"]'
spec:
volumes:
- name: nginx-logs
persistentVolumeClaim:
claimName: nginx-logs
containers:
- image: nginx:1.17.6
name: nginx
ports:
- containerPort: 80
volumeMounts:
- name: nginx-logs
mountPath: /var/log/nginx
readOnly: false
- image: ubuntu:bionic
name: fsfreeze
securityContext:
privileged: true
volumeMounts:
- name: nginx-logs
mountPath: /var/log/nginx
readOnly: false
command: ["/bin/bash", "-c", "sleep infinity"]
---
apiVersion: v1
kind: Service
metadata:
name: my-nginx
namespace: nginx-example
labels:
app: nginx
spec:
type: LoadBalancer
ports:
- port: 80
targetPort: 80
selector:
app: nginx
2. Deploy, backup, delete namespace, then restore:
kubectl apply -f nginx-with-pv.yaml
velero backup create nginx-backup --include-namespaces nginx-example
# Simulate disaster (namespace + PVC deleted; default reclaim policy may delete the disk)
kubectl delete namespace nginx-example
With the default reclaim policy for dynamically provisioned PVs (Delete), the cloud provider may delete the backing disk. Deletion is asynchronous—confirm in your cloud console that the disk is gone before restoring.
velero restore create --from-backup nginx-backup
Summary
- Backups:
velero backup create(with optional--ordered-resources,--include-namespaces,--include-cluster-resources); list withvelero backup get; logs withvelero backup logs; delete withvelero backup delete. - Schedules:
velero schedule create(cron or@every); list withvelero schedule get; delete withvelero schedule delete; trigger ad hoc withvelero backup create --from-schedule <name>. - Restores:
velero restore create --from-backup <name>or--from-schedule <name>; list withvelero restore get; inspect withvelero restore describeandvelero restore logs. - Locations: Add storage with
velero backup-location create; list withvelero backup-location get. - Exclusions: Label resources with
velero.io/exclude-from-backup=trueso they are skipped by backups.
For installation and provider setup (e.g. GCP), see How to Install Velero for Backups Using GCP Provider.
Related Posts
- How to Install Velero for Backups Using GCP Provider – Install and configure Velero with GCP
- Setup Kubernetes Cluster on Ubuntu 20.04 with kubeadm – Build a cluster to backup
- How to Deploy and Configure Argo CD in Kubernetes – GitOps and deployment automation