--- title: "Cómo hacer copias de seguridad de Kubernetes con Velero" description: "Instala Velero con almacenamiento de objetos S3, copia recursos y volúmenes persistentes, programa copias diarias y restaura un namespace borrado paso a paso." category: "Kubernetes Avanzado" language: es source: https://cubepath.com/es/docs/kubernetes-avanzado/copia-de-seguridad-de-kubernetes-con-velero updated: 2026-09-25 --- # Cómo hacer copias de seguridad de Kubernetes con Velero 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 `kubectl` configurado 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: 1. Velero consulta la API de Kubernetes y guarda los recursos seleccionados como JSON en el bucket. 2. Si activas la copia de volúmenes a nivel de sistema de ficheros, el DaemonSet `node-agent` lee 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](https://github.com/vmware-tanzu/velero/releases) y ajusta la variable si hay una más reciente: ```bash 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: ```bash velero version --client-only ``` ```output 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: ```bash nano credentials-velero ``` ```ini [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: ```bash 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](https://github.com/vmware-tanzu/velero-plugin-for-aws). Sustituye `https://your_s3_endpoint` y la región por los de tu proveedor: ```bash 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"` y `s3Url`: 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 DaemonSet `node-agent`, que hace esa copia de ficheros. Comprueba que los pods están en marcha y que Velero puede acceder al bucket: ```bash kubectl get pods -n velero velero backup-location get ``` ```output 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: ```bash nano demo-app.yaml ``` ```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: ```bash 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 ``` ```output 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: ```bash velero backup create demo-backup \ --include-namespaces demo \ --default-volumes-to-fs-backup \ --wait ``` ```output 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: ```bash 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: ```bash kubectl delete namespace demo kubectl get namespace demo ``` ```output Error from server (NotFound): namespaces "demo" not found ``` Restaura desde la copia: ```bash velero restore create demo-restore --from-backup demo-backup --wait ``` ```output 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: ```bash kubectl rollout status deployment/demo -n demo kubectl exec -n demo deploy/demo -- cat /data/prueba.txt ``` ```output 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: ```bash velero schedule create demo-daily \ --schedule="0 3 * * *" \ --include-namespaces demo \ --default-volumes-to-fs-backup \ --ttl 168h0m0s ``` Comprueba la programación: ```bash velero schedule get ``` ```output 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 false ``` Para lanzar una ejecución inmediata sin esperar a la hora programada: ```bash velero backup create --from-schedule demo-daily --wait ``` Las copias generadas se llaman `demo-daily-` 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: ```bash 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: ```bash kubectl patch backupstoragelocation default -n velero --type merge -p '{"spec":{"accessMode":"ReadOnly"}}' ``` ## Solución de problemas - **`velero backup-location get` muestra `Unavailable`.** Revisa los logs con `kubectl logs -n velero deploy/velero | grep -i error`. Las causas habituales son credenciales incorrectas, un bucket que no existe, un `s3Url` sin `https://` o una región distinta de la que espera el proveedor. - **La copia termina en `PartiallyFailed` con errores de volúmenes.** Comprueba que hay un pod `node-agent` en `Running` en 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 con `velero 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=update` en 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.