Restaurar con Tenax¶
Cada restauración es un recurso Restore. La consola, la CLI y la API crean uno. Las restauraciones nunca escriben en
una base de datos existente, salvo que pidas en el mismo lugar y escribas el nombre del objetivo. Elige el modo:
| Necesidad | Modo | Rol |
|---|---|---|
| Mirar datos, comprobar un arreglo, sacar un informe | sandbox (por defecto) | operator |
| Recuperar una tabla o unas cuantas filas | sandbox, y luego copiar lo que necesites | operator |
| Una copia junto a producción (nombre de base de datos nuevo) | new | restorer |
| Un archivo de volcado para alguien fuera del clúster | download (URL prefirmada, 1 h) | restorer |
| Revertir todo el objetivo | in place (tras un respaldo de seguridad) | restorer-admin |
1. Encontrar el punto¶
tenax targets # PITR windows and last backups
tenax backups team/app # versions (ids, times, sizes, verified, pinned)
tenax changes team/app --since 6h # what changed when: per-table counts and DDL per segment
tenax diff <backup-a> <backup-b> # schema and row changes between two versions
En la consola, abre el objetivo y luego Cambios. Cada fila de segmento tiene los enlaces "sandbox before" y "sandbox after", que rellenan el momento.
Con PITR sirve cualquier segundo dentro de una ventana (UTC, RFC3339): --at 2026-01-02T03:04:05Z. Sin PITR, elige un
ID de respaldo: --at 20260102T020000Z-1a2b3c. Si el momento no es restaurable, Tenax explica por qué y muestra las
ventanas.
2. Restaurar en un sandbox (seguro, la opción por defecto)¶
tenax restore team/app --at 2026-01-02T03:04:05Z --ttl 6h --wait
tenax sandbox show <sandbox> # connection info, expiry
tenax query <sandbox> -e "select count(*) from orders where created_at > now() - interval '1 day'"
tenax query <sandbox> -e "select * from orders where id = 42" -o csv > order42.csv
- El sandbox recibe su propio namespace
tenax-sbx-<name>, credenciales aleatorias y un TTL (24 h por defecto; amplíalo contenax sandbox extend <sandbox> --by 24h, hasta el máximo de la política). - La consola de consultas es de solo lectura por defecto, con un timeout de 30 s y un límite de 1.000 filas. Las
columnas que coinciden con los patrones
maskdel objetivo se enmascaran. Cada consulta queda auditada. - Desde otro pod: ponle la etiqueta
tenax.run/sandbox-client: <sandbox>y conéctate a la dirección interna del clúster que muestrasandbox show. - Desde un portátil, si el sandbox se creó con
--expose:tenax sandbox connect <sandbox> --port 15432. Esto abre el túnel a través de Cloudflare Access y muestra la cadena de conexión. tenax sandbox delete <sandbox>cuando termines. Los sandboxes vencidos se borran automáticamente.
3. Restaurar en una base de datos nueva¶
tenax restore team/app --at 2026-01-02T03:04:05Z --to new \
--host postgres.team.svc --database app_restored --credentials-secret tenax-admin --wait
Tenax primero restaura en un sandbox intermedio, ejecuta las comprobaciones y luego copia el resultado en la base de
datos nueva con un volcado y una carga lógicos (ADR 0007). Nunca sobrescribe una base de datos existente. El secreto
de administrador (prefijo tenax-) vive en el namespace del objetivo y necesita CREATE DATABASE.
4. Descarga¶
--wait muestra una URL prefirmada a un volcado descifrado y recomprimido. Es válida durante 1 hora. La URL es un
secreto: compártela como tal.
5. En el mismo lugar (último recurso)¶
tenax restore team/app --at 2026-01-02T03:04:05Z --to in-place --confirm app --credentials-secret tenax-admin --wait
- Detén primero a quienes escriben. Tenax no detiene las aplicaciones. Escálalas a cero o ponlas en modo de mantenimiento.
- Tenax toma un respaldo de seguridad del estado actual (motivo
safety). Omitirlo requiere--skip-safety-backup. - Restaura en un sandbox intermedio, comprueba el resultado y luego reemplaza las bases de datos del objetivo.
- Vuelve a arrancar las aplicaciones y compruébalas.
Si algo sale mal, el respaldo de seguridad es una versión normal del objetivo: restáuralo de la misma manera.
Sin la CLI¶
El recurso Restore es la API:
apiVersion: tenax.run/v1alpha1
kind: Restore
metadata: { name: app-incident-42, namespace: team }
spec:
target: app
source: { time: "2026-01-02T03:04:05Z" } # or backupID: ..., or latest: true
destination:
mode: sandbox
sandbox: { ttl: 6h }
kubectl -n team get restore app-incident-42 -w muestra el progreso: plan, descarga de la base, reproducción,
comprobaciones, Succeeded.
Cuando el propio Tenax está caído¶
El store es la fuente de verdad y el formato de los respaldos es sencillo:
- manifest.json lista cada objeto con su tamaño y su SHA-256.
- Los objetos están comprimidos con zstd y cifrados con age: age -d -i key.txt obj.zst.age | zstd -d.
- Los respaldos físicos de Postgres son flujos tar de pg_basebackup más segmentos de WAL.
- Los respaldos lógicos de Postgres son archivos pg_dump -Fc, uno por base de datos.
- Los respaldos de MySQL son la salida de mysqldump más archivos de binlog.
Tras perder o reconstruir un clúster¶
La recuperación es automática. Tenax no tiene base de datos propia: el store guarda cada respaldo (y es la única copia que importa), Git guarda el BackupStore, las políticas y los objetivos (GitOps), y las identidades age son secretos que restauras como cualquier otro. Instala Tenax en el clúster nuevo con el mismo store y las mismas identidades, y aplica los mismos objetivos. Después:
- El controlador revisa cada store al arrancar (
BackupStore.status.lastImportTime). Para cada objetivo, vuelve a crear los objetos Backup de loskeepBackupObjectsrespaldos más recientes (20 por defecto), incluidos los fijados. No se escribe nada en el store. Los respaldos más antiguos siguen en el store, sujetos a la retención, y en el catálogo de la consola. - Las restauraciones, las ventanas de PITR y la consola funcionan como antes. El streamer inicia una cadena nueva a partir de un respaldo completo nuevo.
La importación también se ejecuta cuando cambian los objetivos y cada controller.autoImport.interval (1 h).
Desactívala con controller.autoImport.enabled: false. tenax catalog import [--dry-run] hace lo mismo a mano, con tu
kubeconfig.