Aller au contenu principal

Sauvegarde et restauration ClickHouse

Fonctionnement de la sauvegarde ClickHouse​

Un sidecar de sauvegarde s'exécute aux côtés de ClickHouse, surveillant en continu les changements et réalisant automatiquement des sauvegardes complètes et incrémentales planifiées : il n'y a pas de tâche cron distincte à configurer.

Les sauvegardes sont :

  • Cohérentes au niveau applicatif : réalisées via le mécanisme natif FREEZE de ClickHouse (hardlinks sans copie), et non un snapshot brut de volume, de sorte qu'une sauvegarde ne capture jamais une table en cours d'écriture.
  • Écrites dans votre object storage : à la fois les métadonnées/manifests et les blobs de données sous-jacents sont copiés dans votre bucket configuré, sous le préfixe de chemin que vous configurez ci-dessous.
  • Dédupliquées et conscientes des chaînes : les sauvegardes incrémentales ne stockent que ce qui a changé ; les politiques de rétention suppriment des chaînes de sauvegarde entières plutôt que de laisser des incréments orphelins.
Ne modifiez jamais les permissions sur le chemin de sauvegarde local

FREEZE fonctionne en créant des liens physiques (hard links) vers les données de table en direct, et non des copies. Les permissions, la propriété et les attributs d'un lien physique sont une propriété des données sous-jacentes elles-mêmes : ils sont partagés entre tous les liens physiques qui pointent vers elles. Modifier les permissions d'un fichier sous le chemin de sauvegarde les modifie aussi sur les données en direct que ClickHouse est en train de lire et d'écrire activement, ce qui peut entraîner une corruption des données. Ne touchez jamais manuellement aux permissions à cet endroit ; laissez ClickHouse et le sidecar de sauvegarde gérer ce chemin de manière exclusive.

Configuration du sidecar de sauvegarde​

Un sidecar de sauvegarde est configuré par défaut sur le pod ClickHouse, contrôlé par clickhouse.backup.enabled (true par défaut). Il exécute clickhouse-backup en mode server --watch, qui auto-planifie les sauvegardes complètes et incrémentales dans le processus ; il n'y a pas de tâche cron distincte, ni rien d'autre à déployer. Ne définissez clickhouse.backup.enabled: false que si vous avez l'intention de gérer entièrement le sidecar vous-même via clickhouse.sidecars à la place.

Destination de l'object storage​

La destination de sauvegarde n'a aucune valeur par défaut : vous devez la configurer avant que les sauvegardes puissent s'exécuter. Elle est déclarée sous clickhouse.backup.objectStorage, avec la même structure et le même vocabulaire que le bucket de données propre à ClickHouse sous clickhouse.objectStorage (voir Backends d'object storage) : un provider plus un bloc de fournisseur portant le bucket/conteneur, un prefix facultatif, et soit credentialless: true (workload identity, sans clé statique) soit une référence existingSecret. Les identifiants ne vivent jamais que dans un secret Kubernetes que vous créez séparément, jamais en ligne dans votre fichier values (le même modèle décrit dans Prérequis) ; le chart refuse les clés d'identifiants dans extraVars.

Le chart dérive les deux chemins de stockage à partir de l'unique prefix : les manifests de sauvegarde arrivent sous <prefix>/metadata et les copies des blobs de données du disque objet sous <prefix>/objects.

Seule la structure est partagée avec le bucket de données, jamais les valeurs : utilisez un bucket véritablement distinct (voir Exigences du bucket). Le chart l'impose et fait échouer le déploiement si la sauvegarde cible le bucket ou le conteneur contenant les données qu'elle protège. Choisissez votre fournisseur ci-dessous.

clickhouse:
backup:
objectStorage:
provider: s3
s3:
bucket: '<bucket-name>'
region: '<region>'
prefix: 'backups'
credentialless: true

Bucket cible : s3.bucket. Aucune entrée d'identifiant nécessaire avec credentialless: true : avec IRSA (voir Backends d'object storage), le token du ServiceAccount est automatiquement monté dans chaque conteneur du pod, y compris ce sidecar. Avec des clés statiques à la place, définissez credentialless: false et faites pointer existingSecret vers un secret portant les clés access-key-id et secret-access-key (la même forme que le secret du bucket de données, avec ses propres identifiants distincts).

Politiques de cycle de vie du bucket​

Les règles de cycle de vie et les protections de bucket pour les deux buckets sont documentées ensemble dans Politiques de cycle de vie du bucket : voir la sous-section Backup bucket pour celui-ci (versioning, Object Lock, réplication, mises en garde sur le tier archive) et la sous-section ClickHouse data bucket pour le bucket de données propre à ClickHouse. Les deux ont besoin de règles différentes, par endroits opposées.

Paramètres ajustables​

D'autres paramètres du sidecar disposent d'un champ typé sous clickhouse.backup.config. Ne surchargez que ceux dont vous avez besoin :

clickhouse:
backup:
config:
backupsToKeepRemote: 30 # only overriding retention here
ParamètreObjectifValeur par défaut
watchSchedulesPlanning des sauvegardes complètes/incrémentales piloté par cron, voir Comprendre le planning de sauvegarde ci-dessous.name=ch-bkp,full=0 2 * * 0,increment=0 2 * * *,full_type=rebase,delete_previous_cycle=false
backupsToKeepRemoteNombre de sauvegardes individuelles à conserver dans l'object storage : chaque sauvegarde complète et chaque incrément compte séparément, voir Comprendre le planning de sauvegarde ci-dessous.7
rebaseBeforeRemoveOldRemoteSans cela, backupsToKeepRemote n'est pas un plafond strict : avec les chaînes incrémentales, clickhouse-backup ne supprimera pas une chaîne dont un incrément plus récent dépend encore, de sorte que le nombre conservé peut dépasser la limite. Cela rebase le plus ancien incrément encore dans la fenêtre de rétention sur une sauvegarde complète autonome, le rendant indépendant de la chaîne plus ancienne qui le précède, laquelle peut ensuite être supprimée, maintenant une rétention stricte.true
uploadConcurrencyTables téléversées en parallèle pendant une sauvegarde, et (même valeur) fichiers par table téléversés en parallèle.2
downloadConcurrencyIdentique à uploadConcurrency, pour la restauration.2
s3ConcurrencyChunks parallèles pour le transfert multipart S3 d'un même fichier, un niveau plus fin que uploadConcurrency/downloadConcurrency.2
rebaseConcurrencyTables traitées en parallèle pendant une opération rebase (voir full_type=rebase ci-dessous).2
logLevelVerbosité des logs du sidecar.info
allowEmptyBackupsSans cela, une nouvelle installation sans encore aucune table est traitée comme une erreur fatale, provoquant un crash-loop du sidecar.true

Les paramètres de concurrence utilisent par défaut une valeur fixe et prudente plutôt que l'auto-détection propre à clickhouse-backup, qui se dimensionne sur le nombre total de CPU du nœud plutôt que sur la limite de CPU réelle de ce conteneur : augmentez-les si vous avez donné plus de CPU au sidecar et souhaitez des sauvegardes et restaurations plus rapides.

Tout autre paramètre non sensible de clickhouse-backup va sous clickhouse.backup.config.extraVars, sous son nom natif en SCREAMING_CASE ; voir la référence de configuration propre à clickhouse-backup pour la liste exhaustive. Le chart rejette une clé extraVars qui entre en conflit avec un champ typé ci-dessus (par exemple extraVars.BACKUPS_TO_KEEP_REMOTE) ou avec un champ appartenant à clickhouse.backup.objectStorage (par exemple extraVars.S3_BUCKET) : définissez plutôt le champ dédié. Il rejette aussi purement et simplement les clés d'identifiants (S3_ACCESS_KEY, GCS_CREDENTIALS_JSON, AZBLOB_ACCOUNT_KEY, ...) : extraVars est rendu dans un ConfigMap, pas un secret, de sorte que les identifiants ne passent jamais que par existingSecret (ou votre propre secret via clickhouse.backup.sidecar.extraEnvVarsSecret).

Comprendre le planning de sauvegarde​

WATCH_SCHEDULES pilote la cadence de sauvegarde avec des expressions cron. Un planning a la forme :

name=<name>,full=<cron>[,increment=<cron>][,full_type=create|rebase][,delete_previous_cycle=true|false]
CléRequiseSignification
nameOuiPréfixe pour les noms de sauvegarde de cette chaîne. Vous permet d'exécuter plusieurs plannings indépendants côte à côte, séparés par ;.
fullOuiExpression cron pour la sauvegarde complète.
incrementNonExpression cron pour la sauvegarde incrémentale. Omettez pour des sauvegardes complètes uniquement.
full_typeNon (create)create re-téléverse toutes les données pour chaque sauvegarde complète. rebase effectue à la place une copie côté serveur de la chaîne précédente (pas de re-téléversement, bien plus rapide), mais seulement une fois qu'une sauvegarde précédente existe déjà ; le tout premier cycle retombe toujours sur create.
delete_previous_cycleNon (false)true supprime toutes les sauvegardes plus anciennes de cette chaîne dès qu'une nouvelle sauvegarde complète réussit, ne conservant que le cycle courant. false laisse les cycles plus anciens en place, élagués uniquement par backupsToKeepRemote ci-dessus.

Les expressions cron acceptent la syntaxe standard à 5 champs (minute, heure, jour, mois, jour de la semaine), un champ optionnel de secondes en tête, et les descripteurs de type @every/@daily.

La valeur par défaut du chart :

clickhouse:
backup:
config:
watchSchedules: name=ch-bkp,full=0 2 * * 0,increment=0 2 * * *,full_type=rebase,delete_previous_cycle=false

Cela exécute une sauvegarde complète chaque dimanche à 2h du matin (via rebase une fois qu'une précédente existe, donc sans re-téléversement) et une sauvegarde incrémentale chaque jour à 2h du matin. Le dimanche, les expressions cron full et increment se déclenchent au même tick : la sauvegarde complète a toujours la priorité, de sorte qu'aucun incrément distinct ne s'exécute ce jour-là.

Fenêtre de rétention : avec delete_previous_cycle: false, backupsToKeepRemote conserve les N sauvegardes les plus récentes, comptant chaque sauvegarde complète et chaque incrément comme sa propre entrée. À 7 entrées par semaine (1 complète + 6 incréments), backupsToKeepRemote: 7 conserve environ 1 semaine d'historique.

Fraîcheur des sauvegardes​

La fraîcheur des sauvegardes est exposée dans le produit à l'aide des tables système propres à ClickHouse. Considérez une sauvegarde comme non saine si aucune sauvegarde complète valide n'existe dans votre objectif de point de reprise, ou si aucune nouvelle sauvegarde n'a été réalisée récemment.

La santé du conteneur ne reflète pas la santé de la sauvegarde

La boucle de surveillance du sidecar réessaie une sauvegarde échouée au tick planifié suivant au lieu de s'arrêter : un échec persistant (mauvais identifiants, un bucket inaccessible, un disque plein) enregistre une erreur à chaque tentative mais ne fait jamais planter le conteneur. Le statut du pod et le compteur de redémarrages restent au vert tout du long. Voir Surveillance et alerting ClickHouse pour mettre en place un signal externe qui, lui, détecte cela.

Restauration​

Restaurer les données ClickHouse est une opération manuelle et délibérée : elle n'est pas déclenchée automatiquement. clickhouse-backup restaure sur place, sur la même instance ClickHouse aux côtés de laquelle le sidecar s'exécute : il a besoin d'un accès direct au système de fichiers pour attacher les data parts de la sauvegarde, la même exigence qui le maintient déployé en tant que sidecar en premier lieu (voir Fonctionnement de la sauvegarde ClickHouse ci-dessus). Il n'existe pas de workflow de restauration dans une instance vide distincte sans monter tout un second déploiement ClickHouse.

Procédure de haut niveau :

  1. Faites d'abord un snapshot de l'état actuel : clickhouse-backup create_remote sur la ou les tables affectées, même si ces données sont déjà dégradées. Cela vous donne un repli distinct de votre chaîne de sauvegarde habituelle si la restauration elle-même tourne mal.
  2. Identifiez la sauvegarde à partir de laquelle restaurer : listez les sauvegardes distantes, vérifiez qu'elle n'est pas signalée comme corrompue, et que sa chaîne de sauvegarde est intacte.
  3. Vérifiez la compatibilité des versions avant de vous engager dans une restauration complète : clickhouse-backup download --schema <backup_name> ne récupère que le schéma et les métadonnées (léger, sans les données de table), afin que vous puissiez inspecter clickhouse_version dans le metadata.json résultant par rapport à la version de ClickHouse actuellement en cours d'exécution.
  4. Arrêtez les écritures vers la ou les tables affectées : mettez en pause ou réduisez l'échelle des producteurs qui y écrivent.
  5. Restaurez d'abord sous un nom différent (--restore-database-mapping/--restore-table-mapping), jamais directement dans la table en direct.
  6. Vérifiez la copie restaurée (nombre de lignes, contrôle ponctuel de valeurs connues) avant de toucher à la production.
  7. Basculez : une fois que la copie mappée est validée, restaurez à nouveau directement sur le nom de la table en direct avec --rm (restore/restore_remote --rm <backup_name>) : clickhouse-backup supprime le schéma existant et le rattache depuis la sauvegarde.

Pour simplement tester qu'une sauvegarde fonctionne (et non répondre à un incident réel), restaurez plutôt sous un nom de table ou de base de données jetable, afin qu'un exercice ne touche jamais aux données de production.

Écueil connu : tentatives de restauration répétées

Si vous réessayez une restauration en utilisant le même nom de sauvegarde après une tentative échouée ou interrompue, l'outil de restauration peut reprendre à partir d'un état local obsolète et ne restaurer que le schéma (DDL), en sautant silencieusement les données réelles, sans erreur. Si une restauration semble vide ou incomplète, effacez l'état local de l'outil avant de réessayer, ou utilisez une cible distincte à chaque fois.

Portée de la reprise après sinistre​

Une restauration ClickHouse seule n'est pas une reprise après sinistre complète pour toutes les fonctionnalités

Certaines fonctionnalités qui utilisent ClickHouse joignent aussi ces données à des informations stockées dans PostgreSQL (par exemple, un inventaire des machines qui appartiennent à votre organisation). Restaurer ClickHouse seul, dans un environnement dont PostgreSQL diffère, produit des résultats incohérents dans le produit : les données ClickHouse et le registre PostgreSQL sont en désaccord l'un avec l'autre.

Une reprise après sinistre complète pour ces fonctionnalités nécessite de restaurer à la fois ClickHouse et PostgreSQL à un point cohérent dans le temps. Planifiez votre stratégie de sauvegarde PostgreSQL (voir Sauvegarde et restauration) et votre stratégie de sauvegarde ClickHouse ensemble, et testez une restauration combinée dans le cadre de vos exercices de reprise après sinistre.

Objectifs de reprise​

Nous ne publions pas actuellement d'objectif de point de reprise (RPO) ni d'objectif de temps de reprise (RTO) fixes pour ClickHouse : ceux-ci dépendent de votre cadence de sauvegarde et de votre volume de données. Nous recommandons d'exécuter un exercice de restauration sur votre propre volume de données pour mesurer votre RTO réel, et de régler votre cadence de sauvegarde (fréquence des sauvegardes complètes et incrémentales) pour correspondre à la fenêtre de perte de données que vous êtes prêt à accepter.