Configuration de ClickHouseCluster
Configuration de base
Répliques et shards
- Répliques : nombre d’instances ClickHouse par shard (pour la haute disponibilité)
- Shards : nombre de partitions horizontales (pour la mise à l’échelle)
replicas: 3 et shards: 2 créera au total 6 pods ClickHouse.
Intégration de Keeper
Chaque cluster ClickHouse a besoin d’un ensemble Keeper pour la coordination. Définissez exactement l’un des deux champskeeperClusterRef ou externalKeeper ; un cluster qui définit les deux, ou aucun des deux, est rejeté.
Faites pointer keeperClusterRef vers un KeeperCluster géré par cet opérateur :
keeperClusterRef.namespace est défini, l’opérateur doit surveiller les deux espaces de noms. Si WATCH_NAMESPACE est configuré, incluez les espaces de noms de ClickHouse et de Keeper dans cette liste.
Keeper géré en externe
UtilisezexternalKeeper pour exécuter ClickHouse avec un ensemble Keeper que l’opérateur ne gère pas —
qu’il soit géré par un autre opérateur, qu’il s’exécute dans un autre cluster Kubernetes, sur des machines virtuelles ou
sur serveurs bare metal, ou qu’il soit partagé entre plusieurs systèmes :
port vaut 9181 par défaut. host est un nom DNS ou une adresse IP ; les adresses IPv6 doivent être placées entre crochets.
Définissez tls: Enabled pour vous connecter via TLS, et indiquez dans port le port sur lequel l’ensemble écoute
les connexions sécurisées :
caBundle
que vous avez configuré. Consultez Communication ClickHouse-Keeper via TLS.
Lorsque plusieurs clusters ClickHouse partagent un même ensemble Keeper, attribuez à chacun son propre znode racine via
settings.extraConfig, afin que leurs métadonnées de réplication, leurs utilisateurs définis en SQL et leurs collections nommées
n’entrent pas en conflit. Créez le znode avant le démarrage de ClickHouse et ne le modifiez plus par la suite :
zookeeper.root dans settings.extraReloadableConfig : un rechargement modifierait la racine d’un
cluster en cours d’exécution et ferait passer ses tables répliquées en lecture seule. Si le znode racine est soumis à des ACL, celles-ci doivent autoriser
la keeper-identity du cluster à créer des znodes enfants.
L’opérateur ne modifie pas ces serveurs et n’attend pas qu’ils soient disponibles avant de réconcilier ClickHouse.
Il revient à l’utilisateur de garantir la disponibilité de l’ensemble.
L’authentification fonctionne de la même manière que pour un Keeper géré par l’opérateur : l’opérateur lit la clé
keeper-identity dans le Secret du cluster et la transmet à ClickHouse. Consultez
External Secret pour connaître la disposition du Secret.
Configuration de KeeperCluster
Transfert du leadership à l’arrêt
Le conteneur Keeper dispose d’un hookpreStop par défaut qui demande à la réplique de céder le leadership Raft
avant de s’arrêter, puis attend la fin de ce transfert avant de laisser le
conteneur se terminer. Ce hook s’exécute à chaque arrêt gracieux du conteneur, et pas uniquement lors des
déploiements progressifs initiés par l’opérateur : une éviction par le descheduler, un drainage de nœuds ou une action de
l’autoscaler déclenchent tous le même hook, puisqu’il s’agit d’un handler preStop exécuté par le kubelet et non
d’une logique de la boucle de réconciliation.
Sans ce hook, le redémarrage du leader actuel laisse l’ensemble sans leader jusqu’à
l’issue d’une nouvelle élection, ce qui peut prendre plusieurs secondes sous charge et se traduit, côté
ClickHouse, par des pertes de connexion à Keeper et une latence accrue des requêtes. Le hook demande à la
réplique de céder le leadership (commande à quatre lettres ydld de Keeper, envoyée via le port
http_control), puis interroge le statut de la réplique jusqu’à ce qu’elle ne soit plus
leader, au lieu d’envoyer la requête et de laisser immédiatement le conteneur s’arrêter : sous une charge d’écriture, une
requête de type fire-and-forget peut encore être devancée par le SIGTERM (condition de concurrence) ; c’est donc
cette attente qui permet de borner la période sans leader.
Le hook ne nécessite aucune configuration et se dégrade gracieusement : sur les versions de Keeper antérieures à
26.3, qui ne prennent pas encore en charge les commandes de leadership utilisées ici, la requête est sans effet (no-op) et
le conteneur s’arrête comme il le ferait sans le hook. Comme il exécute un script shell, il nécessite
bash dans l’image ; si vous utilisez une image Keeper distroless ou scratch, remplacez-le ou supprimez-le
via containerTemplate.lifecycle — consultez la
Référence de l’API.
Configuration du stockage
dataVolumeClaimSpec, un
PersistentVolumeClaimSpec Kubernetes standard. L’opérateur le convertit en un
PersistentVolumeClaim par réplique, monté sur le chemin des données /var/lib/clickhouse :
L’opérateur ne peut modifier un PVC existant que si la StorageClass sous-jacente prend en charge l’extension des volumes.
Domaine du cluster
spec.clusterDomain définit le suffixe DNS Kubernetes que l’opérateur utilise lorsqu’il génère
les noms d’hôte complets des pods qu’il inscrit dans la
configuration du serveur ClickHouse. La valeur par défaut est cluster.local, et ce champ existe à la fois dans
ClickHouseCluster et KeeperCluster.
<cluster-name>-clickhouse-headless qui gère le trafic client.
Il crée également des Services par réplique <cluster-name>-clickhouse-internal-<shard>-<index> qui exposent les pods non prêts au trafic interne
et aux requêtes de gestion de l’opérateur. Ils peuvent servir à la récupération d’une réplique si celle-ci ne parvient pas elle-même à devenir prête.
Les nœuds Keeper utilisent les noms de pods via leur Service headless : <pod>.<headless-service>.<namespace>.svc.<clusterDomain>.
Ne remplacez cette valeur que si le
kubelet de votre cluster s’exécute avec un --cluster-domain
différent de cluster.local. Si la valeur ne correspond pas au véritable domaine du cluster,
ClickHouse ne peut pas résoudre les noms d’hôte de Keeper ni ceux des répliques — la coordination et les
requêtes Distributed échouent avec des erreurs de résolution DNS. Définissez la même valeur sur le
ClickHouseCluster et le KeeperCluster auquel il fait référence.Configuration du pod
Répartition topologique et affinité automatiques
Répartissez les pods sur plusieurs zones de disponibilité :Assurez-vous que votre cluster Kubernetes dispose d’un nombre suffisant de nœuds répartis sur différentes zones pour respecter les contraintes de répartition.
topologyMinDomains sur le nombre de zones de disponibilité pour forcer la répartition :
topologyMinDomains nécessite topologyZoneKey. Les pods restent à l’état Pending tant que le nombre de zones disponibles est inférieur à celui
demandé ; restez donc dans les limites des zones que votre cluster peut fournir.Configuration manuelle
Consultez la Référence de l’API pour voir toutes les options de modèle de pod prises en charge.
Budgets de perturbation des pods
Valeurs par défaut
apply initial protège déjà contre une perte accidentelle de quorum.
Pour un ClickHouseCluster de 3 shards avec
replicas: 3, l’opérateur crée trois PDB, un par shard, chacun avec minAvailable: 1.
Surcharger les valeurs par défaut
spec.podDisruptionBudget pour surcharger minAvailable ou maxUnavailable (un seul) :
maxUnavailable, avec un pourcentage :
unhealthyPodEvictionPolicy au PDB généré — ce qui est utile lorsque vous devez autoriser l’éviction de pods encore en état NotReady :
Politiques
spec.podDisruptionBudget.policy vous permet de choisir avec quel degré d’intervention l’opérateur gère les PDB :
Exemple — désactiver complètement la gestion des PDB sur un cluster de développement :
Désactivation à l’échelle du cluster
ENABLE_PDB de l’opérateur. Avec ENABLE_PDB=false, l’opérateur ignore l’étape de réconciliation des PDB pour chaque ClickHouseCluster et KeeperCluster, quelle que soit la valeur de leur spec.podDisruptionBudget.policy, et ne surveille pas du tout les ressources PodDisruptionBudget. Le ServiceAccount de l’opérateur n’a donc pas besoin d’autorisations RBAC sur poddisruptionbudgets.policy/v1, ce qui est utile lorsque l’opérateur s’exécute avec un ServiceAccount restreint qui exclut volontairement ces autorisations.
Configuration du conteneur
Image personnalisée
Ressources des conteneurs
Variables d’environnement
Points de montage de volumes
Il est possible de spécifier plusieurs montages de volume sur le même
mountPath.
L’opérateur créera un volume projeté regroupant tous les montages spécifiés.Sondes de santé
L’opérateur configure des sondes liveness et readiness sur chaque conteneur ClickHouse et Keeper. Aucune sonde de démarrage n’est définie par défaut.
ClickHouse et Keeper utilisent les mêmes paramètres de temporisation par défaut :
ClickHouse ouvre l’écouteur interserveur avant de charger les tables, et les écouteurs client ensuite. La sonde liveness tolère donc un chargement lent des tables, tandis qu’une sonde readiness réussie indique que la réplique est en mesure de traiter les requêtes.
Vous pouvez remplacer n’importe quelle sonde via
spec.containerTemplate, quelle que soit la ressource. Par exemple, pour personnaliser la sonde liveness de ClickHouse :
Sonde de démarrage
UtilisezstartupProbe lorsqu’un conteneur a besoin de plus de temps pour démarrer que ne le permet la sonde liveness — avec les valeurs par défaut, environ 60 secondes de délai initial, plus 10 vérifications en échec espacées de 5 secondes.
Kubernetes suspend les sondes liveness et readiness jusqu’à ce que la sonde de démarrage réussisse, de sorte qu’un démarrage lent ne déclenche pas de boucle de redémarrage.
Par exemple, pour laisser jusqu’à 10 minutes à une réplique Keeper qui rejoue un snapshot volumineux avant de commencer à accepter des connexions :
Voir la Référence de l’API pour toutes les options prises en charge des modèles de conteneur.
Configuration du TLS/SSL
Configurer des endpoints sécurisés
Format du Secret pour le certificat SSL
tls.crt- certificat serveur encodé en PEMtls.key- clé privée encodée en PEM
Ce format est compatible avec les certificats générés par cert-manager.
Communication de ClickHouse Keeper via TLS
Si TLS est activé pour le KeeperCluster référencé parkeeperClusterRef, ClickHouseCluster utilisera automatiquement une connexion sécurisée vers les nœuds Keeper.
Avec externalKeeper, définissez plutôt tls: Enabled et attribuez au port de chaque nœud le port client sécurisé de l’ensemble (par exemple 9281).
ClickHouseCluster vérifie les certificats des nœuds Keeper à l’aide du magasin de certificats de confiance du système, ainsi que de tout caBundle que vous configurez.
Pour faire confiance à une CA privée (par exemple, une CA auto-signée ou interne), fournissez une référence vers un CA bundle personnalisé :
External Secret
spec.externalSecret :
Le Secret référencé doit se trouver dans le même espace de noms que le ClickHouseCluster. L’opérateur ne supprime jamais un Secret qu’il n’a pas créé.
Clés requises
Voici à quoi ressemble un Secret complet :
Politique : Observe ou Manage
spec.externalSecret.policy contrôle la façon dont l’opérateur gère les clés requises manquantes :
Même avec
policy: Manage, le secret doit déjà exister dans l’espace de noms — l’opérateur ne crée jamais lui-même le secret, il écrit seulement les clés générées dans un secret existant. Si le secret référencé est absent, la réconciliation est bloquée avec la raison ExternalSecretNotFound, quelle que soit la politique.Observe lorsqu’un système externe (Vault, ESO, sealed-secrets, GitOps) fait office de source de vérité et que vous voulez que l’opérateur échoue clairement en cas de mauvaise configuration. Choisissez Manage si vous voulez une initialisation autonome tout en conservant la maîtrise de l’objet secret lui-même (par exemple, pour le sauvegarder).
Condition d’état et dépannage
ExternalSecretValid dans ClickHouseCluster.status.conditions. Consultez-la lorsque la réconciliation semble bloquée :
L’opérateur remet la réconciliation en file d’attente tant que le Secret est invalide. Ainsi, dès que vous ajoutez les clés manquantes, la réconciliation suivante les prend automatiquement en compte : inutile de redémarrer les pods.
L’ensemble des clés requises dépend de la version de ClickHouse utilisée.
named-collections-key n’est validée qu’une fois que la sonde de version de l’opérateur a détecté ClickHouse 25.12 ou une version plus récente. Sur les versions antérieures, la clé peut être absente du Secret. disk-encryption-key n’est requise que lorsque spec.settings.encryption est défini.Ports supplémentaires
8123 HTTP, 9000 natif, 9009 inter-serveur, 9001/9002 gestion, 9363 métriques Prometheus, ainsi que les variantes TLS 8443/9440 lorsque TLS est activé. Les ports interserveur et de gestion sont également exposés via les Services internes de chaque réplique afin que les répliques et l’opérateur puissent communiquer avant qu’une réplique soit prête. Pour que ClickHouse écoute sur des protocoles supplémentaires — MySQL, PostgreSQL, gRPC ou tout autre port personnalisé — déclarez-les dans spec.additionalPorts :
containerPorts du pod ainsi qu’au Service headless public.
L’exemple complet se trouve dans examples/custom_protocols.yaml.
Exemple complet : protocole MySQL wire
9004 :
Contraintes sur les champs
Ports et noms réservés
additionalPorts qui entreraient en conflit avec des ports que l’opérateur utilise lui-même. Tous les ports liés à TLS sont réservés systématiquement afin que l’activation ultérieure de spec.settings.tls.enabled ne puisse pas invalider un cluster auparavant valide.
Les noms suivants sont également rejetés — il s’agit des identifiants internes de type de protocole de l’opérateur (et non des alias lisibles par l’humain) :
Une requête rejetée produit une erreur du type :
Sonde de version et canal de mise à niveau
- Signalement de version — pour
ClickHouseCluster, unJobKubernetes exécute une fois l’image de conteneur afin de détecter la version de ClickHouse en cours d’exécution ; pourKeeperCluster, l’opérateur lit la version signalée par le serveur à partir des répliques en cours d’exécution. La version détectée est enregistrée dans.status.versionet utilisée par d’autres étapes de réconciliation (par exemple, la clé named-collectionsExternal Secretn’est requise qu’à partir de ClickHouse25.12). - Canal de mise à niveau — une vérification périodique du flux public des versions de ClickHouse (
https://clickhouse.com/data/version_date.tsv). L’opérateur indique si une version plus récente est disponible via la condition d’étatVersionUpgraded. Il ne met jamais lui-même le cluster à niveau — l’utilisateur garde le contrôle du tag de l’image.
Choisir un canal de publication
spec.upgradeChannel sélectionne l’ensemble des versions amont avec lesquelles l’opérateur effectue la comparaison. Le même champ existe sur ClickHouseCluster et KeeperCluster.
^(lts|stable|\d+\.\d+)?$) :
En production, il est généralement préférable de fixer le canal sur un
<major>.<minor> explicite (par ex. 25.8). Cela verrouille le cluster sur la ligne de release majeure prévue et permet à l’opérateur de signaler un avertissement WrongReleaseChannel si une réplique dérive d’une manière ou d’une autre vers une autre version majeure — ce qui est particulièrement important lorsque l’image est référencée par un digest (@sha256:...) plutôt que par un tag lisible par l’humain. La valeur vide par défaut convient aux clusters de développement pour lesquels les sauts de version majeure ne posent pas de problème.
Conditions d’état
Inspectez-les avec :
Redéfinition du Job de sonde de version
ClickHouseCluster. KeeperCluster n’exécute plus de Job de sonde de version — sa version est lue directement à partir des répliques Keeper actives —, donc spec.versionProbeTemplate est déprécié et n’y a aucun effet.
La sonde est implémentée sous la forme d’un Job Kubernetes standard. Si votre cluster applique des politiques d’admission qui exigent des Tolerations spécifiques, des sélecteurs de nœuds, des contextes de sécurité, ou si vous souhaitez limiter la durée de présence des Jobs de sonde terminés, redéfinissez le template via spec.versionProbeTemplate:
version-probe est le nom par défaut de l’opérateur — l’entrée sous containers: porte le même nom, donc l’opérateur applique une fusion profonde des champs fournis par l’utilisateur par-dessus les valeurs par défaut.
Contrôles globaux de l’opérateur
Définissez
--disable-version-update-checks=true dans les environnements isolés du réseau ou lorsque le trafic sortant vers clickhouse.com n’est pas autorisé.
Paramètres de ClickHouse
Mot de passe de l’utilisateur default
spec.settings.defaultUserPassword définit le mot de passe du compte intégré default.
Fournissez la valeur à partir d’une clé d’un Secret (recommandé) ou d’une ConfigMap
que vous créez, plutôt que de l’indiquer directement dans la CR :
secret ou configMap, chacun avec name (l’objet)
et key (l’entrée qui contient le mot de passe).
Types de mot de passe
passwordType indique à ClickHouse comment interpréter la valeur. Par défaut, il
est défini sur password (texte en clair) ; les alternatives sont des formes hachées
comme password_sha256_hex et password_double_sha1_hex. Préférez un type haché afin que le
texte en clair ne soit jamais stocké. Consultez les
paramètres utilisateur de ClickHouse
pour la liste complète.
Exemple complet avec un Secret
Avec
passwordType: password, le clickhouse-client du pod est configuré avec
ce mot de passe, ce qui est pratique pour le débogage.Utiliser un ConfigMap
password_sha256_hex :
Ne stockez pas de mot de passe en clair dans un ConfigMap. Utilisez un Secret pour toute valeur en clair
(
passwordType: password).Utilisateurs personnalisés dans la configuration
Configurez des utilisateurs supplémentaires dans les fichiers de configuration. Créez une ConfigMap et un Secret pour l’utilisateur :Synchronisation de la base de données
clickhouse.com/ReplicaInitialized. Une nouvelle réplique n’est donc publiée via le Service headless public qu’une fois son initialisation terminée par l’opérateur : la base de données default est convertie au moteur Replicated et le schéma est synchronisé. Jusque-là, l’opérateur et les autres répliques y accèdent via son Service interne. Avec enableDatabaseSync: false, l’opérateur marque immédiatement les répliques comme initialisées, de sorte que leur disponibilité ne dépend que des sondes de conteneur.
L’opérateur ne supprime jamais une base de données default non-Replicated contenant des données. Une telle réplique commence tout de même à servir le trafic client après la préparation du schéma, mais le cluster signale SchemaInSync=False avec la raison DefaultDatabaseNotReplicated jusqu’à ce que vous résolviez vous-même ce problème de base de données.
Avant qu’une réplique soit supprimée lors d’une réduction d’échelle, l’opérateur retire d’abord le trafic client de celle-ci, attend qu’elle cesse d’être publiée, réplique ses données restantes vers les répliques survivantes, puis la supprime.
Journalisation du serveur
Configurez le journal du serveur ClickHouse viaspec.settings.logger. Chaque champ est facultatif et possède une valeur par défaut sûre ; ainsi, même si vous n’y touchez jamais, un cluster journalise déjà au niveau information, à la fois dans la console du conteneur et dans un fichier avec rotation sur disque.
L’opérateur conserve toujours la journalisation vers la console afin que
kubectl logs fonctionne, et ajoute par-dessus une journalisation dans des fichiers lorsque logToFile vaut true. Un cluster avec les valeurs par défaut génère ce bloc logger :
spec.settings.logger s’applique à un KeeperCluster ; l’opérateur écrit alors ses fichiers dans /var/log/clickhouse-keeper/ et règle le journaliseur Raft (raft_logs_level) sur le même niveau level.
La journalisation dans la console reste activée независимоamment de
logToFile, donc kubectl logs continue de fonctionner même si vous désactivez la journalisation dans un fichier. Définissez jsonLogs: true lorsque vous envoyez des logs vers un système de stockage de logs structurés qui analyse le JSON.Tables système de logs
L’opérateur active les tables systèmequery_log, part_log, text_log, metric_log et asynchronous_metric_log. Comme elles résident sur le même volume que vos données, spec.settings.systemLogsTTLDays limite leur rétention au moyen d’un TTL de table. Le webhook de valeurs par défaut le fixe à 30 lorsque vous créez un cluster sans renseigner ce champ. Indiquez 0 pour désactiver explicitement le TTL.
La valeur par défaut s’applique uniquement aux nouveaux clusters. Un cluster créé avant l’introduction de
systemLogsTTLDays conserve des tables de log système sans limite de rétention tant que vous ne définissez pas ce champ vous-même.@remove, le tout via extraConfig :
Une table désactivée n’est pas supprimée : les données existantes restent sur le disque jusqu’à ce que vous supprimiez vous-même la table.
Lorsque le TTL d’une table système change, ClickHouse recrée cette table et conserve les anciennes données dans une table renommée, par exemple
system.text_log_0. Supprimez ces tables dès que vous n’avez plus besoin de l’historique.Configuration personnalisée
Configuration supplémentaire intégrée
extraConfig :
Liens utiles :
Configuration supplémentaire rechargeable
Toute modification deextraConfig entraîne le redémarrage des pods ClickHouse, car l’opérateur ne peut pas savoir quels paramètres sont pris en compte à l’exécution. Pour les paramètres que ClickHouse recharge à la volée (named_collections étant le cas le plus courant), utilisez plutôt extraReloadableConfig. L’opérateur en applique alors les modifications par un rechargement de la configuration, sans redémarrer les pods :
extraConfig ou extraReloadableConfig ; l’opérateur émet un avertissement lorsque les deux définissent la même section.
En utilisant
extraReloadableConfig, vous garantissez que ses paramètres peuvent être rechargés sans risque. Si vous y placez un paramètre qui nécessite un redémarrage, il ne prendra effet qu’au prochain redémarrage, sans qu’aucune erreur ne soit signalée.Configuration intégrée d’utilisateurs supplémentaires
extraUsersConfig. Cela permet de définir directement des utilisateurs, des profils, des quotas et des privilèges dans la spécification du cluster.
extraUsersConfig est stocké dans l’objet ConfigMap k8s. Évitez d’y stocker des secrets en clair.Consultez la documentation pour connaître toutes les options de configuration prises en charge pour les utilisateurs ClickHouse.
Exemple de configuration
Resynchronisation périodique
En plus de réagir aux événements Kubernetes, l’opérateur réconcilie à nouveau chaque cluster à intervalle fixe. Cela permet de garder à jour les conditions d’état relatives à un state qu’aucun watch ne peut observer — santé des répliques ClickHouse, quorum Keeper — et de réessayer les actions correctives telles que le nettoyage des pods bloqués. L’intervalle est contrôlé par la variable d’environnementRESYNC_PERIOD de l’opérateur (valeur par défaut : 30s). Elle s’applique aux ressources KeeperCluster, où 0 désactive la resynchronisation périodique. Les ressources ClickHouseCluster interrogent la table ClickHouse system.warnings toutes les 30 secondes, ce qui relance déjà la réconciliation ; RESYNC_PERIOD n’a donc actuellement aucun effet sur elles.
MAX_CONCURRENT_RECONCILES (valeur par défaut : 4).
Suspendre la réconciliation
Ajoutez l’annotationclickhouse.com/pause-reconciliation: "true" sur un ClickHouseCluster ou un KeeperCluster pour empêcher l’opérateur de le réconcilier. L’opérateur signale alors ReconcileSucceeded=False avec la raison ReconciliationPaused sur la ressource suspendue, sans y apporter aucune autre modification — ce qui s’avère utile pour intervenir manuellement lorsque l’opérateur risquerait d’écraser vos modifications. Pendant la suspension, l’opérateur signale toutes les conditions d’état (y compris Ready et Healthy) comme Unknown avec la raison ReconciliationPaused, car il n’observe plus le cluster. Supprimez l’annotation pour reprendre la réconciliation : les modifications de la spec en attente seront appliquées lors de la prochaine réconciliation.