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:
1
2
3
4
5
| # 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).
1
2
3
4
5
6
| 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:
View logs for a specific backup (useful for troubleshooting):
1
2
3
4
| velero backup logs <backup-name>
# Example
velero backup logs backup1
|
Deleting Backups
Remove a backup from the server and (if applicable) from object storage:
1
2
3
4
| 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.
1
2
3
4
5
6
7
| # 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:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| # 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):
1
2
3
4
| 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:
Delete a schedule:
1
2
3
4
| 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):
1
| kubectl create secret generic -n velero bsl-credentials --from-file=gcp=./credentials-velero
|
Create the backup location (example: GCP bucket with a prefix):
1
2
3
4
5
| velero backup-location create mnp-staging \
--provider gcp \
--bucket citizix-backups \
--prefix comms-live \
--credential=bsl-credentials=gcp
|
List backup locations:
1
| velero backup-location get
|
Restoring from a Backup
Restore from a specific backup:
1
2
3
4
5
6
7
8
| # 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:
1
2
3
4
| 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:
Describe one or more restores (detailed status and warnings):
1
2
3
4
| velero restore describe <restore-name-1> [<restore-name-2> ...]
# Example
velero restore describe restore1 restore2
|
View restore logs (useful for troubleshooting):
1
2
3
4
| 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:
1
2
3
4
| 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:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
| ---
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:
1
2
3
4
5
6
7
8
9
10
| 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:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
| ---
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:
1
2
3
4
5
6
| 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.
1
| velero restore create --from-backup nginx-backup
|
Summary
- Backups:
velero backup create (with optional --ordered-resources, --include-namespaces, --include-cluster-resources); list with velero backup get; logs with velero backup logs; delete with velero backup delete. - Schedules:
velero schedule create (cron or @every); list with velero schedule get; delete with velero schedule delete; trigger ad hoc with velero backup create --from-schedule <name>. - Restores:
velero restore create --from-backup <name> or --from-schedule <name>; list with velero restore get; inspect with velero restore describe and velero restore logs. - Locations: Add storage with
velero backup-location create; list with velero backup-location get. - Exclusions: Label resources with
velero.io/exclude-from-backup=true so 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