Aller au contenu principal

Stockage ClickHouse

Le stockage de ClickHouse se divise en trois parties :

  • Stockage objet : le bucket que vous fournissez (compatible S3, Azure Blob Storage ou GCS), qui contient les données de table réelles. C'est là que réside l'essentiel de l'empreinte de stockage.
  • Cache du système de fichiers : un volume persistant local agissant comme un cache LRU devant le stockage objet, pour des lectures rapides des données récemment consultées (le même modèle que celui utilisé par ClickHouse Cloud).
  • Métadonnées : un volume persistant local distinct contenant la structure des tables et les manifestes de parties pour les données conservées dans le stockage objet.

Cette page présente d'abord les deux volumes locaux, puis les backends de stockage objet et leur configuration.

Volumes persistants locaux

Les volumes de métadonnées et de cache sont tous deux provisionnés localement, indépendamment de votre backend de stockage objet, et maintenus séparés l'un de l'autre : comme le montre le diagramme ci-dessus, ClickHouse écrit dans les deux, mais seul le cache communique avec le stockage objet.

Volume de métadonnées

Le chart provisionne déjà le volume de métadonnées via persistence (enabled, 20Gi, ReadWriteOnce), monté au niveau du répertoire de données de ClickHouse, où il contient la structure des tables et les manifestes de parties pour les données conservées dans le stockage objet. Dans vos values, vous définissez uniquement la classe de stockage (le chart la laisse indéfinie, donc la StorageClass par défaut de votre cluster s'applique, laquelle peut ne pas être basée sur SSD) et, si nécessaire, vous ajustez la taille :

clickhouse-server:
persistence:
storageClass: gp3 # set an SSD/NVMe-backed class, see Storage class below
size: 20Gi # optional; defaults to 20Gi, see Metadata volume sizing below

La size est indicative, voir Volume de métadonnées pour des conseils de dimensionnement ; contrairement au cache, son empreinte augmente à peine avec le volume de données.

Cache du système de fichiers

Provisionné comme un second volume distinct via extraVolumeClaimTemplates + extraVolumeMounts, monté sur /cache, maintenu séparé du volume de métadonnées afin qu'un cache plein ne prive pas le disque de métadonnées (et vice versa). Pointez le <path> du disque de cache de votre backend de stockage objet vers ce montage (indiqué dans la configuration de chaque backend ci-dessous) :

clickhouse-server:
extraVolumeClaimTemplates:
- metadata:
name: cache
spec:
accessModes:
- ReadWriteOnce
storageClassName: gp3 # adapt to your provider, use an SSD/NVMe-backed class, see Storage class below
resources:
requests:
storage: 50Gi # must stay above CACHE_MAX_SIZE (see Filesystem cache below); 50Gi pairs with the chart's default 48Gi
extraVolumeMounts:
- name: cache
mountPath: /cache

Le storage ci-dessus est indicatif, voir Cache du système de fichiers pour des conseils de dimensionnement : il doit seulement contenir votre ensemble de travail, pas l'intégralité de votre jeu de données, et doit être dimensionné au-dessus de CACHE_MAX_SIZE.

Classe de stockage

Utilisez la même classe de stockage pour les deux volumes : un IOPS élevé est requis à la fois pour les métadonnées et pour le cache :

ClasseExemplesNotes
SSD attaché au réseau (recommandé)AWS EBS gp3 / io2, Azure Premium SSD (Premium_LRS), GCP pd-ssd / pd-balancedSurvit à la perte ou au reschedule d'un nœud : le volume suit le pod vers un nouveau nœud.
NVMe localAWS instance store (types d'instance i3 / i4i), une StorageClass local-volume on-premOption la plus rapide, mais rattachée au nœud sur lequel elle a été provisionnée, voir l'avertissement ci-dessous.
Non supportéClasse HDD (st1 / sc1, pd-standard, Standard HDD), systèmes de fichiers réseau (NFS, EFS, Azure Files, Filestore)La latence est incompatible avec les modèles de lecture/écriture de ClickHouse.
Le NVMe local rattache le pod à son nœud

Une StorageClass local-path lie le volume au nœud spécifique sur lequel il a été provisionné : contrairement au stockage attaché au réseau, il ne peut pas simplement suivre le pod vers un nœud différent. Si l'autoscaler de votre cluster consolide ou draine ce nœud, le pod ne peut pas être reschedulé sans perdre le volume. Si vous utilisez du NVMe local, empêchez votre autoscaler de perturber le nœud (voir Stabilité du nœud), et prévoyez une restauration depuis une sauvegarde plutôt que d'espérer un simple reschedule si le nœud est perdu malgré tout.

Backends de stockage objet

ClickHouse stocke ses données de table sur un bucket de stockage objet que vous fournissez. Chaque fournisseur ci-dessous dispose d'un unique chemin d'authentification supporté : sans identifiants sur AWS S3 et Azure (aucune clé statique à créer, stocker ou faire tourner), et identifiants statiques access-key/secret-key sur GCS et MinIO : GCS parce que l'accès sans identifiants n'est pas possible pour le disque propre à ClickHouse (voir l'onglet GCS pour comprendre pourquoi), MinIO parce qu'il n'a de toute façon aucun fournisseur d'identité cloud avec lequel se fédérer.

Utilisez un bucket dédié, et un bucket séparé pour les sauvegardes

Utilisez un bucket dédié à ClickHouse : ne le partagez pas avec des données sans rapport. Le sidecar de sauvegarde écrit également dans son propre bucket : utilisez pour lui un bucket véritablement séparé, pas seulement un préfixe différent à l'intérieur du bucket de données propre à ClickHouse. Un bucket partagé signifie qu'une seule défaillance (une mauvaise politique de cycle de vie, un identifiant surprivilégié, une suppression accidentelle) peut détruire à la fois vos données actives et vos sauvegardes, réduisant à néant l'intérêt même d'avoir une sauvegarde.

Accès réseau sortant

Si votre cluster restreint le trafic sortant (NetworkPolicies, un pare-feu ou proxy sortant), ClickHouse et le sidecar de sauvegarde ont tous deux besoin d'un accès sortant vers votre endpoint de stockage objet. Avec une configuration sans identifiants, ils doivent aussi atteindre l'endpoint d'échange de token d'identité de votre fournisseur cloud pour échanger le token projeté contre des identifiants à courte durée de vie : AWS STS (sts.amazonaws.com, ou l'endpoint STS de votre région) pour IRSA, Microsoft Entra ID (login.microsoftonline.com) pour Workload Identity.

Politiques de cycle de vie des buckets

Le bucket de données propre à ClickHouse et le bucket du sidecar de sauvegarde nécessitent des règles de cycle de vie et des protections différentes, par endroits opposées. Les deux sont traités ici. Lisez la sous-section correspondant à chaque bucket que vous configurez.

Bucket de données ClickHouse

N'appliquez pas au bucket (ou préfixe) qui sous-tend un disque ClickHouse une règle de cycle de vie qui transitionne ou expire des objets : ClickHouse s'attend à ce que chaque objet qu'il a écrit reste immédiatement lisible indéfiniment. Une transition vers un niveau de stockage d'archivage (S3 Glacier/Deep Archive et équivalents, y compris les niveaux Archive Access optionnels de S3 Intelligent-Tiering) rend l'objet illisible jusqu'à sa restauration, ce qui peut empêcher ClickHouse de démarrer ou provoquer des erreurs lors de la lecture des parties existantes ; une règle d'expiration supprime des données que ClickHouse s'attend encore à trouver, risquant une perte de données. Seul ClickHouse lui-même (via TTL / DROP PARTITION) ou un administrateur informé devrait jamais supprimer ces objets.

La seule règle de cycle de vie qui est sûre : abandonner les uploads multipart incomplets après quelques jours. Cela nettoie uniquement les fragments d'upload orphelins laissés par des uploads interrompus (jamais des données actives), et les empêche de s'accumuler inaperçus dans votre bucket.

N'ajoutez pas non plus de versioning ou d'Object Lock à ce bucket

ClickHouse supprime et réécrit des objets en continu dans le cadre de son fonctionnement normal (merges, TTL, DROP PARTITION). Aucun des deux n'apporte de réel bénéfice de reprise après sinistre ici (c'est le rôle du bucket de sauvegarde), et tous deux nuisent au contraire au fonctionnement normal : le versioning accumule des marqueurs de suppression sans plan de purge propre, et l'Object Lock bloque purement et simplement les suppressions légitimes de ClickHouse lui-même, pas seulement les suppressions accidentelles.

Bucket de sauvegarde

La même règle fondamentale que pour le bucket de données s'applique également ici, pour la même raison : ne laissez pas une règle de cycle de vie transitionner ou expirer des objets que clickhouse-backup gère encore. Il suit sa propre rétention (BACKUPS_TO_KEEP_REMOTE) et ses dépendances de chaîne (REBASE_BEFORE_REMOVE_OLD_REMOTE, voir Paramètres ajustables) directement, et s'attend à ce que chaque sauvegarde dans cette fenêtre reste immédiatement lisible et soit supprimée selon ses propres termes, pas ceux de S3. Une règle d'expiration externe supprime des sauvegardes qu'il s'attend encore à trouver ; une transition vers un niveau d'archivage peut casser la copie côté serveur d'un rebase depuis une chaîne plus ancienne encore référencée. La même règle d'abandon multipart ci-dessus est également sûre ici.

Au-delà de cette base, ce bucket existe spécifiquement pour survivre à un sinistre qui détruit le bucket propre à ClickHouse, donc le durcir davantage justifie le coût et la complexité supplémentaires qui ne se justifient pas sur le bucket de données :

  • Versioning : recommandé. Défense en profondeur contre un identifiant compromis ou un bug supprimant purement et simplement des sauvegardes, en plus de la logique de rétention propre à clickhouse-backup.
  • Object Lock (mode Governance ou Compliance) : cela en vaut la peine si vous avez une exigence de protection contre les ransomwares ou de conformité à satisfaire, mais définissez la période de rétention plus courte que votre fenêtre BACKUPS_TO_KEEP_REMOTE effective. Sinon, il bloque aussi l'élagage de routine propre à clickhouse-backup, pas seulement les suppressions malveillantes. Nous n'avons pas vérifié comment il gère une suppression bloquée, donc l'objectif de conception sûr est que les deux fenêtres n'entrent jamais réellement en collision.
  • Réplication inter-région ou inter-compte : recommandée pour une véritable posture de reprise après sinistre. Un bucket séparé protège déjà contre une mauvaise configuration ou un identifiant partagés ; le répliquer protège en outre contre la perte du compte ou de la région où il réside.
  • Transition vers un niveau d'archivage : sûre uniquement pour les sauvegardes que vous avez explicitement exportées hors du chemin suivi propre à clickhouse-backup (une copie manuelle vers un bucket ou préfixe qu'il ne gère pas). Ne transitionnez jamais les objets à l'intérieur du bucket ou préfixe qu'il gère activement : la même hypothèse de disponibilité en lecture qui exclut cela sur le bucket de données s'applique ici.

Configuration

Sur AWS EKS, ClickHouse s'authentifie auprès de S3 via les IAM Roles for Service Accounts (IRSA) : il n'y a aucune clé d'accès à créer, stocker ou faire tourner. Cela nécessite :

  1. Un fournisseur d'identité IAM OIDC enregistré pour votre cluster EKS (la plupart des clusters EKS en ont déjà un pour d'autres workloads) ; voir la documentation AWS sur les IAM roles for service accounts si vous devez en configurer un.
  2. Un ServiceAccount Kubernetes dédié à ClickHouse, créé par le chart, annoté avec un ARN de rôle IAM.
  3. Un rôle IAM qui fait confiance au fournisseur OIDC de votre cluster, restreint à ce ServiceAccount.
  4. Une politique de permissions n'accordant que l'accès S3 dont ClickHouse et son sidecar de sauvegarde ont besoin.

Configuration du chart : créez un ServiceAccount dédié à ClickHouse et annotez-le avec l'ARN du rôle :

clickhouse-server:
serviceAccount:
annotations:
eks.amazonaws.com/role-arn: 'arn:aws:iam::<account-id>:role/<role-name>'

Politique de confiance : restreinte au ServiceAccount ci-dessus (remplacez <account-id>, <oidc-provider-url> et <namespace>) :

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::<account-id>:oidc-provider/<oidc-provider-url>"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"<oidc-provider-url>:sub": "system:serviceaccount:<namespace>:clickhouse",
"<oidc-provider-url>:aud": "sts.amazonaws.com"
}
}
}
]
}

Politique de permissions : restreinte au bucket dédié à ClickHouse :

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["s3:ListBucket", "s3:GetBucketLocation", "s3:ListBucketMultipartUploads"],
"Resource": [
"arn:aws:s3:::<bucket-name>",
"arn:aws:s3:::<backup-bucket-name>"
]
},
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject",
"s3:AbortMultipartUpload",
"s3:ListMultipartUploadParts"
],
"Resource": [
"arn:aws:s3:::<bucket-name>/*",
"arn:aws:s3:::<backup-bucket-name>/*"
]
}
]
}
astuce

Restreignez la politique au bucket propre à ClickHouse et, puisque IRSA attribue un seul rôle à l'ensemble du pod, également au bucket de sauvegarde séparé (voir le conseil ci-dessus) : la politique accorde lecture/écriture/suppression sur les deux, donc aucun ne devrait être partagé avec des données sans rapport. <bucket-name> doit correspondre à celui que vous définissez dans le <endpoint> du disque ci-dessous ; <backup-bucket-name> est celui que vous définirez dans la configuration de destination propre au sidecar de sauvegarde (voir Sauvegarde et restauration).

Une fois le ServiceAccount en place, la configuration du disque utilise les identifiants fournis par l'environnement : aucun extraEnvVars nécessaire, puisque le token IRSA du ServiceAccount est automatiquement monté dans chaque conteneur du pod, y compris le sidecar de sauvegarde. Vous devez seulement déclarer le disque brut lui-même, nommé object_disk ; le cache du système de fichiers devant lui, et la politique de stockage qui y place les nouvelles tables, sont déjà configurés par le chart :

clickhouse-server:
configdFiles:
00-object-storage.xml: |
<clickhouse>
<storage_configuration>
<disks>
<default>
<!-- 1 GiB, refuse writes below this threshold so the local metadata disk never fills to 100% -->
<keep_free_space_bytes>1073741824</keep_free_space_bytes>
</default>
<object_disk>
<type>s3</type>
<endpoint>https://<bucket-name>.s3.<region>.amazonaws.com/<namespace>/</endpoint>
<use_environment_credentials>true</use_environment_credentials>
</object_disk>
</disks>
</storage_configuration>
</clickhouse>
Nommez le fichier de sorte qu'il soit trié avant object-cache.xml

ClickHouse charge les fichiers config.d dans l'ordre alphabétique, et la configuration de cache propre au chart (object-cache.xml) s'attend à ce que le disque object_disk ci-dessus existe déjà au moment où elle est analysée. Nommez votre fichier 00-object-storage.xml, comme indiqué ci-dessus ; tout nom qui se trie avant object-cache.xml fonctionne, mais c'est la convention utilisée tout au long de cette page.

Bucket cible : défini par la portion <bucket-name> de l'URL <endpoint> ci-dessus : c'est le bucket de données propre à ClickHouse, indépendant du bucket dans lequel écrit le sidecar de sauvegarde.

Identifiants

AWS S3 et Azure s'authentifient sans identifiants par défaut (respectivement IRSA et Microsoft Entra Workload ID, voir les onglets ci-dessus), il n'y a donc aucun secret à longue durée de vie à stocker dans votre cluster pour l'un ou l'autre. GCS et MinIO sont les exceptions : le disque propre à ClickHouse a toujours besoin d'une paire access-key/secret-key statique pour les deux, quelle que soit la configuration d'identité du cluster : GCS parce que le client S3 de ClickHouse ne peut pas consommer un token fédéré (voir l'onglet GCS), MinIO parce qu'il n'a de toute façon aucun fournisseur d'identité cloud avec lequel se fédérer. Cet identifiant statique est transmis de la même manière que les autres configurations sensibles de GitGuardian, voir Gestion des informations sensibles Helm.