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 réelles des tables. C'est là que réside l'essentiel de l'empreinte de stockage.
  • Cache du système de fichiers : un volume persistant local jouant le rôle de 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 parts pour les données conservées dans le stockage objet.

Cette page couvre 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 clickhouse.persistence (enabled, 20Gi, ReadWriteOnce), monté au niveau du répertoire de données de ClickHouse, où il conserve la structure des tables et les manifestes de parts pour les données conservées dans le stockage objet. Dans vos values, vous définissez seulement la storage class (le chart la laisse non définie, de sorte que la StorageClass par défaut de votre cluster s'applique, qui n'est peut-être pas basée sur SSD) et, si nécessaire, ajustez la taille :

clickhouse:
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 recommandations de dimensionnement ; contrairement au cache, son empreinte croît à peine avec le volume de données.

Cache du système de fichiers​

Provisionné nativement via clickhouse.cache, comme un second volume, distinct monté au niveau de /cache, maintenu séparé du volume de métadonnées afin qu'un cache plein n'affame pas le disque de métadonnées (et vice versa). Le chart câble ce volume dans la configuration du disque de stockage objet à votre place (voir Configuration ci-dessous) : vous définissez seulement la storage class et la taille :

clickhouse:
cache:
storageClass: gp3 # adapt to your provider, use an SSD/NVMe-backed class, see Storage class below
size: 50Gi # must stay above cacheMaxSize (see Filesystem cache below); pairs with the chart's auto-derived default

La size ci-dessus est indicative, voir Cache du système de fichiers pour des recommandations de dimensionnement : il n'a besoin de contenir que votre ensemble de travail, pas l'intégralité de votre jeu de données. clickhouse.serverConfig.cacheMaxSize (la limite souple que ClickHouse applique en plus de ce volume) est dérivée automatiquement de cache.size moins une marge de sécurité ; voir Cache du système de fichiers pour la remplacer.

Storage class​

Utilisez la même classe de stockage pour les deux volumes : des IOPS élevés sont requis pour les métadonnées comme 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 reprogrammation 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 épinglée au nœud sur lequel elle a été provisionnée, voir la mise en garde ci-dessous.
Non pris en chargeClasse HDD (st1 / sc1, pd-standard, Standard HDD), systèmes de fichiers réseau (NFS, EFS, Azure Files, Filestore)La latence est incompatible avec les schémas de lecture/écriture de ClickHouse.
Le NVMe local épingle 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 autre nœud. Si l'autoscaler de votre cluster consolide ou draine ce nœud, le pod ne peut pas être reprogrammé 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 de restaurer à partir d'une sauvegarde plutôt que de vous attendre à un simple reprogrammation si le nœud est perdu malgré tout.

Backends de stockage objet​

ClickHouse stocke les données de ses tables sur un bucket de stockage objet que vous fournissez, configuré sous clickhouse.objectStorage. Chaque fournisseur ci-dessous a un seul chemin d'authentification pris en charge : sans identifiants (credentialless: true) sur AWS S3 et Azure (aucune clé statique à créer, stocker ou faire tourner), et des identifiants statiques access-key/secret-key sur GCS, IBM Cloud Object Storage et MinIO.

Exigences relatives aux buckets
  • Deux buckets, un par usage. Donnez à ClickHouse un bucket qui lui est propre, et donnez au sidecar de sauvegarde un bucket réellement distinct.
  • Chiffrement côté serveur sur les deux. Il est transparent pour ClickHouse et le sidecar, donc rien ne change dans le chart. AWS S3, Azure Blob Storage et GCS chiffrent au repos par défaut ; MinIO nécessite sa propre configuration (KES adossé à un KMS). Avec des clés gérées par le client (SSE-KMS et équivalents), l'identité avec laquelle ClickHouse et le sidecar s'authentifient doit aussi être autorisée à utiliser la clé : sur AWS, accordez kms:Decrypt et kms:GenerateDataKey en plus de la politique S3 présentée dans l'onglet AWS S3.
  • Accès sortant. Si votre cluster restreint le trafic sortant, ClickHouse et le sidecar doivent pouvoir atteindre le endpoint du stockage objet, et dans une configuration sans identifiants, également le endpoint d'échange de tokens du fournisseur : AWS STS (sts.amazonaws.com ou le endpoint régional) pour IRSA, Microsoft Entra ID (login.microsoftonline.com) pour Workload Identity.

Politiques de cycle de vie des buckets​

Le propre bucket de données de ClickHouse et le bucket du sidecar de sauvegarde ont besoin de règles de cycle de vie et de protections différentes, parfois opposées. Les deux sont couvertes ici. Lisez la sous-section correspondant à chaque bucket que vous configurez.

Bucket de données ClickHouse​

N'appliquez pas au bucket (ou au préfixe) adossé à 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 parts 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 averti devrait jamais supprimer ces objets.

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

N'ajoutez pas non plus le versioning ou l'Object Lock à ce bucket

ClickHouse supprime et réécrit continuellement des objets dans le cadre de son fonctionnement normal (merges, TTL, DROP PARTITION). Aucun des deux n'apporte ici un réel bénéfice en matière de reprise après sinistre (c'est le rôle du bucket de sauvegarde), et les 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 aussi 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 (backupsToKeepRemote) et ses dépendances de chaîne (rebaseBeforeRemoveOldRemote, voir Paramètres ajustables) directement, et s'attend à ce que chaque sauvegarde à l'intérieur de cette fenêtre reste immédiatement lisible et soit supprimée selon ses propres conditions, pas celles 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 des multipart ci-dessus est également sûre ici.

Au-delà de cette base, ce bucket existe spécifiquement pour survivre à un sinistre qui détruirait le propre bucket de ClickHouse, donc le durcir davantage vaut 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) : utile si vous avez une exigence de protection contre les ransomwares ou de conformité à laquelle vous devez répondre, mais fixez la période de rétention plus courte que votre fenêtre effective backupsToKeepRemote. 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égions ou inter-comptes : recommandée pour une véritable posture de reprise après sinistre. Un bucket distinct protège déjà contre une mauvaise configuration ou un identifiant partagés ; le répliquer davantage protège 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 en dehors du chemin suivi par clickhouse-backup lui-même (une copie manuelle vers un bucket ou un préfixe qu'il ne gère pas). Ne transitionnez jamais les objets à l'intérieur du bucket ou du préfixe qu'il gère activement : la même hypothèse de disponibilité en lecture qui l'exclut sur le bucket de données s'applique ici.

Configuration​

Sur AWS EKS, ClickHouse s'authentifie auprès de S3 à l'aide des 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 charges de travail) ; voir la documentation AWS sur les IAM roles for service accounts si vous devez en configurer un.
  2. Un ServiceAccount Kubernetes dédié pour 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 permission accordant uniquement l'accès S3 dont ClickHouse et son sidecar de sauvegarde ont besoin.

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

clickhouse:
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 permission : 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 propre bucket de ClickHouse et, puisque IRSA attribue un seul rôle à l'ensemble du pod, également au bucket de sauvegarde distinct (voir Exigences relatives aux buckets). <bucket-name> doit correspondre à objectStorage.s3.bucket 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, définissez credentialless: true dans vos values. Il n'y a aucun identifiant statique ni aucun secret à créer :

clickhouse:
objectStorage:
provider: s3
s3:
endpoint: 'https://<bucket-name>.s3.<region>.amazonaws.com'
bucket: '<bucket-name>'
region: '<region>'
credentialless: true

Bucket cible : s3.bucket, indépendant du bucket dans lequel écrit le sidecar de sauvegarde. s3.endpoint doit déjà intégrer le bucket comme sous-domaine, correspondant aux propres URLs virtual-hosted-style d'AWS (la valeur par défaut forcePathStyle: false) ; voir l'onglet MinIO si votre stockage compatible S3 a plutôt besoin d'un endpoint path-style sans bucket.

Identifiants​

AWS S3 et Azure prennent en charge l'authentification sans identifiants (credentialless: true, respectivement adossée à IRSA et Microsoft Entra Workload ID, voir les onglets ci-dessus). GCS, IBM Cloud Object Storage et MinIO sont les exceptions : le propre disque de ClickHouse a toujours besoin d'une paire access-key/secret-key statique, référencée via objectStorage.<provider>.existingSecret, quelle que soit la configuration d'identité du cluster. Cet identifiant statique est transmis de la même manière que les autres configurations sensibles de GitGuardian, voir Gestion des informations sensibles Helm.