Aller au contenu principal

Sauvegarde et restauration de 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 prenant automatiquement des sauvegardes complètes et incrémentielles planifiées : il n'y a pas de tâche cron distincte à configurer.

Les sauvegardes sont :

  • Cohérentes au niveau applicatif : prises via le mécanisme natif FREEZE de ClickHouse (liens physiques zéro-copie), et non un instantané 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/manifestes 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émentielles 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 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 chaque lien physique qui pointe vers elles. Modifier les permissions sur un fichier situé sous le chemin de sauvegarde les modifie aussi sur les données en direct que ClickHouse lit et écrit 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 exclusivement.

Configuration du sidecar de sauvegarde

Un sidecar de sauvegarde est configuré par défaut sur le pod ClickHouse, via clickhouse-server.sidecars : le mécanisme du chart pour ajouter un conteneur supplémentaire aux côtés des volumes que ClickHouse lui-même utilise. Il exécute clickhouse-backup en mode server --watch, qui auto-planifie les sauvegardes complètes et incrémentielles en interne ; il n'y a pas de tâche cron distincte, et rien d'autre à déployer.

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. Cela se divise en deux parties, toutes deux spécifiques au fournisseur : les paramètres non sensibles (bucket/conteneur, région, chemin) vont sous clickhouse.backupConfig (voir Paramètres ajustables ci-dessous pour le reste de cette map), tandis que les identifiants (lorsqu'une clé statique est requise) sont transmis via un secret Kubernetes créé séparément, jamais en ligne dans votre fichier de valeurs (le même schéma décrit dans Prérequis). Le bucket cible est défini indépendamment du propre bucket de données de ClickHouse (voir Backends d'object storage) : utilisez un bucket réellement distinct, pas seulement un préfixe différent dans le même (voir le conseil dans cette section pour comprendre pourquoi). Choisissez votre fournisseur ci-dessous.

clickhouse:
backupConfig:
REMOTE_STORAGE: 's3'
S3_BUCKET: '<bucket-name>'
S3_REGION: '<region>'
S3_PATH: 'backups/metadata'
S3_OBJECT_DISK_PATH: 'backups/objects'

Bucket cible : S3_BUCKET. Aucune entrée d'identifiant nécessaire : avec IRSA (voir Backends d'object storage), le token du ServiceAccount est automatiquement monté dans chaque conteneur du pod, y compris ce sidecar.

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 (versionnage, Object Lock, réplication, mises en garde sur la couche d'archivage) et la sous-section ClickHouse data bucket pour le propre bucket de données de ClickHouse. Les deux ont besoin de règles différentes, parfois opposées.

Paramètres ajustables

Au-delà de la destination de l'object storage ci-dessus, une poignée d'autres paramètres du sidecar sont exposés sous la même map clickhouse.backupConfig, avec des valeurs par défaut raisonnables prêtes à l'emploi : ne remplacez que ceux que vous devez modifier, sans redéclarer toute la spécification du sidecar :

clickhouse:
backupConfig:
BACKUPS_TO_KEEP_REMOTE: '30' # only overriding retention here
ParamètreObjectifValeur par défaut
WATCH_SCHEDULESPlanning des sauvegardes complètes/incrémentielles 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
BACKUPS_TO_KEEP_REMOTENombre 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
REBASE_BEFORE_REMOVE_OLD_REMOTESans cela, BACKUPS_TO_KEEP_REMOTE n'est pas une limite stricte : avec les chaînes incrémentielles, 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 alors être supprimée, maintenant une rétention stricte.true
UPLOAD_CONCURRENCYTables 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
DOWNLOAD_CONCURRENCYIdentique à UPLOAD_CONCURRENCY, pour la restauration.2
S3_CONCURRENCYChunks parallèles pour le transfert multipart S3 d'un seul fichier, un niveau plus granulaire que UPLOAD_CONCURRENCY/DOWNLOAD_CONCURRENCY.2
REBASE_CONCURRENCYTables traitées en parallèle pendant une opération de rebase (voir full_type=rebase ci-dessous).2
LOG_LEVELVerbosité des logs du sidecar.info
ALLOW_EMPTY_BACKUPSSans cela, une nouvelle installation sans table encore présente est traitée comme une erreur fatale, entraînant un crash-loop du sidecar.true

Les paramètres de concurrence prennent 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 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.

Quelques autres paramètres sont déjà configurés par le chart avec des valeurs par défaut raisonnables et ne sont pas exposés pour être remplacés ; voir la propre référence de configuration de clickhouse-backup pour la liste exhaustive des paramètres disponibles.

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éRequisSignification
nameOuiPréfixe des 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émentielle. Omettez pour des sauvegardes complètes uniquement.
full_typeNon (create)create re-téléverse toutes les données à 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 revient toujours à create.
delete_previous_cycleNon (false)true supprime chaque sauvegarde plus ancienne de cette chaîne dès qu'une nouvelle sauvegarde complète réussit, ne conservant que le cycle actuel. false laisse les cycles plus anciens en place, élagués uniquement par BACKUPS_TO_KEEP_REMOTE 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 des descripteurs de style @every/@daily.

La valeur par défaut du chart :

clickhouse:
backupConfig:
WATCH_SCHEDULES: '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 pas de re-téléversement) et une sauvegarde incrémentielle chaque jour à 2h du matin. Le dimanche, les expressions cron full et increment se déclenchent au même tick : la sauvegarde complète est toujours prioritaire, donc aucun incrément distinct ne s'exécute ce jour-là.

Fenêtre de rétention : avec delete_previous_cycle: false, BACKUPS_TO_KEEP_REMOTE 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), BACKUPS_TO_KEEP_REMOTE: '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 propres tables système de ClickHouse. Considérez une sauvegarde comme défaillante si aucune sauvegarde complète valide n'existe dans votre objectif de point de reprise, ou si aucune nouvelle sauvegarde n'a été prise récemment.

La santé du conteneur ne reflète pas la santé des sauvegardes

La boucle de surveillance du sidecar réessaie une sauvegarde échouée au prochain tick planifié 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 nombre de redémarrages restent au vert tout du long. Voir Surveillance et alertes ClickHouse pour mettre en place un signal externe qui, lui, détecte cela.

Restauration

La restauration des 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 parties de données 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 flux de restauration vers une instance vide séparée sans mettre en place un second déploiement ClickHouse complet.

Procédure de haut niveau :

  1. Faites d'abord un instantané 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. Vous obtenez 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 cassée, 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> récupère uniquement le schéma et les métadonnées (léger, sans 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 sur la ou les tables affectées : mettez en pause ou réduisez l'échelle des producteurs qui écrivent dedans.
  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 la copie mappée 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 réattache depuis la sauvegarde.

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

Piège 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 depuis un état local périmé et ne restaurer que le schéma (DDL), 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 chaque fonctionnalité

Certaines fonctionnalités qui utilisent ClickHouse joignent également ces données avec des informations stockées dans PostgreSQL (par exemple, un inventaire des machines qui appartiennent à votre organisation). Restaurer ClickHouse seul, dans un environnement dont le 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) ou d'objectif de temps de reprise (RTO) fixe 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 définir votre cadence de sauvegarde (fréquence des sauvegardes complètes et incrémentielles) pour correspondre à la fenêtre de perte de données que vous êtes prêt à accepter.