Aller au contenu

Restaurer avec Tenax

Chaque restauration est une ressource Restore. La console, la CLI et l'API en créent toutes une. Une restauration n'écrit jamais dans une base existante, sauf si vous demandez sur place et tapez le nom de la cible. Choisissez le mode :

Besoin Mode Rôle
Consulter des données, vérifier un correctif, produire un rapport bac à sable (par défaut) operator
Récupérer une table ou quelques lignes bac à sable, puis copier ce dont vous avez besoin operator
Une copie à côté de la production (nouveau nom de base) nouvelle base restorer
Un fichier de dump pour quelqu'un hors du cluster téléchargement (URL présignée, 1 h) restorer
Ramener toute la cible en arrière sur place (après une sauvegarde de sécurité) restorer-admin

1. Trouver le point

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

Dans la console, ouvrez la cible, puis Modifications. Chaque ligne de segment a des liens « sandbox before » et « sandbox after » qui remplissent l'instant pour vous.

Avec la PITR, n'importe quelle seconde d'une fenêtre convient (UTC, RFC3339) : --at 2026-01-02T03:04:05Z. Sans PITR, choisissez un identifiant de sauvegarde : --at 20260102T020000Z-1a2b3c. Si l'instant n'est pas restaurable, Tenax explique pourquoi et affiche les fenêtres.

2. Restaurer dans un bac à sable (sûr, par défaut)

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
  • Le bac à sable reçoit son propre namespace tenax-sbx-<name>, des identifiants aléatoires et un TTL (24 h par défaut ; prolongez avec tenax sandbox extend <sandbox> --by 24h, jusqu'au maximum de la politique).
  • La console de requêtes est en lecture seule par défaut, avec un délai de 30 s et une limite de 1 000 lignes. Les colonnes qui correspondent aux motifs mask de la cible sont masquées. Chaque requête est auditée.
  • Depuis un autre pod : donnez-lui le label tenax.run/sandbox-client: <sandbox> et connectez-vous à l'adresse interne au cluster qu'affiche sandbox show.
  • Depuis un poste, si le bac à sable a été créé avec --expose : tenax sandbox connect <sandbox> --port 15432. Cela ouvre le tunnel via Cloudflare Access et affiche la chaîne de connexion.
  • tenax sandbox delete <sandbox> une fois terminé. Les bacs à sable expirés sont supprimés automatiquement.

3. Restaurer dans une nouvelle base

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 restaure d'abord dans un bac à sable intermédiaire, exécute les contrôles, puis copie le résultat dans la nouvelle base par un dump et un chargement logiques (ADR 0007). Il n'écrase jamais une base existante. Le secret administrateur (préfixe tenax-) se trouve dans le namespace de la cible et doit disposer de CREATE DATABASE.

4. Téléchargement

tenax restore team/app --at <backup-id> --to download --wait

--wait affiche une URL présignée vers un dump déchiffré et recompressé. Elle est valable 1 heure. L'URL est un secret : partagez-la comme tel.

5. Sur place (en dernier recours)

tenax restore team/app --at 2026-01-02T03:04:05Z --to in-place --confirm app --credentials-secret tenax-admin --wait
  1. Arrêtez d'abord les écritures. Tenax n'arrête pas les applications. Réduisez-les à zéro, ou passez-les en mode maintenance.
  2. Tenax prend une sauvegarde de sécurité de l'état actuel (raison safety). L'ignorer exige --skip-safety-backup.
  3. Il restaure dans un bac à sable intermédiaire, contrôle le résultat, puis remplace les bases de la cible.
  4. Redémarrez les applications et vérifiez-les.

Si quelque chose tourne mal, la sauvegarde de sécurité est une version normale de la cible : restaurez-la de la même façon.

Sans la CLI

La ressource Restore est 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 affiche la progression : planification, récupération de la base, rejeu, contrôles, Succeeded.

Quand Tenax lui-même est en panne

Le store est la source de vérité, et le format de sauvegarde est simple : - manifest.json liste chaque objet avec sa taille et son SHA-256. - Les objets sont compressés avec zstd et chiffrés avec age : age -d -i key.txt obj.zst.age | zstd -d. - Les sauvegardes physiques Postgres sont des flux tar pg_basebackup plus des segments WAL. - Les sauvegardes logiques Postgres sont des fichiers pg_dump -Fc, un par base. - Les sauvegardes MySQL sont la sortie de mysqldump plus des fichiers binlog.

Après la perte ou la reconstruction d'un cluster

La reprise est automatique. Tenax ne tient aucune base de données à lui : le store contient chaque sauvegarde (et c'est la seule copie qui compte), Git contient le BackupStore, les politiques et les cibles (GitOps), et les identités age sont des secrets que vous restaurez comme les autres. Installez Tenax sur le nouveau cluster avec le même store et les mêmes identités, et appliquez les mêmes cibles. Ensuite :

  1. Le contrôleur vérifie chaque store au démarrage (BackupStore.status.lastImportTime). Pour chaque cible, il recrée les objets Backup des keepBackupObjects sauvegardes les plus récentes (20 par défaut), épingles comprises. Rien n'est écrit dans le store. Les sauvegardes plus anciennes restent dans le store, soumises à la rétention, et dans le catalogue de la console.
  2. Les restaurations, les fenêtres PITR et la console fonctionnent comme avant. Le streamer démarre une nouvelle chaîne à partir d'une sauvegarde complète neuve.

L'import s'exécute aussi quand les cibles changent, et toutes les controller.autoImport.interval (1 h). Désactivez-le avec controller.autoImport.enabled: false. tenax catalog import [--dry-run] fait la même chose à la main, avec votre kubeconfig.