🗺️ What is Velero?
Velero (formerly Ark) is a CNCF open-source tool for backing up and restoring Kubernetes cluster resources and persistent volumes. It supports disaster recovery, data migration between clusters, and pre-upgrade snapshots.
Velero works by integrating with your cloud provider's object storage (e.g. S3, GCS, Azure Blob) for resource manifests and with volume snapshot APIs for PV data.
🛡️ Disaster Recovery
Scheduled backups to object storage. Restore entire namespaces or targeted resources.
🚚 Cluster Migration
Move workloads between clusters or cloud providers by backup + restore.
📸 Pre-change Snapshots
Snapshot before upgrades or risky changes. Roll back to a known-good state.
🔌 Plugin Architecture
Cloud-provider plugins for object stores and volume snapshots. Extensible with hooks.
🧩 Core Concepts
Key CRDs
| CRD | Purpose |
|---|---|
Backup | Point-in-time backup — what to include/exclude, TTL, hooks |
Restore | Restore from a backup — namespace mapping, label selectors |
Schedule | Cron-triggered recurring Backup creation |
BackupStorageLocation | Object-store bucket + credentials (multiple supported) |
VolumeSnapshotLocation | Where volume snapshots are stored (cloud zone/region) |
DownloadRequest | Used internally by CLI to stream backup logs |
Backup Approaches
CSI Snapshots
Uses the CSI VolumeSnapshot API. Fast, storage-native, preferred on modern clusters.
File-System Backup
Node Agent DaemonSet streams volume data to object storage using Kopia. Works without CSI support.
Cloud-native Snapshots
Provider plugin calls cloud snapshot APIs (EBS, GCP PD, Azure Disk) directly. Very fast.
Installing Velero (AWS example)
# Install Velero CLI (macOS)
brew install velero
# Create static credentials file (use IRSA in production)
cat > credentials-velero <<EOF
[default]
aws_access_key_id=AKIAIOSFODNN7EXAMPLE
aws_secret_access_key=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
EOF
# Deploy Velero into the cluster
velero install \
--provider aws \
--plugins velero/velero-plugin-for-aws:v1.9.0 \
--bucket my-velero-backups \
--secret-file ./credentials-velero \
--backup-location-config region=us-east-1 \
--snapshot-location-config region=us-east-1 \
--use-node-agent
Verify Installation
kubectl get deployment velero -n velero
velero backup-location get
# NAME PROVIDER BUCKET/PREFIX PHASE
# default aws my-velero-backups Available
kubectl get daemonset node-agent -n velero
# NAME PROVIDER BUCKET/PREFIX PHASE
# default aws my-velero-backups Available
kubectl get daemonset node-agent -n velero
💾 Backups & Restores
Creating a Backup
# Ad-hoc backup of a single namespace
velero backup create my-app-backup \
--include-namespaces my-app \
--ttl 720h # retain for 30 days
# Backup with label selector
velero backup create api-backup \
--selector app=api \
--include-namespaces production
# Backup entire cluster (all namespaces)
velero backup create full-cluster-backup
# Check status
velero backup describe my-app-backup
velero backup logs my-app-backup
Backup YAML manifest
apiVersion: velero.io/v1
kind: Backup
metadata:
name: my-app-backup
namespace: velero
spec:
includedNamespaces:
- my-app
excludedResources:
- events
- events.events.k8s.io
ttl: 720h0m0s
storageLocation: default
volumeSnapshotLocations:
- default
hooks:
resources:
- name: freeze-db
includedNamespaces: [my-app]
labelSelector:
matchLabels: {app: postgres}
pre:
- exec:
container: postgres
command: ["/bin/bash", "-c", "psql -c 'CHECKPOINT;'"]
onError: Fail
timeout: 30s
Restoring from a Backup
# Restore everything from a backup
velero restore create --from-backup my-app-backup
# Restore to a different namespace
velero restore create \
--from-backup my-app-backup \
--namespace-mappings my-app:my-app-restored
# Restore only specific resources
velero restore create \
--from-backup my-app-backup \
--include-resources deployments,services,configmaps
# Monitor restore status
velero restore describe my-app-backup-20240101
velero restore logs my-app-backup-20240101
Scheduled Backups
# CLI shorthand
velero schedule create daily-app-backup \
--schedule="0 2 * * *" \
--include-namespaces my-app \
--ttl 168h # 7 days
# As a YAML manifest
apiVersion: velero.io/v1
kind: Schedule
metadata:
name: daily-app-backup
namespace: velero
spec:
schedule: "0 2 * * *" # 2 AM daily
template:
includedNamespaces:
- my-app
ttl: 168h0m0s
storageLocation: default
Backup Retention Strategy
| Schedule | Frequency | TTL | Use case |
|---|---|---|---|
| Hourly | @every 1h | 24h | High-change workloads, short-term undo |
| Daily | 0 2 * * * | 7d | Standard production namespaces |
| Weekly | 0 3 * * 0 | 30d | Compliance / long-term retention |
| Monthly | 0 4 1 * * | 365d | Regulatory / audit archives |
🚚 Cluster Migration
Velero's most powerful use case: move workloads from one cluster to another — across regions, cloud providers, or on-prem to cloud.
Migration Workflow
- Install Velero on source cluster pointing to shared object storage bucket.
- Run
velero backup create cluster-migration --include-namespaces app1,app2on source. - Verify backup is
Completed:velero backup describe cluster-migration. - Install Velero on destination cluster pointing to the same object storage bucket (read-only is fine).
- Run
velero restore create --from-backup cluster-migrationon destination. - Validate workloads, update DNS/load-balancer endpoints, drain source.
--restore-option flags or a ConfigMap to map old → new storage classes before restoring PVCs.
# Map storage classes during restore
velero restore create \
--from-backup cluster-migration \
--storage-class-name standard=premium-ssd
# Or use a ConfigMap
kubectl apply -f - <<EOF
apiVersion: v1
kind: ConfigMap
metadata:
name: change-storage-class-config
namespace: velero
labels:
velero.io/plugin-config: ""
velero.io/change-storage-class: RestoreItemAction
data:
gp2: gp3
standard: premium-ssd
EOF
Multiple Backup Storage Locations
You can configure secondary BSLs for cross-region redundancy:
velero backup-location create secondary \
--provider aws \
--bucket my-velero-backups-eu \
--config region=eu-west-1
# Mark a BSL as read-only (for migration destination)
velero backup-location set secondary --access-mode ReadOnly
Production Best Practices
Test Restores Regularly
Schedule monthly restore drills to a staging cluster. A backup you've never restored from is not a backup.
Encrypt Backups
Enable server-side encryption on your S3 bucket (SSE-KMS). Velero does not encrypt independently.
Monitor Backup Status
Expose velero_backup_success_total and velero_backup_failure_total Prometheus metrics. Alert on failures.
Exclude Ephemeral Data
Exclude events, cache PVCs, and scratch volumes from backups to reduce size and cost.
📝 Knowledge Check
CHECKPOINT in Postgres). Post-backup hooks resume after the snapshot completes.gp2 → gp3). How do you handle this in Velero?change-storage-class ConfigMap. Velero's change-storage-class RestoreItemAction plugin reads this ConfigMap and rewrites StorageClass references during restore.