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 :
| Classe | Exemples | Notes |
|---|---|---|
| SSD attaché au réseau (recommandé) | AWS EBS gp3 / io2, Azure Premium SSD (Premium_LRS), GCP pd-ssd / pd-balanced | Survit à la perte ou au reprogrammation d'un nœud : le volume suit le pod vers un nouveau nœud. |
| NVMe local | AWS instance store (types d'instance i3 / i4i), une StorageClass local-volume on-prem | Option 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 charge | 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 schémas de lecture/écriture de ClickHouse. |
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.
- 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:Decryptetkms:GenerateDataKeyen 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.comou 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.
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-backuplui-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
- AWS S3
- Azure Blob Storage
- GCS
- IBM Cloud Object Storage
- MinIO
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 :
- 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.
- Un ServiceAccount Kubernetes dédié pour ClickHouse, créé par le chart, annoté avec un ARN de rôle IAM.
- Un rôle IAM qui fait confiance au fournisseur OIDC de votre cluster, restreint à ce ServiceAccount.
- 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>/*"
]
}
]
}
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.
Sur AKS, ClickHouse s'authentifie auprès d'Azure Blob Storage à l'aide de Microsoft Entra Workload ID : le même modèle de fédération OIDC qu'IRSA, sous la nomenclature d'Azure. Cela nécessite :
- Workload Identity et l'émetteur OIDC activés sur votre cluster AKS (sur les clusters AKS Automatic, c'est préconfiguré ; sur AKS Standard, activez-le explicitement).
- Un ServiceAccount Kubernetes dédié pour ClickHouse, créé par le chart, annoté avec le client ID d'une identité gérée, le pod lui-même étant labellisé pour s'inscrire.
- Un federated identity credential liant cette identité gérée à l'émetteur OIDC de votre cluster et au sujet du ServiceAccount.
- Une attribution de rôle Azure RBAC accordant uniquement l'accès Blob Storage dont ClickHouse et son sidecar de sauvegarde ont besoin.
Activez Workload Identity sur le cluster (AKS Standard uniquement, à ignorer sur AKS Automatic) :
az aks update \
--resource-group <resource-group> \
--name <cluster-name> \
--enable-oidc-issuer \
--enable-workload-identity
export AKS_OIDC_ISSUER="$(az aks show --name <cluster-name> \
--resource-group <resource-group> \
--query "oidcIssuerProfile.issuerUrl" --output tsv)"
Créez une identité gérée pour ClickHouse :
az identity create \
--name clickhouse-workload-identity \
--resource-group <resource-group>
export IDENTITY_CLIENT_ID="$(az identity show \
--name clickhouse-workload-identity \
--resource-group <resource-group> \
--query 'clientId' --output tsv)"
Configuration du chart : créez un ServiceAccount dédié pour ClickHouse, annoté avec le client ID de l'identité gérée, et labellisez le pod pour s'inscrire au mutating webhook qui injecte le token fédéré :
clickhouse:
serviceAccount:
annotations:
azure.workload.identity/client-id: '<identity-client-id>'
podLabels:
azure.workload.identity/use: 'true'
Federated identity credential : lie l'identité gérée au sujet du ServiceAccount (remplacez <namespace>) :
az identity federated-credential create \
--name clickhouse-federated-credential \
--identity-name clickhouse-workload-identity \
--resource-group <resource-group> \
--issuer "${AKS_OIDC_ISSUER}" \
--subject system:serviceaccount:<namespace>:clickhouse \
--audience api://AzureADTokenExchange
Attribution de rôle : accordez à l'identité gérée l'accès au compte de stockage, restreint à un conteneur si vous en utilisez un dédié :
az role assignment create \
--assignee-object-id "$(az identity show --name clickhouse-workload-identity \
--resource-group <resource-group> --query principalId --output tsv)" \
--assignee-principal-type ServicePrincipal \
--role "Storage Blob Data Contributor" \
--scope <storage-account-resource-id>
Une fois cela en place, définissez credentialless: true dans vos values. Il n'y a aucune clé de compte statique ni aucun secret à créer :
clickhouse:
objectStorage:
provider: azblob
azblob:
storageAccountUrl: 'https://<storage-account-name>.blob.core.windows.net'
containerName: '<container-name>'
credentialless: true
Bucket cible : l'équivalent Azure d'un bucket est un conteneur au sein d'un compte de stockage, défini ici par storageAccountUrl (le compte) et containerName (le conteneur) ; indépendant du conteneur dans lequel écrit le sidecar de sauvegarde.
ClickHouse n'a pas de type de disque GCS natif : il accède à GCS via son type de disque s3 pointé vers le endpoint d'interopérabilité compatible S3 de GCS (storage.googleapis.com), comme documenté par ClickHouse lui-même. Contrairement à S3 et Azure, c'est le seul chemin d'authentification pris en charge pour le propre disque GCS de ClickHouse : fournissez un bucket GCS et une paire de clés HMAC pour un compte de service ayant accès à celui-ci. L'accès sans identifiants n'est pas possible : GCP n'a aucun échange qui transforme un token Workload Identity Federation en clés HMAC temporaires, et les clés HMAC GCS sont toujours statiques. Le sidecar de sauvegarde utilise plutôt l'API native de GCS et peut s'authentifier via Workload Identity Federation.
Il n'y a pas de mode sans identifiants pour GCS : créez un secret Kubernetes avec la paire de clés HMAC, comme décrit dans Gestion des informations sensibles Helm :
kubectl create secret generic clickhouse-gcs-credentials \
--namespace <namespace> \
--from-literal=access-key-id=<gcs-hmac-access-key-id> \
--from-literal=secret-access-key=<gcs-hmac-secret-access-key>
Puis référencez le secret dans vos values :
clickhouse:
objectStorage:
provider: gcs
gcs:
bucket: '<bucket-name>'
existingSecret: clickhouse-gcs-credentials
Bucket cible : gcs.bucket, indépendant du bucket dans lequel écrit le sidecar de sauvegarde. gcs.endpoint a pour valeur par défaut https://storage.googleapis.com et nécessite rarement d'être remplacé.
Le client GCS de clickhouse-backup n'accepte pas les clés HMAC : il ne lit qu'une clé JSON de compte de service GCP native. Voir Sauvegarde et restauration pour l'identifiant dont le sidecar a besoin en plus de la paire de clés HMAC ci-dessus.
IBM Cloud Object Storage (COS) expose une API compatible S3, donc ClickHouse y accède via son type de disque s3 avec une paire de clés HMAC statique, de la même manière que pour GCS. L'accès sans identifiants n'est pas possible : IBM Cloud IAM n'a aucun échange qui transforme un token de profil de confiance en clés HMAC temporaires, et les clés HMAC COS n'existent que sous forme de clés statiques à l'intérieur d'un identifiant de service.
Créez d'abord un bucket dédié à ClickHouse dans la console ou la CLI IBM Cloud (COS rejette les ACL S3 que certains outils définissent à la création du bucket), puis un identifiant de service avec HMAC activé et le rôle Writer restreint à ce bucket. Pour faire tourner la clé sans la manipuler à la main, créez l'identifiant de service depuis IBM Cloud Secrets Manager et synchronisez-le dans le cluster.
Créez le secret d'identifiants, comme décrit dans Gestion des informations sensibles Helm :
kubectl create secret generic clickhouse-cos-credentials \
--namespace <namespace> \
--from-literal=access-key-id=<cos-hmac-access-key-id> \
--from-literal=secret-access-key=<cos-hmac-secret-access-key>
Puis référencez le secret dans vos values :
clickhouse:
objectStorage:
provider: s3
s3:
endpoint: 'https://s3.direct.<region>.cloud-object-storage.appdomain.cloud'
bucket: '<bucket-name>'
region: '<region>-standard' # the bucket's storage class code (LocationConstraint), for example eu-de-standard
forcePathStyle: true
existingSecret: clickhouse-cos-credentials
Bucket cible : s3.bucket, indépendant du bucket dans lequel écrit le sidecar de sauvegarde.
Utilisez le endpoint direct de COS (s3.direct.<region>...) depuis un cluster VPC : il maintient le trafic sur le réseau privé IBM Cloud sans coût de bande passante. Les endpoints privés de COS (s3.private.<region>...) ne sont pas accessibles depuis les clusters VPC, et les endpoints publics nécessitent un accès internet sortant depuis les workers.
MinIO n'est pas un fournisseur cloud, il n'y a donc pas d'identité équivalente à IAM avec laquelle se fédérer : ClickHouse s'y authentifie toujours avec une paire access-key/secret-key statique, de la même manière que pour GCS. Contrairement à GCS, MinIO parle la même API S3 que le sidecar de sauvegarde attend déjà, donc une seule paire access-key/secret-key peut couvrir à la fois le propre disque de ClickHouse et le sidecar de sauvegarde : aucun type d'identifiant distinct n'est nécessaire pour le chemin de sauvegarde.
MinIO est configuré comme provider: s3, et non comme un fournisseur distinct à part entière : son API est compatible S3, il utilise donc les mêmes champs objectStorage.s3 qu'AWS, simplement avec un endpoint personnalisé et forcePathStyle: true (la plupart des stockages compatibles S3, MinIO compris, attendent le nom du bucket comme un segment de chemin plutôt que comme un sous-domaine).
Créez le secret d'identifiants, comme décrit dans Gestion des informations sensibles Helm :
kubectl create secret generic clickhouse-minio-credentials \
--namespace <namespace> \
--from-literal=access-key-id=<minio-access-key> \
--from-literal=secret-access-key=<minio-secret-key>
Puis référencez le secret dans vos values :
clickhouse:
objectStorage:
provider: s3
s3:
endpoint: 'http://<minio-host>:<minio-port>'
bucket: '<bucket-name>'
region: 'us-east-1' # MinIO ignores the value but the field is required
forcePathStyle: true
existingSecret: clickhouse-minio-credentials
Bucket cible : s3.bucket, indépendant du bucket dans lequel écrit le sidecar de sauvegarde.
Si votre déploiement MinIO termine le TLS avec un certificat auto-signé ou d'une CA interne, ajoutez cette CA au trust store du pod ClickHouse plutôt que de désactiver la vérification des certificats. Si MinIO n'est accessible que via le réseau interne de votre cluster, un endpoint http:// simple (comme montré ci-dessus) évite totalement le problème.
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.