Ripristinare con Tenax¶
Ogni ripristino è una risorsa Restore. La console, la CLI e l'API ne creano tutte una. I ripristini non scrivono
mai in un database esistente, a meno che tu non chieda il ripristino sul posto e digiti il nome del target.
Scegli la modalità:
| Esigenza | Modalità | Ruolo |
|---|---|---|
| Guardare i dati, verificare una correzione, eseguire un report | sandbox (predefinita) | operator |
| Recuperare una tabella o poche righe | sandbox, poi copia ciò che ti serve | operator |
| Una copia accanto alla produzione (nuovo nome di database) | new | restorer |
| Un file di dump per qualcuno fuori dal cluster | download (URL prefirmato, 1 h) | restorer |
| Riportare indietro l'intero target | sul posto (dopo un backup di sicurezza) | restorer-admin |
1. Trovare il 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
Nella console, apri il target, poi Modifiche. Ogni riga di segmento ha i link "sandbox prima" e "dopo" che compilano l'orario.
Con PITR funziona qualsiasi secondo dentro una finestra (UTC, RFC3339): --at 2026-01-02T03:04:05Z. Senza PITR,
scegli un id di backup: --at 20260102T020000Z-1a2b3c. Se l'orario non è ripristinabile, Tenax spiega perché e
stampa le finestre.
2. Ripristinare in una sandbox (sicuro, l'opzione predefinita)¶
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
- La sandbox riceve un namespace proprio
tenax-sbx-<name>, credenziali casuali e un TTL (predefinito 24 h, estendibile contenax sandbox extend <sandbox> --by 24h, fino al massimo della policy). - La console di query è in sola lettura per impostazione predefinita, con un timeout di 30 s e un limite di 1.000
righe. Le colonne che corrispondono ai pattern
maskdel target vengono mascherate. Ogni query viene registrata nell'audit. - Da un altro pod: assegnagli l'etichetta
tenax.run/sandbox-client: <sandbox>e connettiti all'indirizzo interno al cluster stampato dasandbox show. - Da un portatile, se la sandbox è stata creata con
--expose:tenax sandbox connect <sandbox> --port 15432. Questo apre il tunnel tramite Cloudflare Access e stampa la stringa di connessione. tenax sandbox delete <sandbox>quando hai finito. Le sandbox scadute vengono eliminate automaticamente.
3. Ripristinare in un nuovo database¶
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 ripristina prima in una sandbox di staging, esegue i controlli, poi copia il risultato nel nuovo database con
un dump e un caricamento logici (ADR 0007). Non sovrascrive mai un database esistente. Il secret di amministratore
(prefisso tenax-) si trova nel namespace del target e richiede CREATE DATABASE.
4. Download¶
--wait stampa un URL prefirmato verso un dump decifrato e ricompresso. È valido per 1 ora. L'URL è un segreto:
condividilo come tale.
5. Sul posto (ultima risorsa)¶
tenax restore team/app --at 2026-01-02T03:04:05Z --to in-place --confirm app --credentials-secret tenax-admin --wait
- Prima ferma chi scrive. Tenax non ferma le applicazioni. Scalale a zero o mettile in modalità manutenzione.
- Tenax esegue un backup di sicurezza dello stato attuale (motivo
safety). Per saltarlo serve--skip-safety-backup. - Ripristina in una sandbox di staging, controlla il risultato, poi sostituisce i database del target.
- Riavvia le applicazioni e controllale.
Se qualcosa va storto, il backup di sicurezza è una normale versione del target: ripristinalo allo stesso modo.
Senza la CLI¶
La risorsa Restore è l'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 mostra l'avanzamento: piano, download della base, replay,
controlli, Succeeded.
Quando Tenax stesso non è disponibile¶
Lo store è la fonte di verità, e il formato dei backup è semplice:
- manifest.json elenca ogni oggetto con dimensione e SHA-256.
- Gli oggetti sono compressi con zstd e cifrati con age: age -d -i key.txt obj.zst.age | zstd -d.
- I backup fisici di Postgres sono stream tar di pg_basebackup più segmenti WAL.
- I backup logici di Postgres sono file pg_dump -Fc, uno per database.
- I backup di MySQL sono l'output di mysqldump più i file binlog.
Dopo la perdita o la ricostruzione di un cluster¶
Il recupero è automatico. Tenax non ha un database proprio: lo store contiene ogni backup (ed è l'unica copia che conta), Git contiene il BackupStore, le policy e i target (GitOps), e le identità age sono secret che ripristini come qualsiasi altro. Installa Tenax sul nuovo cluster con lo stesso store e le stesse identità, e applica gli stessi target. Poi:
- All'avvio il controller controlla ogni store (
BackupStore.status.lastImportTime). Per ogni target ricrea gli oggetti Backup deikeepBackupObjectsbackup più recenti (predefinito 20), blocchi compresi. Nello store non viene scritto nulla. I backup più vecchi restano nello store, soggetti alla conservazione, e nel catalogo della console. - Ripristini, finestre PITR e console funzionano come prima. Lo streamer avvia una nuova catena da un nuovo backup completo.
L'importazione viene eseguita anche quando i target cambiano e ogni controller.autoImport.interval (1 h).
Disattivala con controller.autoImport.enabled: false. tenax catalog import [--dry-run] fa lo stesso a mano,
usando il tuo kubeconfig.