Velero es una herramienta de código abierto que hace copias de seguridad de los recursos de un clúster de Kubernetes (Deployments, Services, ConfigMaps, Secrets, etc.) y de los datos de sus volúmenes persistentes, y las guarda en un almacenamiento de objetos compatible con S3. En este tutorial instalarás Velero con copia de volúmenes a nivel de sistema de ficheros, harás una copia de un namespace con datos, lo borrarás, lo restaurarás y programarás copias diarias con retención automática.
Requisitos previos
Para seguir esta guía necesitas:
- Un clúster de Kubernetes 1.29 o superior con una StorageClass por defecto, por ejemplo desplegado sobre VPS de CubePath.
- Una estación de trabajo Linux (por ejemplo Ubuntu 24.04) con
kubectlconfigurado contra el clúster con permisos de administrador. - Un bucket en un almacenamiento de objetos compatible con S3 (AWS S3, MinIO, Wasabi, Cloudflare R2 u otro), con su endpoint, región, y una clave de acceso con permisos de lectura y escritura sobre ese bucket. En esta guía el bucket se llama
velero-backups.
Cómo funciona Velero
Velero tiene dos partes: la CLI velero, que ejecutas en tu estación de trabajo, y un Deployment en el namespace velero del clúster que hace el trabajo real. Al crear una copia:
- Velero consulta la API de Kubernetes y guarda los recursos seleccionados como JSON en el bucket.
- Si activas la copia de volúmenes a nivel de sistema de ficheros, el DaemonSet
node-agentlee los datos de cada volumen desde el nodo donde está montado y los sube al bucket con Kopia, de forma incremental y deduplicada.
La copia de ficheros funciona con cualquier tipo de volumen, sin depender de que el proveedor de almacenamiento soporte snapshots. Es la opción más portátil, y la que usarás aquí.
Paso 1: Instalar la CLI de Velero
Descarga la CLI desde las versiones publicadas en GitHub. Consulta la última versión estable en la página de versiones y ajusta la variable si hay una más reciente:
VELERO_VERSION=v1.17.0
curl -fsSLO "https://github.com/vmware-tanzu/velero/releases/download/${VELERO_VERSION}/velero-${VELERO_VERSION}-linux-amd64.tar.gz"
tar -xzf "velero-${VELERO_VERSION}-linux-amd64.tar.gz"
sudo install -m 0755 "velero-${VELERO_VERSION}-linux-amd64/velero" /usr/local/bin/velero
En una máquina arm64, sustituye linux-amd64 por linux-arm64. Comprueba la instalación:
velero version --client-only
Client:
Version: v1.17.0
Git commit: ...
Paso 2: Crear el fichero de credenciales
Velero usa el plugin de AWS para hablar con cualquier almacenamiento compatible con S3. Guarda las claves en un fichero con formato de credenciales de AWS:
nano credentials-velero
[default]
aws_access_key_id = your_access_key
aws_secret_access_key = your_secret_key
Restringe los permisos del fichero, ya que contiene claves en texto plano:
chmod 600 credentials-velero
Paso 3: Instalar Velero en el clúster
La orden velero install crea el namespace velero, los CRD, el Deployment y un Secret con tus credenciales. Cada versión de Velero es compatible con una versión concreta del plugin de AWS: para Velero 1.17 es la v1.13. Si usas otra versión, consulta la tabla de compatibilidad en el repositorio del plugin.
Sustituye https://your_s3_endpoint y la región por los de tu proveedor:
velero install \
--provider aws \
--plugins velero/velero-plugin-for-aws:v1.13.0 \
--bucket velero-backups \
--secret-file ./credentials-velero \
--backup-location-config region=us-east-1,s3ForcePathStyle="true",s3Url=https://your_s3_endpoint \
--use-volume-snapshots=false \
--use-node-agent
Qué hace cada opción relevante:
s3ForcePathStyle="true"ys3Url: necesarios para proveedores distintos de AWS. Con AWS S3 puedes omitir ambos.--use-volume-snapshots=false: no configura snapshots del proveedor de discos; los datos de los volúmenes se copiarán como ficheros.--use-node-agent: despliega el DaemonSetnode-agent, que hace esa copia de ficheros.
Comprueba que los pods están en marcha y que Velero puede acceder al bucket:
kubectl get pods -n velero
velero backup-location get
NAME READY STATUS RESTARTS AGE
node-agent-7bq2m 1/1 Running 0 60s
node-agent-kx9fd 1/1 Running 0 60s
velero-6c8f7d9b5d-4lpzn 1/1 Running 0 60s
NAME PROVIDER BUCKET/PREFIX PHASE LAST VALIDATED ACCESS MODE DEFAULT
default aws velero-backups Available 2026-09-25 10:12:03 +0200 CEST ReadWrite true
La columna PHASE debe indicar Available. Si muestra Unavailable, revisa la sección de solución de problemas antes de continuar.
Paso 4: Crear una aplicación de prueba con datos
Para comprobar que la restauración recupera también los datos, crea un namespace con un pod que escribe un fichero en un volumen persistente:
nano demo-app.yaml
apiVersion: v1
kind: Namespace
metadata:
name: demo
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: demo-data
namespace: demo
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 1Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: demo
namespace: demo
spec:
replicas: 1
selector:
matchLabels:
app: demo
template:
metadata:
labels:
app: demo
spec:
containers:
- name: app
image: busybox:1.36
command: ["sh", "-c", "sleep infinity"]
volumeMounts:
- name: data
mountPath: /data
volumes:
- name: data
persistentVolumeClaim:
claimName: demo-data
Aplícalo y escribe un fichero en el volumen:
kubectl apply -f demo-app.yaml
kubectl rollout status deployment/demo -n demo
kubectl exec -n demo deploy/demo -- sh -c 'echo "datos importantes" > /data/prueba.txt'
kubectl exec -n demo deploy/demo -- cat /data/prueba.txt
datos importantes
Paso 5: Hacer una copia de seguridad
Crea una copia del namespace demo. La opción --default-volumes-to-fs-backup indica que los volúmenes de los pods se copien con el node-agent; sin ella solo se guardarían los recursos:
velero backup create demo-backup \
--include-namespaces demo \
--default-volumes-to-fs-backup \
--wait
Backup request "demo-backup" submitted successfully.
Waiting for backup to complete. You may safely press ctrl-c to stop waiting - your backup will continue in the background.
...
Backup completed with status: Completed. You may check for more information using the commands `velero backup describe demo-backup` and `velero backup logs demo-backup`.
Revisa el detalle, incluidos los volúmenes copiados:
velero backup describe demo-backup --details
En la salida, Phase debe ser Completed y en la sección de copias de volúmenes debe aparecer demo/demo-...: data como completada. Si Phase es PartiallyFailed, consulta los errores con velero backup logs demo-backup.
Paso 6: Restaurar el namespace
Simula un desastre borrando el namespace completo, con su volumen:
kubectl delete namespace demo
kubectl get namespace demo
Error from server (NotFound): namespaces "demo" not found
Restaura desde la copia:
velero restore create demo-restore --from-backup demo-backup --wait
Restore request "demo-restore" submitted successfully.
...
Restore completed with status: Completed. You may check for more information using the commands `velero restore describe demo-restore` and `velero restore logs demo-restore`.
Velero recrea el namespace, el PVC y el Deployment, y el node-agent vuelca los datos en el nuevo volumen antes de que arranque el contenedor. Comprueba que el fichero ha vuelto:
kubectl rollout status deployment/demo -n demo
kubectl exec -n demo deploy/demo -- cat /data/prueba.txt
datos importantes
Si necesitas restaurar en otro namespace para comparar sin tocar el original, añade --namespace-mappings demo:demo-copia al velero restore create.
Paso 7: Programar copias automáticas
Una copia manual no protege de nada si nadie se acuerda de hacerla. Crea una programación diaria a las 03:00 UTC que conserve cada copia 7 días:
velero schedule create demo-daily \
--schedule="0 3 * * *" \
--include-namespaces demo \
--default-volumes-to-fs-backup \
--ttl 168h0m0s
Comprueba la programación:
velero schedule get
NAME STATUS CREATED SCHEDULE BACKUP TTL LAST BACKUP SELECTOR PAUSED
demo-daily Enabled 2026-09-25 10:30:12 +0200 CEST 0 3 * * * 168h0m0s n/a <none> false
Para lanzar una ejecución inmediata sin esperar a la hora programada:
velero backup create --from-schedule demo-daily --wait
Las copias generadas se llaman demo-daily-<fecha> y aparecen en velero backup get. Cuando su TTL caduca, Velero las borra del clúster y del bucket.
Para proteger todo el clúster, omite --include-namespaces y excluye los namespaces del sistema que no quieras restaurar, por ejemplo con --exclude-namespaces kube-system,velero.
Migrar aplicaciones a otro clúster
Como las copias viven en el bucket, puedes restaurarlas en un clúster distinto. Instala Velero en el clúster de destino con el mismo bucket y las mismas credenciales (paso 3). Velero sincroniza la lista de copias desde el bucket en un minuto aproximadamente:
velero backup get
Cuando aparezca la copia, restáurala igual que en el paso 6. Ten en cuenta que el clúster de destino debe tener una StorageClass por defecto (o una con el mismo nombre que la del origen) y una versión de Kubernetes que admita las APIs de los recursos copiados. Para evitar que el clúster de destino borre o modifique copias del origen, cambia su ubicación a solo lectura:
kubectl patch backupstoragelocation default -n velero --type merge -p '{"spec":{"accessMode":"ReadOnly"}}'
Solución de problemas
velero backup-location getmuestraUnavailable. Revisa los logs conkubectl logs -n velero deploy/velero | grep -i error. Las causas habituales son credenciales incorrectas, un bucket que no existe, uns3Urlsinhttps://o una región distinta de la que espera el proveedor.- La copia termina en
PartiallyFailedcon errores de volúmenes. Comprueba que hay un podnode-agentenRunningen el nodo donde corre el pod de la aplicación:kubectl get pods -n velero -o wide. - La restauración deja el pod en
Init. Velero añade un contenedor init que espera a que termine la restauración de datos. Revisa el avance convelero restore describe demo-restore --details. - Recursos existentes no se sobrescriben. Por defecto Velero no modifica objetos que ya existen en el clúster. Borra antes el namespace o usa
--existing-resource-policy=updateen la restauración.
Conclusión
Has instalado Velero con un almacenamiento S3, copiado y restaurado un namespace con sus datos y programado copias diarias con caducidad automática. Una copia solo vale si se restaura, así que conviene repetir el paso 6 de forma periódica en un namespace o clúster de pruebas. Como siguientes pasos, puedes activar el versionado y el bloqueo de objetos en el bucket para protegerte de borrados accidentales, añadir una segunda ubicación en otra región con velero backup-location create, o usar snapshots CSI si tu proveedor de almacenamiento los soporta.
