
Le rapport traite des questions pratiques du développement d'un opérateur sous Kubernetes, de la conception de son architecture et des principes fondamentaux de son fonctionnement.
Dans la premiĂšre partie du rapport, nous examinerons :
- ce qu'est un opérateur dans Kubernetes et à quoi il sert ;
- comment un opérateur simplifie la gestion des systÚmes complexes ;
- ce que l'opérateur peut faire, et ce qu'il ne peut pas faire.
Ensuite, nous aborderons la structure interne de l'opérateur. Nous examinerons l'architecture et le fonctionnement de l'opérateur étape par étape. Nous analyserons en détail :
- l'interaction entre l'opérateur et Kubernetes ;
- quelles fonctions l'opérateur assume, et ce qu'il délÚgue à Kubernetes.
Nous examinerons la gestion des shards et des répliques de bases de données sous Kubernetes.
Ensuite, nous discuterons des questions de stockage des données :
- comment travailler avec le stockage persistant du point de vue de l'opérateur ;
- les piĂšges de l'utilisation du stockage local.
Dans la partie finale du rapport, nous examinerons des exemples pratiques d'application avec Amazon ou Google Cloud Service. Le rapport se fonde sur l'exemple du développement et de l'exploitation de l'opérateur pour ClickHouse.
Vidéo :

Je m'appelle Vladislav Klimenko. Aujourd'hui, je voudrais parler de notre expérience dans le développement et l'exploitation d'un opérateur, en particulier d'un opérateur spécialisé pour la gestion des clusters de bases de données. à titre d'exemple, pour gérer le cluster ClickHouse.

Pourquoi avons-nous la possibilité de parler de l'opérateur et de ClickHouse ?
- Nous soutenons et développons ClickHouse.
- Actuellement, nous essayons d'apporter notre contribution au développement de ClickHouse. Et nous sommes les deuxiÚmes aprÚs Yandex en termes de volume de changements apportés à ClickHouse.
- Nous essayons de créer des projets supplémentaires pour l'écosystÚme ClickHouse.
Je voudrais parler de l'un de ces projets. Il s'agit du ClickHouse-operator pour Kubernetes.
Dans mon rapport, je voudrais aborder deux sujets :
- Le premier sujet est de savoir comment notre opérateur gÚre les bases de données ClickHouse sous Kubernetes.
- Le deuxiÚme sujet est de savoir comment fonctionnent les opérateurs en général, c'est-à -dire comment ils interagissent avec Kubernetes.
Ces deux questions seront entrecroisées tout au long de mon rapport.

Qui pourrait ĂȘtre intĂ©ressĂ© par ce que j'essaie de raconter ?
- Cela intéressera surtout ceux qui exploitent des opérateurs.
- Ou ceux qui veulent créer le leur, afin de comprendre comment cela fonctionne en interne, comment l'opérateur interagit avec Kubernetes et quels piÚges peuvent surgir.

Pour bien comprendre ce dont nous allons discuter aujourd'hui, il serait bon de savoir comment fonctionne Kubernetes et d'avoir une formation de base sur les technologies cloud.

Qu'est-ce que ClickHouse ? C'est une base de donnĂ©es en colonnes spĂ©cialisĂ©e dans le traitement en ligne des requĂȘtes analytiques. Et elle est entiĂšrement open source.
Et nous devons connaßtre seulement deux choses. Il faut savoir que c'est une base de données, donc ce que je vais décrire sera applicable à pratiquement n'importe quelle base de données. Et que le SGBD ClickHouse se scalabilité trÚs bien, offrant pratiquement une scalabilité linéaire. Par conséquent, l'état du cluster est un état naturel pour ClickHouse. Nous sommes donc particuliÚrement intéressés à discuter de la maniÚre de gérer un cluster ClickHouse dans Kubernetes.

Pourquoi est-il nécessaire dans ce contexte ? Pourquoi ne pouvons-nous pas continuer à l'exploiter de façon autonome ? Les réponses sont en partie techniques et en partie organisationnelles.
- Dans la pratique, nous rencontrons de plus en plus souvent cette situation oĂč, dans les grandes entreprises, presque tous les composants sont dĂ©jĂ dans Kubernetes. Les bases de donnĂ©es restent Ă l'extĂ©rieur.
- Et de plus en plus, la question est posée : « Peut-on les intégrer à l'intérieur ? ». Par conséquent, les grandes entreprises tentent de maximiser l'unification de la gestion afin de pouvoir gérer rapidement leurs entrepÎts de données.
- Cela est particuliĂšrement utile s'il est nĂ©cessaire de reproduire au maximum la mĂȘme chose Ă un nouvel endroit, c'est-Ă -dire une portabilitĂ© maximale.

Ă quel point cela est-il simple ou difficile ? Bien sĂ»r, cela peut ĂȘtre fait manuellement. Mais ce n'est pas si simple, car nous avons Ă gĂ©rer la complexitĂ© de Kubernetes lui-mĂȘme, et cela s'ajoute Ă la spĂ©cificitĂ© de ClickHouse. C'est donc une agrĂ©gation.
Et tout cela ensemble constitue un ensemble de technologies assez vaste, dont la gestion devient déjà assez complexe, car Kubernetes apporte ses propres questions quotidiennes d'exploitation, tandis que ClickHouse amÚne ses questions d'exploitation quotidienne. Surtout si nous avons plusieurs instances de ClickHouse, et que nous devons constamment intervenir.

ClickHouse, avec une configuration dynamique, pose un certain nombre de questions qui créent une charge constante sur le DevOps :
- Lorsque nous souhaitons modifier quelque chose dans ClickHouse, par exemple, ajouter une réplique ou un shard, nous devons gérer la configuration.
- Ensuite, il faut changer le schéma de données, car ClickHouse a une méthode spécifique de sharding. Il faut organiser le schéma de données et configurer les paramÚtres.
- Il faut configurer la surveillance.
- Collecte des journaux pour les nouveaux shards, pour les nouvelles répliques.
- Il faut s'occuper de la restauration.
- Et du redémarrage.
Ce sont des tùches routiniÚres qu'il serait souhaitable d'alléger dans l'exploitation.

Kubernetes aide bien Ă l'exploitation, mais dans les tĂąches systĂšme de base.
Kubernetes facilite et automatise des activités telles que :
- Restauration.
- Redémarrage.
- Gestion du systĂšme de stockage.
C'est bien, c'est la bonne direction, mais il n'a pas une compréhension complÚte de l'exploitation d'un cluster de bases de données.
On espÚre obtenir davantage, on souhaite faire fonctionner l'ensemble de la base de données sous Kubernetes.

On aimerait avoir quelque chose comme un grand bouton rouge magique, sur lequel vous appuyez et cela déploie et maintient un cluster tout au long de son cycle de vie, avec les tùches quotidiennes à résoudre. Un cluster ClickHouse sur Kubernetes.
Nous avons tenté de créer une solution qui aiderait à faciliter le travail. C'est l'opérateur ClickHouse pour Kubernetes de la société Altinity.

Un opérateur est un programme dont la tùche principale est de gérer d'autres programmes, c'est-à -dire un gestionnaire.
Il contient des modÚles de comportement. On peut appeler cela des connaissances codifiées sur le domaine.
Sa tùche principale est d'alléger la vie des DevOps et de réduire le micromanagement, permettant ainsi au DevOps de penser en termes de haut niveau, c'est-à -dire qu'il ne s'occupe pas du micromanagement et ne configure pas tous les détails manuellement.
L'opérateur est justement un robot assistant qui lutte contre les micro-tùches et aide les DevOps.

Pourquoi avoir besoin d'un opérateur ? Il se montre particuliÚrement efficace sur deux points :
- Lorsque le spécialiste qui s'occupe de ClickHouse manque d'expérience, mais qu'il faut déjà exploiter ClickHouse, l'opérateur facilite l'exploitation et permet de gérer un cluster ClickHouse avec une configuration relativement complexe, sans vraiment se soucier des détails du fonctionnement interne. Il reçoit simplement des tùches de haut niveau, et cela fonctionne.
- La deuxiÚme tùche dans laquelle il excelle particuliÚrement est celle de l'automatisation d'un grand nombre de tùches répétitives. Il soulage les administrateurs systÚme des micro-tùches.

Cela est surtout nécessaire pour ceux qui commencent leur parcours ou pour ceux qui doivent se concentrer sur l'automatisation.

Quelle est donc la diffĂ©rence entre une approche basĂ©e sur des opĂ©rateurs et d'autres systĂšmes ? Il y a aussi Helm, qui aide Ă installer ClickHouse et qui permet de dessiner des chartes Helm qui peuvent mĂȘme dĂ©ployer un cluster entier de ClickHouse. Quelle est donc la diffĂ©rence entre un opĂ©rateur et Helm par exemple ?
La principale diffĂ©rence fondamentale est que Helm gĂšre des paquets, tandis que l'opĂ©rateur va plus loin. Cela implique le suivi de tout le cycle de vie. Ce n'est pas juste une installation, mais des tĂąches quotidiennes qui incluent le dimensionnement, le sharding, c'est-Ă -dire tout ce qui doit ĂȘtre fait dans le cycle de vie (y compris la suppression si nĂ©cessaire) â tout cela est gĂ©rĂ© par l'opĂ©rateur. Il tente d'automatiser et de maintenir l'ensemble du cycle de vie des logiciels. C'est cela sa diffĂ©rence fondamentale par rapport aux autres solutions disponibles.

C'était la partie d'introduction, passons à la suite.
Comment construisons-nous notre opérateur ? Nous essayons d'aborder la question en gérant le cluster ClickHouse comme une seule ressource.
Ici, à gauche, nous avons les données d'entrée. C'est un YAML avec la spécification du cluster, qui est traditionnellement transmis à Kubernetes via kubectl. L'opérateur le capte, fait sa magie et à la sortie nous obtenons un schéma comme celui-ci. C'est l'implémentation de ClickHouse dans Kubernetes.
Nous allons ensuite examiner progressivement comment fonctionne l'opĂ©rateur, quelles tĂąches typiques peuvent ĂȘtre rĂ©solues. Nous ne traiterons que les tĂąches typiques, car notre temps est limitĂ©. Nous ne parlerons pas de tout ce que l'opĂ©rateur peut rĂ©soudre.

Partons de la pratique. Notre projet est entiĂšrement open source, donc vous pouvez voir sur GitHub comment il fonctionne. Si vous voulez simplement lancer, vous pouvez commencer avec le Quick Start Guide.
Si vous souhaitez vous plonger dans les détails, nous essayons de maintenir la documentation dans un état raisonnablement correct.

Commençons par un exercice pratique. Le premier dĂ©fi, par lequel nous voulons tous commencer, est de lancer le premier exemple d'une maniĂšre ou d'une autre. Comment lancer ClickHouse Ă l'aide d'un opĂ©rateur, mĂȘme sans vraiment savoir comment il fonctionne ? Nous rĂ©digeons un manifeste, car toute communication avec k8s se fait via des manfestes.

Voici un manifeste assez complexe. Ce que nous avons surligné en rouge est ce sur quoi il faut mettre l'accent. Nous demandons à l'opérateur de créer un cluster nommé demo.
Pour l'instant, ce sont des exemples de base. Le stockage n'est pas encore décrit, mais nous reviendrons au stockage un peu plus tard. Pour l'instant, nous allons observer le développement du cluster en dynamique.
Nous avons créé ce manifeste. Nous le donnons à notre opérateur. Il a travaillé, fait sa magie.

Nous regardons dans la console. Trois composants suscitent notre intĂ©rĂȘt : le Pod, deux Services, et le StatefulSet.
L'opérateur a fonctionné, et nous pouvons voir ce qu'il a créé.

Il crée à peu prÚs ce schéma. Nous avons un StatefulSet, un Pod, un ConfigMap pour chaque réplique, un ConfigMap pour l'ensemble du cluster. Des services sont indispensables comme points d'entrée dans le cluster.
Les services sont le Load Balancer Service central et éventuellement un pour chaque réplique, pour chaque shard.
Voici Ă quoi ressemble un cluster de base. Il est constituĂ© d'un seul nĆud.

Allons plus loin, compliquons les choses. Il faut sharder le cluster.

Nos tùches augmentent, et la dynamique commence. Nous voulons ajouter un shard. Nous suivons le développement. Nous changeons notre spécification. Nous indiquons que nous voulons deux shards.
C'est le mĂȘme fichier qui se dĂ©veloppe dynamiquement avec la croissance du systĂšme. Il n'y a pas de stockage, le stockage sera abordĂ© plus tard, c'est un sujet distinct.
Nous donnons le YAML à l'opérateur et voyons ce que cela donne.

L'opérateur a réfléchi et a créé les entités suivantes. Nous avons déjà deux Pods, trois Services, et, soudainement, 2 StatefulSets. Pourquoi 2 StatefulSets ?

Sur le schĂ©ma, c'Ă©tait comme ça â c'est notre Ă©tat initial, lorsque nous avions un pod.

Cela devient ainsi. Pour l'instant, tout est simple, cela a été dupliqué.

Et pourquoi y a-t-il deux StatefulSets ? Il faut s'arrĂȘter un moment et discuter de la maniĂšre dont Kubernetes gĂšre les Pods.
Il existe un objet appelĂ© StatefulSet, qui permet de crĂ©er un ensemble de Pods Ă partir d'un modĂšle. Le facteur clĂ© ici est le modĂšle. Et il est possible de lancer plusieurs Pods Ă partir d'un mĂȘme modĂšle dans un StatefulSet. La phrase clĂ© ici est « plusieurs Pods Ă partir d'un mĂȘme modĂšle ».
Il y avait une grande tentation de faire tout le cluster en l' empaquetant dans un seul StatefulSet. Cela fonctionnerait, il n'y a aucun problĂšme Ă cela. Mais il y a un dĂ©tail. Si nous voulons crĂ©er un cluster hĂ©tĂ©rogĂšne, c'est-Ă -dire avec plusieurs versions de ClickHouse, alors nous commençons Ă avoir des questions. Oui, StatefulSet peut effectuer une mise Ă jour progressive, et il est possible d'appliquer une nouvelle version, en prĂ©cisant qu'il ne faut pas essayer d'avoir plus de cette quantitĂ© de nĆuds Ă la fois.
Mais si nous extrapolons la tùche et disons que nous voulons créer un cluster complÚtement hétérogÚne et que nous ne souhaitons pas remplacer une ancienne version par une nouvelle à l'aide de la mise à jour progressive, mais que nous voulons simplement créer un cluster hétérogÚne tant en termes de différentes versions de ClickHouse que de différents types de stockage. Nous souhaitons, par exemple, que certaines répliques soient sur des disques séparés, sur des disques lents, en gros construire complÚtement un cluster hétérogÚne. Et à cause du fait que StatefulSet propose une solution standardisée à partir d'un seul modÚle, il n'est donc pas possible de faire cela.
AprĂšs rĂ©flexion, il a Ă©tĂ© dĂ©cidĂ© de procĂ©der comme suit. Chaque rĂ©plique a son propre StatefulSet. Cette solution prĂ©sente certains inconvĂ©nients, mais pratiquement, elle encapsule complĂštement l'opĂ©rateur. Et il y a de nombreux avantages. Nous pouvons construire complĂštement le type de cluster que nous voulons, par exemple complĂštement hĂ©tĂ©rogĂšne. Ainsi, dans le cluster oĂč nous avons deux shards avec une rĂ©plique chacun, nous aurons 2 StatefulSets et 2 Pods prĂ©cisĂ©ment parce que nous avons choisi cette approche en raison des raisons mentionnĂ©es prĂ©cĂ©demment pour la possibilitĂ© de construire un cluster hĂ©tĂ©rogĂšne.

Revenons à des tùches pratiques. Dans notre cluster, il est nécessaire de configurer les utilisateurs, c'est-à -dire qu'il faut produire une certaine configuration de ClickHouse dans Kubernetes. L'opérateur fournit toutes les possibilités à cet égard.

Nous pouvons directement écrire dans le YAML ce que nous voulons. Toutes les options de configuration se mappent directement depuis ce YAML vers les configs ClickHouse, qui sont ensuite réparties dans tout le cluster.
Nous pouvons aussi Ă©crire de cette maniĂšre. C'est juste un exemple. Le mot de passe peut ĂȘtre chiffrĂ©. Toutes les options de configuration de ClickHouse sont absolument supportĂ©es. C'est seulement un exemple.
La configuration du cluster est diffusée sous forme de ConfigMap. En pratique, la mise à jour de ConfigMap ne se fait pas instantanément, donc si le cluster est grand, le processus de propagation de la configuration prend un certain temps. Mais tout cela est trÚs pratique à utiliser.

Nous compliquons la tùche. Le cluster se développe. Nous voulons répliquer des données. Autrement dit, nous avons déjà deux shards, avec une réplique chacun, et les utilisateurs sont configurés. Nous grandissons et souhaitons nous consacrer à la réplication.

Que nous faut-il pour la réplication?
Nous avons besoin de ZooKeeper. Dans ClickHouse, la réplication est construite en utilisant ZooKeeper. ZooKeeper est nécessaire pour que différentes répliques de ClickHouse aient un consensus sur les blocs de données présents dans chaque ClickHouse.
Vous pouvez utiliser n'importe quel ZooKeeper. Si l'entreprise dispose d'un ZooKeeper externe, il peut ĂȘtre utilisĂ©. Sinon, vous pouvez l'installer Ă partir de notre rĂ©fĂ©rentiel. Il existe un installateur qui facilite tout cela.

Et le schéma d'interaction de l'ensemble du systÚme est le suivant. Nous avons Kubernetes comme plateforme. Sur celui-ci s'exécute l'opérateur ClickHouse. J'ai représenté ZooKeeper ici. Et l'opérateur interagit à la fois avec ClickHouse et avec ZooKeeper. Cela signifie qu'il y a interaction.
Et tout cela est nécessaire pour que ClickHouse puisse répliquer des données avec succÚs dans k8s.

Voyons maintenant la tĂąche elle-mĂȘme, la façon dont le manifeste de rĂ©plication sera prĂ©sentĂ©.
Nous ajoutons deux sections Ă notre manifeste. La premiĂšre concerne la source de ZooKeeper, qui peut ĂȘtre Ă la fois interne Ă Kubernetes ou externe. C'est juste une description. Et nous commandons des rĂ©pliques. Autrement dit, nous voulons deux rĂ©pliques. Au total, nous devrions avoir 4 pod. Nous nous souvenons que le stockage sera abordĂ© un peu plus tard. Le stockage est une histoire Ă part.

C'était comme ça.

Cela devient ainsi. Des répliques sont ajoutées. La quatriÚme ne rentrait pas, nous croyons qu'il peut y en avoir beaucoup. Et sur le cÎté, ZooKeeper est ajouté. Les schémas se complexifient.

Il est temps d'ajouter la tĂąche suivante. Nous allons ajouter un stockage persistant.
Pour le stockage persistant, nous avons différentes options d'implémentation.
Dans le cas oĂč nous nous exĂ©cutons chez un fournisseur cloud, par exemple, en utilisant Amazon, Google, il y a une grande tentation d'utiliser un stockage cloud. C'est trĂšs pratique, c'est bon.
Et il y a une deuxiĂšme option. C'est pour le stockage local, lorsque nous avons des disques locaux sur chaque nĆud. Cette option est beaucoup plus complexe Ă exĂ©cuter, mais elle est plus performante.

Voyons ce que nous avons concernant le stockage cloud.
Il y a des avantages. C'est trĂšs simple Ă configurer. Nous commandons simplement Ă notre fournisseur cloud de nous donner, s'il vous plaĂźt, un stockage de telle capacitĂ©, de telle classe. Les classes sont dĂ©finies par les fournisseurs eux-mĂȘmes.
Il y a un inconvénient. Pour certains, cela n'est pas critique. Bien sûr, il y aura des problÚmes de performance. C'est trÚs pratique au travail, fiable, mais il existe certaines baisses de performance potentielles.

Et comme ClickHouse met l'accent sur la performance, on peut mĂȘme dire qu'il extrait le maximum possible, c'est pourquoi de nombreux clients essaient d'optimiser leurs performances.

Pour tirer le meilleur parti, nous avons besoin d'un stockage local.
Kubernetes fournit trois abstractions pour utiliser le stockage local. Ce sont :
- EmptyDir
- HostPath.
- Local
Considérons comment ils diffÚrent et se ressemblent.
Tout d'abord, dans les trois approches, le stockage est constituĂ© de disques locaux situĂ©s sur le mĂȘme nĆud physique Kubernetes. Mais ils ont certaines diffĂ©rences.

Commençons par le plus simple, c'est-à -dire emptyDir. Qu'est-ce que c'est en pratique ? C'est quand dans notre spécification, nous demandons au systÚme de conteneurisation (la plupart du temps, c'est Docker) de nous donner accÚs à un dossier sur le disque local.
En pratique, Docker crée quelque part, sur ses propres chemins, un dossier temporaire, le nommant avec un long hachage. Et il fournit une interface d'accÚs à celui-ci.
Comment cela fonctionnera-t-il en termes de performance ? Cela fonctionnera Ă la vitesse du disque local, c'est-Ă -dire que c'est un accĂšs complet Ă votre disque.
Mais cela a son inconvénient. La persistance est assez douteuse dans ce cas. à la premiÚre action de Docker avec des conteneurs, la persistance est perdue. Si Kubernetes décide pour une raison quelconque de déplacer ce Pod sur un autre disque, les données seront perdues.
Cette approche est bonne pour les tests, car elle montre déjà une vitesse satisfaisante, mais pour quelque chose de sérieux, cette option n'est pas adéquate.

C'est pourquoi il existe une deuxiĂšme approche. C'est le hostPath. Si nous regardons les diapositives prĂ©cĂ©dentes et celle-ci, nous pouvons voir une seule diffĂ©rence. Notre dossier a Ă©tĂ© dĂ©placĂ© du Docker vers le nĆud Kubernetes. C'est un peu plus simple. Nous inscrivons directement le chemin dans le systĂšme de fichiers local oĂč nous souhaitons stocker nos donnĂ©es.
Ce moyen présente des avantages. C'est une véritable persistance, et en plus, c'est classique. Les données seront enregistrées sur le disque à une certaine adresse.
Il y a aussi des inconvĂ©nients. C'est la complexitĂ© de la gestion. Notre Kubernetes peut vouloir dĂ©placer un Pod vers un autre nĆud physique. Et c'est lĂ qu'intervient DevOps. Il doit bien expliquer Ă tout le systĂšme que ces Pods ne peuvent ĂȘtre dĂ©placĂ©s que sur des nĆuds oĂč tu as quelque chose montĂ© sur ces chemins, et pas plus d'un nĆud Ă la fois. C'est assez compliquĂ©.
SpĂ©cifiquement pour ces besoins, nous avons créé des modĂšles chez notre opĂ©rateur pour cacher toute cette complexitĂ©. On pouvait simplement dire : « Je veux qu'il y ait une instance de ClickHouse sur chaque nĆud physique et sur tel chemin ».

Mais ce besoin n'est pas seulement le nÎtre, donc les messieurs de Kubernetes comprennent aussi que les gens veulent accéder aux disques physiques, c'est pourquoi ils offrent un troisiÚme niveau.
Cela s'appelle local. La diffĂ©rence avec la diapositive prĂ©cĂ©dente est pratiquement nulle. Auparavant, il fallait le faire manuellement, dire que ces Pods ne peuvent pas ĂȘtre dĂ©placĂ©s d'un nĆud Ă un autre, parce qu'ils doivent ĂȘtre attachĂ©s Ă un chemin spĂ©cifique d'un disque physique local, et maintenant toutes ces connaissances sont encapsulĂ©es dans Kubernetes lui-mĂȘme. Et donc, c'est beaucoup plus facile Ă configurer.

Revenons à notre tùche pratique. Revenons au modÚle YAML. Ici, nous avons un vrai stockage. Nous sommes revenus à cela. Nous définissons un modÚle classique VolumeClaim comme dans k8s. Et nous décrivons quel stockage nous voulons.
AprĂšs cela, k8s demandera du stockage. Il nous en attribuera dans le StatefulSet. Et finalement, cela sera Ă la disposition de ClickHouse.

Nous avions un schéma comme ceci. Notre stockage persistant était rouge, ce qui suggérait qu'il fallait le faire.

Et il devient vert. Maintenant, le schéma du cluster ClickHouse sur k8s est complÚtement finalisé. Nous avons des shards, des répliques, ZooKeeper, il y a un vrai persistant, réalisé d'une maniÚre ou d'une autre. Le schéma est déjà entiÚrement opérationnel.

Nouscontinuons à avancer. Notre cluster évolue. Et Alexey s'efforce, il sort une nouvelle version de ClickHouse.
Une tĂąche pratique se pose - tester la nouvelle version de ClickHouse sur notre cluster. Ăvidemment, on ne veut pas tout mettre Ă jour, on veut peut-ĂȘtre installer la nouvelle version dans un coin Ă©loignĂ© sur une rĂ©plique, ou peut-ĂȘtre pas une nouvelle version, mais deux, car elles sortent frĂ©quemment.
Que pouvons-nous en dire ?

Ici, nous avons justement cette possibilitĂ©. Ce sont des modĂšles de pod. On peut dĂ©tailler comment notre opĂ©rateur permet de construire un cluster hĂ©tĂ©rogĂšne. Câest-Ă -dire configurĂ©, allant de toutes les rĂ©pliques en tas, jusqu'Ă chaque rĂ©plique personnelle, avec quelle version de ClickHouse nous souhaitons, quelle version de stockage nous voulons. Nous pouvons complĂštement configurer un cluster de cette configuration comme nous en avons besoin.

Nous allons maintenant approfondir un peu. Auparavant, nous avons parlé du fonctionnement de l'opérateur ClickHouse en relation avec la spécificité de ClickHouse.
Maintenant, j'aimerais dire quelques mots sur le fonctionnement de n'importe quel opérateur, ainsi que sur la maniÚre dont il interagit avec K8s.

Commençons par examiner l'interaction avec K8s. Que se passe-t-il lorsque nous faisons un kubectl apply ? Nos objets apparaissent via l'API dans etcd.

Par exemple, les objets de base de Kubernetes : pod, StatefulSet, service, etc.
Ă ce stade, rien de physique ne se produit encore. Ces objets doivent ĂȘtre matĂ©rialisĂ©s dans le cluster.

Pour cela, un contrÎleur apparaßt. Le contrÎleur est un composant spécial de k8s qui sait comment matérialiser ces descriptions. Il sait comment et ce qu'il faut faire physiquement. Il sait comment exécuter des conteneurs, ce qu'il faut configurer pour que le serveur fonctionne.

Et il matérialise nos objets dans K8s.
Mais nous voulons opérer non seulement avec des pods et des StatefulSets, nous voulons créer une ClickHouseInstallation, c'est-à -dire un objet de type ClickHouse, pour l'opérer comme un tout. Pour l'instant, cette possibilité n'existe pas.

Mais K8s a une autre chose sympa. Nous souhaitons qu'il y ait quelque part cette entité complexe, qui serait constituée de pods et de StatefulSets pour notre cluster.

Et que faut-il faire pour cela ? Tout d'abord, la Custom Resource Definition entre en jeu. Qu'est-ce que c'est ? C'est une description pour K8s indiquant que vous aurez un autre type de données, que nous souhaitons ajouter une ressource personnalisée complexe aux pods et StatefulSets. C'est une description de la structure des données.

Nous l'envoyons également via kubectl apply. Kubernetes l'a joyeusement accepté.
Et maintenant, nous avons dans le stockage, dans l'objet dans etcd, la possibilité d'enregistrer une ressource personnalisée appelée ClickHouseInstallation.
Mais pour l'instant, rien d'autre ne se produira. C'est-à -dire que si nous créons maintenant un fichier YAML que nous avons examiné, contenant la description des shards, des répliques, et que nous exécutons « kubectl apply », Kubernetes l'acceptera, le mettra dans etcd et dira : « TrÚs bien, mais je ne sais pas quoi en faire. Je ne sais pas comment gérer ClickHouseInstallation. »

Par conséquent, nous avons besoin de quelqu'un pour aider Kubernetes à gérer un nouveau type de données. à gauche, nous avons le contrÎleur Kubernetes par défaut, qui travaille avec des types de données standard. à droite, nous devrions avoir un contrÎleur personnalisé qui sait travailler avec des types de données personnalisés.
Et autrement dit, cela s'appelle un opĂ©rateur. Je l'ai ici spĂ©cifiquement mis en dehors de Kubernetes, car il peut fonctionner en dehors de K8s. Le plus souvent, tous les opĂ©rateurs fonctionnent dans Kubernetes, mais rien ne l'empĂȘche de fonctionner Ă l'extĂ©rieur, c'est pourquoi il est spĂ©cifiquement mis Ă l'extĂ©rieur ici.

Et déjà à son tour, le contrÎleur personnalisé, aussi appelé opérateur, interagit avec Kubernetes via l'API. Il sait déjà interagir avec l'API. Et il sait déjà comment matérialiser un schéma complexe à partir d'une ressource personnalisée que nous voulons créer. C'est précisément ce que fait l'opérateur.

Comment fonctionne un opérateur ? Regardons la partie droite pour savoir comment il fait cela. Découvrons comment l'opérateur matérialise tout cela et comment se déroule ensuite l'interaction avec K8s.

L'opĂ©rateur est un programme. Il est orientĂ© Ă©vĂ©nements. L'opĂ©rateur s'abonne aux Ă©vĂ©nements via l'API Kubernetes. Dans l'API Kubernetes, il existe des points d'entrĂ©e oĂč l'on peut s'abonner aux Ă©vĂ©nements. Et si quelque chose change dans K8s, Kubernetes envoie des Ă©vĂ©nements Ă tous ceux qui le souhaitent, c'est-Ă -dire que ceux qui se sont abonnĂ©s Ă ce point API recevront des notifications.
L'opérateur s'abonne aux événements et doit effectuer une certaine réaction. Sa tùche est de réagir aux événements qui apparaissent.

Les événements sont générés par certaines mises à jour. Notre fichier YAML avec la description de ClickHouseInstallation arrive. Il passe par kubectl apply et va dans etcd. Un événement a alors été déclenché, et cet événement est finalement arrivé au ClickHouse-operator. L'opérateur a reçu cette description. Et il doit faire quelque chose. Si une mise à jour de l'objet ClickHouseInstallation arrive, il faut mettre à jour le cluster. Et la tùche de l'opérateur est de mettre à jour le cluster.

Que fait-il ? Tout d'abord, il faut Ă©tablir un plan d'action pour dĂ©terminer ce que nous allons faire avec cette mise Ă jour. Les mises Ă jour peuvent ĂȘtre trĂšs petites, c'est-Ă -dire de petites exĂ©cutions YAML, mais elles peuvent entraĂźner des changements trĂšs importants dans le cluster. Par consĂ©quent, l'opĂ©rateur crĂ©e un plan et s'y tient ensuite.

Il commence à travailler en conformité avec ce plan pour matérialiser les pod, les services, c'est-à -dire pour faire ce qui est sa tùche principale. C'est comme construire un cluster ClickHouse dans Kubernetes.

Désormais, abordons une question intéressante. Il s'agit de la répartition des responsabilités entre Kubernetes et l'opérateur, c'est-à -dire ce que fait Kubernetes, ce que fait l'opérateur et comment ils interagissent entre eux.
Kubernetes s'occupe des Ă©lĂ©ments systĂšme, c'est-Ă -dire du jeu d'objets de base qui peut ĂȘtre interprĂ©tĂ© comme un ensemble Ă portĂ©e systĂšme. Kubernetes sait comment lancer des pod, redĂ©marrer des conteneurs, monter des volumes, travailler avec ConfigMap, c'est-Ă -dire tout ce qui peut ĂȘtre qualifiĂ© de systĂšme.
Les opérateurs opÚrent dans des domaines d'application. Chaque opérateur est conçu pour son domaine d'application. Nous avons créé celui pour ClickHouse.
Et l'opérateur interagit précisément dans les termes du domaine d'application, tels que l'ajout d'une réplique, la création d'un schéma, la configuration de la surveillance. Il en résulte une telle répartition.

Examinons un exemple pratique de la façon dont cette répartition des responsabilités se produit lorsque nous effectuons l'action d'ajout d'une réplique.
L'opérateur reçoit la tùche d'ajouter une réplique. Que fait-il ? L'opérateur calcule qu'il faut créer un nouveau StatefulSet, dans lequel il doit décrire certains modÚles et les réclamations de volumes.

Il prépare tout cela et le transmet ensuite à K8s. Il indique qu'il a besoin d'une ConfigMap, d'un StatefulSet, d'un Volume. Kubernetes exécute cela. Il matérialise les unités de base avec lesquelles il fonctionne.

Et ensuite, le ClickHouse-operator entre Ă nouveau en jeu. Il a dĂ©jĂ un pod physique sur lequel il peut travailler. Et le ClickHouse-operator travaille Ă nouveau dans les termes du domaine d'application. C'est-Ă -dire que pour inclure une rĂ©plique dans le cluster ClickHouse, il faut d'abord configurer le schĂ©ma de donnĂ©es existant dans ce cluster. DeuxiĂšmement, cette rĂ©plique doit ĂȘtre intĂ©grĂ©e dans la surveillance afin d'ĂȘtre bien suivie. L'opĂ©rateur s'en occupe dĂ©jĂ .

Et ce n'est qu'ensuite que ClickHouse entre en jeu, c'est-Ă -dire une autre entitĂ© de niveau supĂ©rieur. C'est dĂ©jĂ une base de donnĂ©es. Elle dispose de sa propre instance, d'une nouvelle rĂ©plique configurĂ©e, prĂȘte Ă rejoindre le cluster.
On obtient une chaßne d'exécution et de répartition des responsabilités lors de l'ajout d'une réplique qui est assez longue.

Continuons nos tùches pratiques. Si le cluster existe déjà , il est possible d'effectuer la migration de la configuration.

Nous avons fait en sorte que dans le XML existant, que ClickHouse comprend, on puisse passer Ă travers.

Il est possible de faire un réglage fin de ClickHouse. En fait, le déploiement zoné est ce dont j'ai parlé en expliquant hostPath, le stockage local. C'est comment réaliser correctement un déploiement zoné.

La prochaine tĂąche pratique concerne la surveillance.

Si notre cluster change, il est nécessaire de configurer périodiquement la surveillance.
Examinons le schéma. Nous avons déjà étudié les flÚches vertes ici. Maintenant, regardons les flÚches rouges. C'est ainsi que nous voulons surveiller notre cluster. Comment les métriques du cluster ClickHouse vont dans Prometheus, puis dans Grafana.

Quelle est la difficulté liée à la surveillance ? Pourquoi cela est-il considéré comme un accomplissement ? La complexité réside dans la dynamique. Lorsque nous avons un cluster unique et qu'il est statique, il est possible de configurer une fois pour toutes la surveillance et de ne plus s'en préoccuper.
Mais si nous avons plusieurs clusters, ou si quelque chose change constamment, le processus devient dynamique. Et s'occuper en permanence de la reconfiguration de la surveillance est une perte de ressources et de temps, c'est-Ă -dire mĂȘme simplement de l'ennui. Il faut automatiser cela. La complexitĂ© rĂ©side prĂ©cisĂ©ment dans la dynamique du processus. Et l'opĂ©rateur l'automatise trĂšs bien.

Comment notre cluster a-t-il évolué ? Au début, il était comme ça.

Ensuite, il est devenu comme ça.

Au final, il est devenu comme ça.
Et la surveillance est automatiquement effectuée par l'opérateur. Un point d'entrée unique.

Nous regardons simplement dans le tableau de bord Grafana pour voir comment la vie de notre cluster s'anime à l'intérieur.
Au fait, le tableau de bord Grafana est également distribué avec notre opérateur directement dans le code source. Vous pouvez le connecter et l'utiliser. Ce screenshot m'a été donné par nos DevOps.

OĂč voudrions-nous avancer ? C'est :
- Développer l'automatisation des tests. L'objectif principal est le test automatisé des nouvelles versions.
- Nous voulons également automatiser l'intégration avec ZooKeeper. Et nous prévoyons de nous intégrer avec ZooKeeper-operator. C'est-à -dire qu'un opérateur a été écrit pour ZooKeeper et il est logique que les deux opérateurs commencent à s'intégrer pour créer une solution plus conviviale.
- Nous souhaitons effectuer des contrÎles de santé plus complexes.
- En vert, j'ai souligné que nous avons l'héritage des Templates en cours - FAIT, c'est-à -dire qu'avec la prochaine version de l'opérateur, nous aurons déjà l'héritage des modÚles. C'est un outil puissant qui permet de construire des configurations complexes à partir de morceaux.
- Et nous voulons automatiser des tĂąches complexes. La principale est le Re-sharding.

Faisons le point intermédiaire.

Qu'obtenons-nous à la sortie ? Et vaut-il la peine de s'en occuper ou non ? Devons-nous vraiment essayer d'intégrer la base de données dans Kubernetes et d'appliquer l'opérateur en général, et l'opérateur Alitnity en particulier ?
Ă la sortie, nous obtenons :
- Une simplification significative et une automatisation de la configuration, du déploiement, ainsi que du support.
- Surveillance intégrée immédiatement.
- Et des modĂšles codifiĂ©s prĂȘts Ă l'emploi pour des situations complexes. Il n'est plus nĂ©cessaire d'ajouter une rĂ©plique manuellement. Cela est gĂ©rĂ© par l'opĂ©rateur.

Il reste une derniÚre question. Nous avons déjà une base de données dans Kubernetes, de la virtualisation. Quelle est la performance de cette solution, surtout en tenant compte du fait que ClickHouse est optimisé pour la performance ?
La réponse - tout est normal ! Je ne vais pas détailler cela, c'est un sujet pour une présentation séparée.

Mais il existe un projet, appelé TSBS. Quel est son objectif principal ? C'est un test de bases de données pour la performance. C'est une tentative de comparer le chaud avec le chaud, le doux avec le doux.
Comment cela fonctionne-t-il ? Un ensemble de donnĂ©es est gĂ©nĂ©rĂ©. Ensuite, cet ensemble de donnĂ©es est exĂ©cutĂ© sur le mĂȘme ensemble de tests sur diffĂ©rentes bases de donnĂ©es. Chaque base de donnĂ©es rĂ©sout un problĂšme comme elle sait le faire. Et ensuite, les rĂ©sultats peuvent ĂȘtre comparĂ©s.
Il prend déjà en charge un grand nombre de bases de données. J'ai mis en avant trois principales. Ce sont :
- TimescaleDB.
- InfluxDB.
- ClickHouse.

Une comparaison a également été menée avec une autre solution similaire. Une comparaison avec RedShift. La comparaison a été faite sur Amazon. ClickHouse devance également tous dans ce domaine.

Que peut-on conclure de ce que je viens de dire ?
- Il est possible d'utiliser une base de donnĂ©es dans Kubernetes. Peut-ĂȘtre que n'importe quelle base de donnĂ©es est utilisable, mais globalement, cela semble possible. Il est certainement possible d'utiliser ClickHouse dans Kubernetes grĂące Ă notre opĂ©rateur.
- L'opérateur aide à automatiser les processus et rend la vie vraiment plus simple.
- La performance est correcte.
- Et il nous semble que cela peut et doit ĂȘtre utilisĂ©.
Open source â rejoignez-nous !
Comme je l'ai déjà mentionné, l'opérateur est un produit entiÚrement open source, donc ce serait formidable si le plus grand nombre de personnes possible l'utilisait. Rejoignez-nous ! Nous vous attendons tous !
Merci Ă tous !
Questions

Merci pour la présentation ! Je m'appelle Anton. Je viens de l'entreprise SEMrush. Je suis curieux de savoir ce qu'il en est de la journalisation. On entend parler de surveillance, mais pas de journalisation, quand on parle de tout le cluster. Par exemple, nous avons installé un cluster sur du matériel. Et nous utilisons la journalisation centralisée, en rassemblant les données avec des outils standard dans un tout commun. Et puis nous en extrayons les données qui nous intéressent.
C'est une bonne question, c'est-Ă -dire que la journalisation figure sur la liste des choses Ă faire. Pour l'instant, notre opĂ©rateur ne l'automatise pas. Il est encore en dĂ©veloppement, le projet est encore assez jeune. Nous comprenons la nĂ©cessitĂ© de la journalisation. C'est aussi un sujet trĂšs important. Et il est probablement tout aussi crucial que la surveillance. Mais la surveillance Ă©tait en tĂȘte de liste pour la mise en Ćuvre. La journalisation viendra. Nous essayons Ă©videmment d'automatiser tous les aspects de la vie du cluster. Donc, la rĂ©ponse est qu'Ă l'heure actuelle, l'opĂ©rateur ne peut malheureusement pas le faire, mais c'est prĂ©vu, nous allons le faire. Si vous avez envie de participer, n'hĂ©sitez pas Ă faire un pull request.
Bonjour ! Merci pour la prĂ©sentation ! J'ai une question standard liĂ©e aux Persistent Volumes. Lorsque nous crĂ©ons une configuration avec cet opĂ©rateur, comment l'opĂ©rateur dĂ©termine-t-il sur quel nĆud un disque ou un dossier est montĂ© ? Devons-nous lui expliquer au prĂ©alable, s'il vous plaĂźt, de placer notre ClickHouse uniquement sur ces nĆuds oĂč il y a un disque ?
D'aprĂšs ce que je comprends, cette question est une prolongation du stockage local, en particulier de la partie sur hostPath. C'est comme expliquer Ă tout le systĂšme qu'il faut que le pod soit lancĂ© prĂ©cisĂ©ment sur un nĆud oĂč nous avons un disque connectĂ©s physiquement qui est montĂ© Ă un certain chemin. C'est un sujet que j'ai abordĂ© trĂšs superficiellement, car la rĂ©ponse est assez longue.
En rĂ©sumĂ©, cela ressemble Ă ceci. Bien sĂ»r, nous devons effectuer le provisioning de ces volumes. Ă l'heure actuelle, il n'y a pas de provisioning dynamique dans le stockage local, donc les DevOps doivent dĂ©couper les disques eux-mĂȘmes, ces volumes. Ils doivent expliquer Ă Kubernetes le provisioning, que vous aurez des volumes persistants d'une certaine classe, qui se trouvent sur certains nĆuds. Ensuite, il faudra expliquer Ă Kubernetes que les pods qui exigent une certaine classe de stockage local doivent ĂȘtre programmĂ©s uniquement sur certains nĆuds selon les labels. Pour ces objectifs, l'opĂ©rateur a la possibilitĂ© d'assigner un certain label et un par instance hĂŽte. Ainsi, il en rĂ©sultera que les pods seront routĂ©s par Kubernetes pour ne s'exĂ©cuter que sur des nĆuds rĂ©pondant aux exigences, en termes de labels, pour parler simplement. Les administrateurs attribuent des labels et effectuent le provisioning des disques manuellement. Ainsi, cela se dimensionne.
Et justement, la troisiÚme option locale aide à faciliter cela. Comme je l'ai souligné, c'est un travail minutieux de configuration, qui aide à obtenir des performances maximales en sortie.
J'ai une deuxiĂšme question Ă ce sujet. Kubernetes a Ă©tĂ© conçu de maniĂšre Ă ce que la perte d'un nĆud ne soit pas un problĂšme pour nous. Que faire si nous perdons le nĆud oĂč se trouve notre shard ?
Oui, Kubernetes Ă©tait initialement positionnĂ© de sorte que notre relation avec nos pods soit celle du bĂ©tail, mais ici, chaque disque devient quelque chose comme un animal de compagnie. Il y a un problĂšme, c'est que nous ne pouvons pas simplement les jeter. L'Ă©volution de Kubernetes va dans le sens oĂč il n'est pas possible de traiter cela de maniĂšre totalement philosophique, comme s'il s'agissait de ressources complĂštement interchangeables.
Maintenant, une question pratique. Que faire si vous avez perdu le nĆud sur lequel se trouvait le disque ? Ici, le problĂšme doit ĂȘtre rĂ©solu Ă un niveau supĂ©rieur. Dans le cas de ClickHouse, nous avons des rĂ©pliques qui fonctionnent Ă un niveau supĂ©rieur, c'est-Ă -dire au niveau de ClickHouse.
Quelle est donc la disposition ? C'est Ă DevOps que revient la responsabilitĂ© de ne pas perdre les donnĂ©es. Ils doivent correctement configurer la rĂ©plication et veiller Ă ce que celle-ci s'exĂ©cute. Les donnĂ©es doivent ĂȘtre dupliquĂ©es dans la rĂ©plique au niveau de ClickHouse. Ce n'est pas la tĂąche d'un opĂ©rateur. Et ce n'est pas non plus la tĂąche de Kubernetes lui-mĂȘme. C'est au niveau de ClickHouse.
Que faire si vous avez un nĆud physique qui a Ă©chouĂ© ? Il faudra en installer un second, et correctement y provisionner un disque, appliquer des labels. AprĂšs cela, il rĂ©pondra aux exigences permettant Ă Kubernetes de lancer une instance de pod dessus. Kubernetes l'initialisera. Vous avez en effet un nombre de pods insuffisant pour atteindre l'objectif. Cela passera par le cycle que j'ai montrĂ©. Et au plus haut niveau, ClickHouse comprendra qu'une rĂ©plique est entrĂ©e, qu'elle est encore vide et qu'il faut commencer Ă y transfĂ©rer des donnĂ©es. Ce processus est encore mal automatisĂ©.
Merci pour votre présentation ! Lorsque des incidents se produisent, que l'opérateur tombe et redémarre, tout en recevant des événements, comment traitez-vous cela ?
Que se passe-t-il si l'opérateur est tombé et redémarré, n'est-ce pas ?
Oui. Et à ce moment-là , des événements sont apparus.
La tĂąche de gĂ©rer cette situation est en partie partagĂ©e entre l'opĂ©rateur et Kubernetes. Kubernetes a la capacitĂ© de rejouer l'Ă©vĂ©nement qui s'est produit. Il le rejoue. La tĂąche de l'opĂ©rateur est de s'assurer que lorsque le replay du log d'Ă©vĂ©nements est effectuĂ©, ces Ă©vĂ©nements soient idempotents. Ainsi, la rĂ©pĂ©tition de la mĂȘme entrĂ©e d'Ă©vĂ©nement ne dĂ©truira pas notre systĂšme. Et notre opĂ©rateur gĂšre cette tĂąche.
Bonjour ! Merci pour votre présentation ! Dmitry Zavyalov, entreprise Smedova. Envisagez-vous d'ajouter la possibilité de configurer l'opérateur avec haproxy ? Un autre équilibreur de charge en plus de l'option standard serait intéressant, pour qu'il soit intelligent et comprenne que c'est véritablement ClickHouse.
Parlez-vous de Ingress ?
Oui, remplacer Ingress par haproxy. Dans haproxy, vous pouvez spĂ©cifier la topologie du cluster, oĂč se trouvent ses rĂ©pliques.
Pour l'instant, nous n'y avons pas rĂ©flĂ©chi. Si c'est nĂ©cessaire pour vous et que vous pouvez expliquer pourquoi, nous pourrions le mettre en Ćuvre, surtout si vous souhaitez participer. Nous examinerons avec plaisir cette option. En rĂ©sumĂ©, non, nous n'avons pas cette fonctionnalitĂ© actuellement. Merci pour la suggestion, nous y jetterons un Ćil. Et si vous pouvez aussi expliquer le cas d'utilisation et pourquoi c'est nĂ©cessaire en pratique, par exemple en crĂ©ant des issues sur GitHub, ce serait parfait.
C'est déjà fait.
Bien. Nous sommes ouverts à toutes les propositions. Et haproxy est sur la liste des tùches à faire. La liste des tùches s'allonge, elle ne diminue pas pour l'instant. Mais c'est une bonne chose, cela signifie que le produit est demandé.
Source : habr.com
