ClickHouse San Francisco Bay Area Meetup : Akvorado

Vincent Bernat

Voici les dia­po­si­tives que j’ai pré­sen­tées lors d’un mee­tup Click­House Bay Area en juillet 2022, or­ga­nisé par Al­ti­nity. Elles portent sur Ak­vo­rado, un col­lec­teur et vi­sua­li­sa­teur de flux ré­seau, et no­tam­ment sur la fa­çon dont il s’ap­puie sur Click­House, une base de don­nées orien­tée colonnes.

La réunion a été en­re­gis­trée et est dis­po­nible sur YouTube. Voici la par­tie qui concerne ma pré­sen­ta­tion, avec des sous-titres1 :

J’ai eu quelques ques­tions sur la fa­çon d’ob­te­nir des in­for­ma­tions des couches su­pé­rieures, comme HTTP. Comme mon cas d’uti­li­sa­tion d’Ak­vo­rado se si­tuait à la pé­ri­phé­rie du ré­seau, mes ré­ponses étaient prin­ci­pa­le­ment né­ga­tives. Ce­pen­dant, comme sFlow est ex­ten­sible, lorsque vous col­lec­tez des flux à par­tir de ser­veurs Li­nux, vous pou­vez in­té­grer des don­nées sup­plé­men­taires et les ex­por­ter également.

J’ai éga­le­ment reçu une ques­tion sur l’agré­ga­tion dans une seule table. Click­House peut agré­ger au­to­ma­ti­que­ment des don­nées en uti­li­sant le TTL. Ma ré­ponse pour ne pas le faire est par­tielle. Il y a une autre rai­son : les pé­riodes de ré­ten­tion des dif­fé­rentes tables peuvent se che­vau­cher. Par exemple, la table prin­ci­pale conserve les don­nées pen­dant 15 jours, mais même pen­dant ces 15 jours, si je fais une re­quête sur une fe­nêtre de 12 heures, il est plus ra­pide d’uti­li­ser la table agré­gée flows_​1m0s, sauf si je de­mande quelque chose sur les ports et les adresses IP.

Transcription#

Akvorado: a Flow Collector and Visualizer Backed by ClickHouse

Bon­jour. Je suis Vincent Ber­nat. Je suis un in­gé­nieur ré­seau fran­çais qui tra­vaille chez Free. Je fais cette pré­sen­ta­tion de­puis Pa­ris, France. C’est un plai­sir de vous voir. Je vais vous pré­sen­ter Ak­vo­rado, un col­lec­teur et vi­sua­li­seur de flux ré­seau uti­li­sant ClickHouse.

About Free

Il a été dé­ve­loppé en in­terne chez Free. Free est un FAI fran­çais fondé en 1999. C’est l’un des tous pre­miers four­nis­seurs d’ac­cès ac­ces­sible sans abon­ne­ment et sans nu­méro sur­taxé en France. Il a contri­bué à la dé­mo­cra­ti­sa­tion de l’ADSL en France en fai­sant bais­ser les prix. Il a été par­ti­cu­liè­re­ment in­no­vant avec l’in­tro­duc­tion de la Free­box. Il s’agit de la pre­mière boîte d’ac­cès « Triple Play », in­cluant In­ter­net, té­lé­vi­sion et té­lé­phone. Il a aussi beau­coup contri­bué à l’adop­tion d’IPv6 en France en 2008. L’offre mo­bile a aussi été très in­no­vante avec un quota de don­nées très élevé. Ac­tuel­le­ment, il y a plus de 100 Go in­clus et vous pou­vez l’uti­li­ser un peu par­tout dans le monde. Mais nous ne sommes pas dis­po­nibles à San Francisco.

About Akvorado

Ak­vo­rado est un col­lec­teur NetFlow, IPFIX, sFlow. Les rou­teurs en­voient un ex­trait des pa­quets qu’ils re­çoivent à Ak­vo­rado, quelque chose comme un pa­quet sur 10000.

Il y a plu­sieurs pro­to­coles pour ça. IPFIX est la ver­sion IETF de NetFlow. Net­flow est un pro­to­cole pro­prié­taire de Cisco. sFlow est un autre type de pro­to­cole. La dif­fé­rence est qu’il n’agrège pas les don­nées. Il les en­voie en temps réel. Mais c’est une dif­fé­rence mi­neure car NetFlow est aussi ca­pable d’en­voyer les don­nées qua­si­ment en temps réel avec la bonne confi­gu­ra­tion. Vous pou­vez ob­te­nir un re­tard de 10 se­condes. En pra­tique, vous choi­sis­sez le pro­to­cole que vos rou­teurs savent gé­rer. Il est donc im­por­tant de com­prendre plu­sieurs pro­to­coles car tous les rou­teurs ne pro­posent pas tous les pro­tocoles.

Ak­vo­rado re­çoit les flux et les en­ri­chit avec des in­for­ma­tions sup­plé­men­taires. No­tam­ment, il ajoute les in­for­ma­tions liées à la lo­ca­li­sa­tion en uti­li­sant les bases de don­nées de Max­mind. Il ajoute les noms et les des­crip­tions des in­ter­faces en uti­li­sant le pro­to­cole SNMP. Il ajoute les nu­mé­ros d’AS. Les nu­mé­ros d’AS sont le moyen d’iden­ti­fier les or­ga­ni­sa­tions sur In­ter­net. De­puis l’adresse IP, vous ob­te­nez le nu­méro d’AS et le nu­méro d’AS vous per­met d’ob­te­nir le nom.

On ajoute éga­le­ment cer­tains at­tri­buts aux rou­teurs en uti­li­sant des règles de clas­si­fi­ca­tion : on ajoute la lo­ca­li­sa­tion, le rôle, le pro­prié­taire du rou­teur et on ajoute éga­le­ment des at­tri­buts aux in­ter­faces : le four­nis­seur, la fron­tière, la connec­ti­vité (est-ce qu’il s’agit d’une in­ter­face de tran­sit ou de pee­ring). Ces in­for­ma­tions sont très utiles à avoir quand vous avez be­soin d’in­ter­ro­ger les don­nées ré­coltées.

En­suite, Ak­vo­rado sé­ria­lise les flux avec Pro­to­buf et les en­voie vers un clus­ter Kafka. De­puis ré­cem­ment, c’est un pro­jet libre. Nous l’avons pu­blié sur GitHub. Il y a aussi une jo­lie in­ter­face gra­phique pour in­ter­ro­ger les données.

Screenshots (1/3)
Screenshots (2/3)
Screenshots (3/3)

Voici quelques cap­tures d’écran mais je vais vous faire une dé­mons­tration.

Live demo

Vous pou­vez es­sayer la démo sur demo.akvorado.net. Elle tourne sur une pe­tite ma­chine vir­tuelle et uti­lise des don­nées générées.

La page d’ac­cueil montre quelques mé­triques pour in­di­quer si tout fonc­tionne cor­rec­te­ment. Elle af­fiche aussi le der­nier flux reçu. Vous pou­vez voir à quoi cela res­semble. Il y a la date de ré­cep­tion, le nombre d’oc­tets et de pa­quets, le rou­teur qui a en­voyé le flux, son nom.

Les at­tri­buts sui­vants pro­viennent des règles de clas­si­fi­ca­tion. Le taux d’échan­tillon­nage est par­ti­cu­liè­re­ment élevé pour cette démo. Il in­dique que le rou­teur en­voie un flux pour 50000 flux reçu. L’adresse source. Le nu­méro d’AS source. La géo­lo­ca­li­sa­tion n’est pas confi­gu­rée donc on n’ob­tient pas le pays. Vous ob­te­nez le port source.

En ce qui concerne l’in­ter­face d’en­trée, vous avez le nom, la des­crip­tion, la vi­tesse et aussi, via les règles de clas­si­fi­ca­tion, le fait qu’il s’agit d’une in­ter­face ex­terne (connec­tée à In­ter­net). Il s’agit d’une in­ter­face de tran­sit connec­tée à Cogent, qui est un four­nis­seur de tran­sit et vous avez des choses si­mi­laires pour l’adresse des­ti­na­tion, le pays et l’in­ter­face de sortie.

Il y a EType qui in­dique prin­ci­pa­le­ment IPv4 ou IPv6. For­war­ding sta­tus. 64 si­gni­fie que le pa­quet a été routé. 128 si­gni­fie qu’il a été sup­primé. Si vous avez des règles de fil­trage, c’est in­té­res­sant. Et le pro­to­cole : 17 pour UDP, 6 pour TCP. La plu­part des champs sont re­çus avec le flux, mais cer­tains sont ajou­tés plus tard.

La par­tie la plus in­té­res­sante est l’on­glet « vi­sua­li­sa­tion ». Re­gar­dons sur 7 jours. Cela ré­pond à la ques­tion « d’où vient mon tra­fic ? » On voit par exemple dans cette démo que la plu­part du tra­fic pro­vient de Net­flix mais aussi de Google et de Fa­ce­book. Il y a un filtre et vous pou­vez ajou­ter d’autres choses. Par exemple, si on ne veut voir que le tra­fic IPv6. Je peux mettre ce filtre et quand j’ap­plique, j’ob­tiens uni­que­ment le tra­fic IPv6. Comme les don­nées sont gé­né­rées, c’est un peu com­pli­qué de voir la dif­fé­rence. IPv6 re­pré­sente qua­si­ment 60 Gbps tan­dis que le tra­fic to­tal est d’en­vi­ron 90 Gbps.

Une autre re­pré­sen­ta­tion in­té­res­sante que peut four­nir l’in­ter­face web est le gra­phique « san­key ». On voit les trois plus gros par­leurs : Net­flix, Google et Fa­ce­book. Il montre aussi que les 2/3 du tra­fic passent par des four­nis­seurs de tran­sit. Le tiers res­tant passe par des points d’échange.

Un point d’échange est un en­droit où les gens peuvent se connec­ter sur le même switch et échan­ger du tra­fic gra­tui­te­ment ou non. Mais vous n’avez pas la to­ta­lité d’In­ter­net sur un point d’échange. Si vous vou­lez ac­cé­der à la to­ta­lité d’In­ter­net, vous de­vez aussi avoir un four­nis­seur de transit.

On peut par exemple ré­pondre à la ques­tion « com­ment ob­tient-on le tra­fic de Google ? » Il semble que le gros du tra­fic passe par du tran­sit mais une pe­tite par­tie vient des points d’échange. C’est une vi­sua­li­sa­tion très ap­pré­ciée chez les in­gé­nieurs ré­seau. Re­tour­nons à la pré­sentation.

ClickHouse usage

Com­ment avons-nous uti­lisé Click­House ? Ce sont les tables que nous avons ac­tuel­le­ment. Pe­tit aver­tis­se­ment. C’est la pre­mière fois que j’uti­lise Click­House. Je suis un in­gé­nieur ré­seau et non un in­gé­nieur de bases de don­nées. J’ai quelques no­tions, mais c’est as­sez lé­ger. Tout re­tour est le bien­venu et pre­nez tout avec un peu de distance.

Les rec­tangles vio­lets sont les tables, ceux en bleu sont les vues et les blancs sont les dic­tion­naires. J’ai été trop ra­pide et j’ai ou­blié de dire… Non, non, c’est bon, dé­solé. Donc comme je vous di­sais, les flux ar­rivent de Kafka dans la table flows_​2_raw qui n’uti­lise pas le disque. Il y a un consom­ma­teur qui ex­trait les flux et les en­voie dans la table flows qui est la table prin­ci­pale conte­nant tous les flux. Il y a quelques autres tables flows qui agrègent les don­nées sur le temps pour prendre moins de place et ac­cé­lé­rer les re­quêtes. Je don­ne­rai plus de dé­tails par la suite.

Ingestion

Donc l’in­ges­tion se fait en uti­li­sant Kafka. Nous re­ce­vons les don­nées en uti­li­sant le mo­teur Kafka. Les don­nées sont en­co­dées avec le for­mat Pro­to­buf. Les sché­mas Pro­to­buf sont ver­sion­nés. Ils ar­rivent de­puis un su­jet ver­sionné de Kafka et ils sont sto­ckés dans des tables ver­sionnées.

La table flows n’est pas ver­sion­née. Les consom­ma­teurs nor­ma­lisent la don­née pour cor­res­pondre au for­mat de la table flows. Quand il y a un chan­ge­ment de schéma, on in­cré­mente le nu­méro de ver­sion. Cela per­met de faire des mises à jour sans im­pact. Si vous avez d’an­ciens col­lec­teurs qui tournent dans le ré­seau, ils conti­nuent de fonc­tion­ner. Par exemple, ils vont conti­nuer à en­voyer des flux dans le su­jet flows-v1 de Kafka. Ils uti­lisent le for­mat FlowMessagev1. Ils se­ront trai­tés dans la table flows_​1_raw et flows_​1_raw_​consumer nor­ma­lise la donnée.

Il n’y a pas de re­gistre pour les sché­mas. À chaque mise à jour, il faut co­pier les sché­mas sur le ser­veur Click­House. C’est un peu em­bê­tant mais on ne perd pas de don­nées car Kafka garde les mes­sages pen­dant que Click­House re­dé­marre. Click­House sait uti­li­ser un re­gistre quand on uti­lise le for­mat Avro mais je crois que cela n’est pas pos­sible avec Protobuf.

Flows table

La table prin­ci­pale est la table flows. En voici une vue par­tielle. Beau­coup de co­lonnes sont man­quantes. Pour chaque co­lonne Src, vous avez une co­lonne Dst. Pour chaque co­lonne InIf, vous avez une co­lonne OutIf qui cor­res­pond. Il n’y a rien de spé­cial. On uti­lise LowCardinality quand cela a un sens et la table est or­don­née avec TimeReceived car chaque re­quête va uti­liser ça.

Aggregating timeseries

La table flows garde 15 jours de don­nées dans notre confi­gu­ra­tion. Cela re­pré­sente 500 Go. C’est très lent d’in­ter­ro­ger une heure de don­nées et presque im­pos­sible de prendre un jour, deux jours, trois jours. C’est pos­sible, mais très lent. Cela prend plu­sieurs se­condes. Et on veut des ré­ponses ra­pides. On veut aussi gar­der les don­nées pen­dant 5 ans. C’est un pré­re­quis cou­rant pour ce type de be­soins. On veut pou­voir re­gar­der ce qui s’est passé il y a un an sur la même pé­riode. Pour se faire, on doit agré­ger les don­nées quand elles de­viennent plus vieilles. Click­House agrège les don­nées, mais ce n’est pas as­sez flexible pour nous.

RRD-like aggregation

On uti­lise une ap­proche ins­pi­rée des bases RRD. Les bases RRD sont les an­cêtres des bases de don­nées ba­sées sur le temps. Les don­nées sont sto­ckées dans un tam­pon cir­cu­laire et après un cer­tain temps les don­nées sont conso­li­dées en uti­li­sant une fonc­tion spé­ci­fique, comme min, max ou la moyenne. Nous fai­sons ça avec un sum­ming merge tree sur les oc­tets et les pa­quets. On re­tire éga­le­ment les adresses IP et les ports TCP/UDP.

On ne peut pas gar­der les adresses IP pen­dant trop long­temps pour des rai­sons lé­gales mais aussi parce qu’elles contiennent des in­for­ma­tions iden­ti­fiant les abon­nés. De plus, ce n’est pas très in­té­res­sant au-delà d’un cer­tain nombre de jours. Les par­ties in­té­res­santes des adresses IP sur­vivent via les règles de clas­si­fi­ca­tions. On at­tache une ré­gion à une IP. Ainsi que via les nu­mé­ros d’AS : on sait que cette adresse IP ap­par­tient à Fa­ce­book par exemple. Ainsi, au-delà de quelques jours, nous ne gar­dons pas les IP.

Pour les ports TCP et UDP, la rai­son est autre. Nous au­rions pu les gar­der, mais ils sont as­sez aléa­toires. La plu­part du temps, soit le port source, soit le port des­ti­na­tion est connu. Par exemple, les ports 80 ou 443 pour HTTP. Mais l’autre port peut être to­ta­le­ment aléa­toire. Il n’est pas fa­cile de sa­voir quel est le port ser­veur et ainsi, il est plus fa­cile de ne pas les gar­der. De plus, passé quelques jours, ce n’est pas très in­té­res­sant de gar­der les ports et cela aide à com­pres­ser mieux les don­nées. Cela aide à agré­ger plus ef­fi­ca­ce­ment les don­nées en ne gar­dant pas cette in­formation.

À la dif­fé­rence de RRD, on ne garde pas les va­leurs maxi­males. C’est quelque chose qui se­rait à faire à un mo­ment car quand on consi­dère une plage de temps plus grande… Je vais vous mon­trer sur la démo, c’est in­té­res­sant… Vous pou­vez voir ici que le maxi­mum est au­tour de 60 Gbps. Mais si je de­mande des don­nées sur 30 jours, le maxi­mum est un peu plus bas. C’est parce qu’il ne s’agit pas réel­le­ment d’un maxi­mum, mais d’une moyenne se­lon la ré­so­lu­tion de la table. Une moyenne sur 5 mi­nutes et une moyenne sur une heure, cela donne une va­leur maxi­male dif­fé­rente. Mais c’est quelque chose que l’on peut sans doute cor­ri­ger avec Click­House, je pense.

On a donc une table qui agrège sur 1 mi­nute, une table sur 5 mi­nutes et une table sur une heure. Elles gardent les don­nées sur 7 jours, 90 jours et 5 ans. C’est très ef­fi­cace. Ak­vo­rado choi­sit au­to­ma­ti­que­ment la meilleure table se­lon la pé­riode de­man­dée, les co­lonnes de­man­dées (si vous de­man­dez une adresse IP source, il faut uti­li­ser la table prin­cipale).

Materialized view for aggregated table

Je vou­lais aussi vous mon­trer com­ment on rem­plit une table agré­gée car cela montre une fonc­tion­na­lité as­sez in­té­res­sante de Click­House. Vous pou­vez sé­lec­tion­ner tout avec l’étoile, sauf quelques co­lonnes. On veut ex­clure les adresses source et des­ti­na­tion et les ports source et des­ti­na­tion. C’est très fa­cile à faire. On peut aussi rem­pla­cer des co­lonnes. Par exemple, la co­lonne TimeReceived est tron­quée à l’heure pré­cé­dente. C’est une fonc­tion­na­lité ap­préciable.

Exporters table

La table exporters. C’est juste une pe­tite table pour gar­der une liste des rou­teurs, de leurs noms et des in­ter­faces avec leurs des­crip­tions. Elle est uti­li­sée pour la com­plé­tion des filtres dans l’in­ter­face web. Je vou­lais vous mon­trer ça pour illus­trer une autre fonc­tion­na­lité in­té­res­sante de Click­House. Il y a plein de moyens de ma­ni­pu­ler des ta­bleaux. Avec une seule re­quête, je peux rem­plir la table avec ARRAY JOIN et arrayEnumerate.

Dictionaries

Une autre par­tie in­té­res­sante, ce sont les dic­tion­naires. On en uti­lise trois. Un dic­tion­naire pour don­ner un nom à chaque nu­méro d’AS. Il y a en­vi­ron 100 000 nu­mé­ros d’AS. À par­tir d’un nu­méro d’AS, vous pou­vez avoir un nom.

On a un autre dic­tion­naire pour les nu­mé­ros de pro­to­cole. Ainsi, le pro­to­cole 17, c’est UDP. Les pro­to­coles ne changent ja­mais. Les nu­mé­ros d’AS ne changent que de ma­nière peu fré­quentes et c’est prin­ci­pa­le­ment cos­mé­tique. Par exemple, l’AS de Twitch TV peut de­ve­nir plus tard l’AS d’Ama­zon Twitch TV. C’est prin­ci­pa­le­ment cos­mé­tique et c’est uti­lisé que lors de l’af­fi­chage. On uti­lise donc ces dic­tion­naires pen­dant les requêtes.

Le troi­sième dic­tion­naire per­met de faire une cor­res­pon­dance entre les ré­seaux, comme ce­lui-ci, et un nom, un rôle, une ré­gion et un pro­prié­taire. Cette fois, on uti­lise ce dic­tion­naire pen­dant l’in­ges­tion pour ma­té­ria­li­ser cer­taines co­lonnes. On ne veut pas que les don­nées his­to­riques soient al­té­rées quand on al­loue un ré­seau à une ré­gion dif­férente.

Network classification during ingestion

La clas­si­fi­ca­tion des ré­seaux est faite à l’in­ges­tion via la vue ma­té­ria­li­sée où on sé­lec­tionne tout ce que l’on re­çoit de­puis Kafka et on ajoute juste les noms, rôles, etc., en uti­li­sant le dic­tion­naire. Le dic­tion­naire networks uti­lise la mé­thode IP_​TRIE. Cela si­gni­fie qu’à par­tir d’une adresse IP, Click­House peut ra­pi­de­ment ef­fec­tuer une re­cherche pour sé­lec­tion­ner le ré­seau cor­res­pondant.

Ce ne sont pas les seules don­nées qui sont gé­né­rées à par­tir d’autres don­nées. Si vous vous sou­ve­nez, on gé­nère aussi les don­nées de lo­ca­li­sa­tion, les nu­mé­ros d’AS et la clas­si­fi­ca­tion. Pour la géo­lo­ca­li­sa­tion, on ne le fait pas dans Click­House. On au­rait pu le faire dans Click­House avec un dic­tion­naire. Cela au­rait fonc­tionné, mais c’est as­sez simple de le faire dans Ak­vo­rado di­rec­te­ment. La clas­si­fi­ca­tion est faite en uti­li­sant des règles four­nies par l’uti­li­sa­teur. Cette fois, c’est plus simple de le faire dans Ak­vo­rado, pas dans ClickHouse.

User queries

Si vous vous sou­ve­nez de la démo, l’uti­li­sa­teur four­nit une pé­riode, des co­lonnes (dans l’in­ter­face web, on ap­pelle cela des di­men­sions) et une ex­pres­sion pour filtrer.

Filter expression

L’ex­pres­sion de filtre, c’est quelque chose d’as­sez in­té­res­sant. Nos uti­li­sa­teurs sont des in­gé­nieurs ré­seau. Ils peuvent connaître SQL, mais ce ne sont pas des spé­cia­listes. On uti­lise donc un lan­gage qui res­semble à SQL pour les filtres et on le tra­duit vers le SQL uti­lisé par Click­House avec un ana­ly­seur syn­taxique.

Notre do­maine est plus simple, donc on prend des rac­cour­cis pour sim­pli­fier cer­taines choses. Par exemple, on peut don­ner les adresses IP di­rec­te­ment. On peut uti­li­ser des guille­mets simples ou doubles, il n’y a pas de dif­fé­rences. On peut uti­li­ser des constantes. EType est nor­ma­le­ment un en­tier, mais on peut don­ner un nom. On es­saie de rendre les choses plus simple. L’ana­ly­seur tra­duit ça vers le SQL de ClickHouse.

C’est aussi sûr parce qu’on ana­lyse le filtre et on construit la re­quête SQL. Si vous uti­li­sez une co­lonne in­con­nue ou faites une er­reur de syn­taxe, ou quelque chose comme ça, l’ana­ly­seur va échouer avec un mes­sage d’er­reur et on ne construit pas de re­quête. On ne peut pas in­jec­ter des don­nées dans Click­House, même si Click­House n’est déjà pas très vul­né­rable à ce type d’at­taque, ce n’est pas pos­sible car l’ana­ly­seur doit com­prendre ce que vous vou­lez pour le tra­duire à ClickHouse.

User query to ClickHouse query

En­suite, l’in­té­gra­lité de la re­quête de l’uti­li­sa­teur est trans­for­mée en SQL. Click­House aide beau­coup pour re­tour­ner des don­nées qui sont di­rec­te­ment uti­li­sables par l’in­ter­face web. Ainsi, quand il y a des don­nées qui manquent, on peut au­to­ma­ti­que­ment com­plé­ter avec des 0. C’est ce qui est fait ici.

No­tez que j’uti­lise la table agré­gée à 5 mi­nutes. Il y a une va­leur ma­gique ici, 600. On adapte la ré­so­lu­tion de­man­dée par l’uti­li­sa­teur. Par exemple, il peut de­man­der une va­leur toutes les 632 se­condes. On adapte pour cor­res­pondre à la ré­so­lu­tion de la table. Cela doit être un mul­tiple de la ré­so­lu­tion de la table pour que le ré­sul­tat soit cor­rect. Comme la ré­so­lu­tion est de 300 se­condes et que l’uti­li­sa­teur a de­mandé un point en­vi­ron toutes les 600 se­condes, on va lui don­ner un point toutes les 600 secondes.

Il y a une sous-re­quête. L’uti­li­sa­teur a de­mandé à grou­per se­lon les nu­mé­ros d’AS. On va cal­cu­ler les 10 pre­miers AS cor­res­pon­dant au même filtre sur la même pé­riode. On sé­lec­tionne les 10 plus gros AS. Pour chaque nu­méro d’AS que l’on ob­tient, s’il fait par­tie du top 10, on af­fiche le nu­méro d’AS avec son nom en uti­li­sant le dic­tion­naire. Si­non, on af­fiche juste Others. Ainsi, on ne re­tourne pas une énorme liste d’AS à l’uti­lisateur.

Go bindings

Pas­sons main­te­nant à Ak­vo­rado. C’est écrit en Go. On uti­lise clickhouse-go/v2 qui uti­lise le pro­to­cole client/serveur na­tif. C’est une in­ter­face de bas ni­veau, mais cela nous convient parce que les abs­trac­tions viennent sou­vent avec des res­tric­tions. La do­cu­men­ta­tion n’est pas ter­rible. Elle ne cor­res­pond pas aux stan­dards ha­bi­tuels de Go. Il y a quelques exemples pour com­prendre mais cela fonc­tionne très bien sinon.

On écrit pas mal de tests uni­taires mais ils ne tournent pas sur une vraie base de don­nées. Pour chaque re­quête, on ren­voie des ré­ponses pré-cal­cu­lées en uti­li­sant un mock gé­néré par GoMock. Par exemple, du­rant les tests, cette re­quête est ef­fec­tuée. GoMock gé­nère une fausse fonc­tion qui va ré­pondre avec ces ré­sul­tats : customer-1, customer-2, customer-3. Cela nous per­met de faire de nom­breux tests ra­pi­de­ment sans se re­po­ser sur une base de don­nées externe.

Migrations

La der­nière chose dont je veux par­ler, ce sont les mi­gra­tions. Avec une base de don­nées tra­di­tion­nelle, un lo­gi­ciel va sou­vent pro­po­ser des mi­gra­tions à exé­cu­ter lors des mises à jour. Avec Click­House, c’est plus com­pli­qué, parce qu’on ne peut pas faire ce qu’on veut. On a donc un chef d’or­chestre qui va gé­rer les dif­fé­rents com­po­sants, in­ternes et ex­ternes, y com­pris Click­House et Kafka. Il va gé­rer les mi­gra­tions et c’est fait avec du code en Go. Chaque étape de mi­gra­tion a une des­crip­tion, un test et une fonc­tion. Il n’y a pas d’état : chaque étape est exé­cu­tée au dé­mar­rage. Le test per­met de sau­ter une étape qui n’est pas né­ces­saire. On ne gère pas les re­tours en arrière.

Steps

Il y a une étape pour créer les dic­tion­naires : pro­to­cole, ASN et ré­seau. Une autre pour créer les tables flows, la prin­ci­pale et les agré­gées. Si vous met­tez à jour de­puis une an­cienne ver­sion, il y a une étape qui ajoute les co­lonnes man­quantes. Il y a une étape pour créer les consom­ma­teurs des tables flows. Une étape pour confi­gu­rer les TTL. Cela si­gni­fie que si l’uti­li­sa­teur change la confi­gu­ra­tion des TTL et re­dé­marre, les TTL se­ront ef­fec­ti­ve­ment mis à jour. Et une étape pour la table exporters et les tables « raw ».

Migration for dictionaries and views

Il y a deux types d’étapes. Il y a celles qui mo­di­fient les dic­tion­naires et les vues. On n’a pas be­soin de gar­der des don­nées pour celles-ci. On fait deux tests. On teste si la table existe. La table, la vue ou le dic­tion­naire existe. Et on teste si la table a les bonnes co­lonnes aux bons en­droits. C’est fait en créant un conden­sat du nom, du type et de la po­si­tion sur la table sys­tème columns et en le com­pa­rant à une va­leur fixe. C’est pas mal que Click­House ex­pose beau­coup de choses dans les tables sys­tèmes car cela nous per­met de faire ça.

Migration for data tables

Le deuxième type d’étapes, c’est quand on veut conser­ver les don­nées. Dans ce cas, on uti­lise des mu­ta­tions. On teste « est-ce qu’on a déjà la co­lonne que l’on veut ajou­ter ? » Dans le cas contraire, on uti­lise ALTER TABLE pour ajou­ter la co­lonne. Il y a beau­coup de li­mites sur ce qu’on peut mo­di­fier, mais avec quelques com­pro­mis, jusqu’à au­jourd’hui, on a été ca­pable de faire ce qu’on voulait.

Testing migrations

Les mi­gra­tions sont tes­tées. Cela fait par­tie des tests au­to­ma­tiques. Il y a une base de don­nées Click­House qui est dé­mar­rée dans un conte­neur. Les mi­gra­tions sont tes­tées de­puis des états va­riés, in­cluant une base vide. Chaque test doit don­ner le même état fi­nal et à chaque fois qu’on ajoute une étape de mi­gra­tion, l’état fi­nal est en­re­gis­tré pour être uti­lisé dans des fu­turs tests, via la re­quête af­fi­chée ici. Cela nous per­met de nous as­su­rer qu’un uti­li­sa­teur peut mi­grer d’une ver­sion à une autre.

Single node setup

Notre confi­gu­ra­tion est plu­tôt pe­tite. Tout tourne dans une seule VM, y com­pris Kafka et Ak­vo­rado. On fait tout tour­ner dans des conte­neurs avec docker-compose. C’est une confi­gu­ra­tion très simple. 1 To de disque, 64 Go de mé­moire. Pour le mo­ment, on a 30 000 flux/s mais la cible, c’est 100 000 flux/s. Vous avez des gra­phiques pour le CPU, la mé­moire et le disque. Tout est as­sez faible, mais il y a aussi le sys­tème anti-DDoS qui tourne en fond, toutes les 5 se­condes, en fai­sant des re­quêtes. Il gé­nère une bonne par­tie de la charge.

Opinions about ClickHouse

En conclu­sion, mon opi­nion sur Click­House. Fa­cile d’ac­cès, bonne do­cu­men­ta­tion. Il y a beau­coup de fonc­tions dis­po­nibles. Les fonc­tions liées aux chaînes par exemple, avec la conver­sion vers des quan­ti­tés fa­ciles à lire. On a vrai­ment l’im­pres­sion que c’est quelque chose qui cherche à ré­soudre di­rec­te­ment les pro­blèmes dans Click­House plu­tôt que de dé­lé­guer cela à une autre couche. Cela donne un peu l’im­pres­sion d’être magique.

Une autre so­lu­tion po­pu­laire pour cet usage est ElasticSearch. Contrai­re­ment à ElasticSearch, Click­House est très ra­pide sans ef­fort et reste très ra­pide. Gé­rer un clus­ter ElasticSearch est beau­coup plus dif­fi­cile pour ce cas d’usage. Il faut un peu de temps pour com­prendre les tables agré­gées et on a vite fait de faire quelque chose qui pa­raît cor­rect mais qui ne l’est pas. Par exemple, en agré­gant en uti­li­sant des moyennes, on ob­tient pas ce que l’on at­tend. Ce­pen­dant, Click­House a des fonc­tions pour faire ça.

Questions?

C’est tout pour moi. Avez-vous des questions ?

Questions#

Vincent, c’était un ex­posé ab­so­lu­ment gé­nial et on a quelques ques­tions en at­tente. Je peux les voir. Il y en a deux de Gi­lad. La pre­mière est Ak­vo­rado ne prend en compte que les pro­to­coles de la couche 3, com­ment il dé­tecte de quelle ap­pli­ca­tion il s’agit ?

Il s’agit d’une li­mi­ta­tion des pro­to­coles NetFlow/IPFIX/sFlow. Ces pro­to­coles ne col­lectent que des in­for­ma­tions de couche 4. NetFlow/IPFIX sont li­mi­tés aux in­for­ma­tions de la couche 4, plus quelques mé­ta­don­nées comme les nu­mé­ros d’AS. sFlow peut voir plus loin à l’in­té­rieur des pa­quets. Vous pou­vez ob­te­nir les en­têtes de ni­veau 4 ainsi que 200 oc­tets dans chaque pa­quet re­tourné. Vous pou­vez faire ça mais Ak­vo­rado n’uti­lise pas ça pour le moment.

Vous pou­vez de­vi­ner l’ap­pli­ca­tion en uti­li­sant les ports ou les adresses IP. Cela dé­pend. Par exemple, si vous avez un clus­ter Ku­ber­netes, l’adresse IP doit vous don­ner l’ap­pli­ca­tion cible. Vous pou­vez uti­li­ser ça. Pour le mo­ment, vous ne pou­vez pas vrai­ment sa­voir à coup sûr que c’est une re­quête HTTP. Vous ne pou­vez pas sa­voir quelle re­quête HTTP a été faite. Ce n’est pas ce type d’outils.

Cool. La ques­tion sui­vante de Gi­lad a mon nom de­dans, mais je ne sais pas si je peux vrai­ment y ré­pondre. Gi­lad de­mande s’il ne se­rait pas mieux d’avoir une seule table plu­tôt que 3 tables. Gi­lad, peux-tu par­ler ? Je crois que tu peux par­ler. Qu’as-tu à l’es­prit avec cette question ?

Oui. Je vois que tu as trois tables, une pour l’agré­ga­tion à 1 mi­nute, une pour 5 mi­nutes et une pour 1 heure. Est-ce que tu as testé avec une seule table en uti­li­sant le TTL pour agré­ger les don­nées à 1 mi­nute, de­puis de 1 à 5 mi­nutes, puis de 5 mi­nutes à 1 heure, tout dans la même table avec une co­lonne pour in­di­quer la ré­solution ?

Oui. J’ai es­sayé, mais quand on es­saie d’agré­ger des don­nées dans la même table, il y a un pré­re­quis sur la clé pri­maire… Je peux me trom­per mais je n’ai pas réussi à faire ça car la clé pri­maire ne doit pas changer.

Dans la clé pri­maire, nous avons TimeReceived et nous vou­lons la tron­quer à la mi­nute la plus proche, aux 5 mi­nutes les plus proches et à l’heure la plus proche. Je peux faire ça avec une co­lonne pour TimeReceived, une autre co­lonne avec TimeReceived tron­qué à la mi­nute, TimeReceived tron­qué aux 5 mi­nutes et TimeReceived tron­qué à l’heure. Je dois avoir les trois co­lonnes qui existent pour per­mettre l’agré­ga­tion. Cela pa­raît plus com­pli­qué mais il y a peut-être une meilleure ap­proche. Je se­rais in­té­ressé de le savoir.

Cela au­rait pu fonc­tion­ner, mais comme on ne peut pas mo­di­fier… cela veut dire que si je veux ajou­ter une nou­velle agré­ga­tion, par exemple en ajou­tant une agré­ga­tion à 10 mi­nutes, je ne peux pas mo­di­fier la table car la clé pri­maire ne peut pas chan­ger. C’est la rai­son prin­ci­pale qui fait que j’ai choisi 3 tables même si cela rend l’ap­pli­ca­tion un peu plus com­plexe car on doit choi­sir la bonne table.

Je vou­lais dire que nous avons une so­lu­tion as­sez si­mi­laire et que nous avons uti­lisé une seule table mais on a pas testé les per­for­mances entre plu­sieurs tables et une seule. C’était in­té­res­sant de demander.

Gi­lad, tu avais une autre ques­tion pour Vincent, à pro­pos de com­ment tu as dé­ployé Click­House, est-ce que tu as uti­lisé Ku­ber­netes. Vincent, il semble que tu as uti­lisé docker-compose, est-ce bien ça ?

Oui. Parce que c’est tou­jours un peu un PoC, mais comme cela marche si bien, on a pas es­sayé de faire mieux. Je ne m’at­ten­dais pas que tout tienne dans une seule VM. Pour le mo­ment, c’est tou­jours un peu un es­sai, mais on est allé en pro­duc­tion comme ça. Donc c’est une seule VM avec docker-compose. Vous faites docker-compose up et vous ob­te­nez quelque chose qui fonc­tionne. Donc tout tourne dans des conte­neurs, y com­pris Click­House. Il n’y a pas de clus­ter. C’est un dé­ploie­ment sur un seul nœud.

Cool. Oui, c’est un très bon exemple. J’ai une ques­tion. Je n’ai pas vu de ques­tions sur You­tube. Si vous vou­lez po­ser des ques­tions, vous pou­vez le faire dans le chat. Vincent, j’en ai une. L’in­ter­face web est su­perbe. Com­ment as-tu construit ça ?

Ça a été un peu pé­nible car je ne suis pas dev Java­Script. Il s’agit de vue.js. Ce­lui-ci. C’est ce fra­me­work. Avec TailwindCSS. Ce fra­me­work. C’est tout. Je pense que c’est ex­pli­qué un peu dans la do­cu­men­ta­tion. C’est open source, donc vous pou­vez al­ler re­gar­der. Un com­po­sant im­por­tant, c’est les gra­phiques. Il s’agit de ECharts. C’est un pro­jet Apache qui s’ap­pelle ECharts. C’est lui qui fait les gra­phiques et c’est un su­per pro­jet si vous avez be­soin de dé­ve­lop­per une in­ter­face avec des gra­phiques. C’est très ro­buste et po­ly­va­lent. J’ai mis pas mal de temps avant de le trouver.

Oui, elle est su­perbe et l’in­ter­ac­ti­vité est ex­cep­tion­nelle. C’est très cool. Bien. Y a-t-il d’autres ques­tions pour Vincent avant de pas­ser à la suite ? Oui, il y en a une autre. Est-ce que vous avez un plan pour ana­ly­ser HTTP ? À pro­pos de la couche 7.

Chez Free, on uti­lise le pro­to­cole NetFlow et ce pro­to­cole ne per­met pas d’al­ler re­gar­der ce qui se passe en couche 7. On au­rait dû uti­li­ser sFlow. Aussi, on est un FAI et on a pas vrai­ment be­soin de ça. Donc, rien n’est pla­ni­fié pour le mo­ment. C’est prin­ci­pa­le­ment pour les opé­ra­teurs ré­seaux te­le­com et ceux en da­ta­cen­ter. Cela pour­rait être in­té­res­sant, mais pas prévu pour le moment.

Merci ! Merci pour toutes ces ques­tions. Je crois que je ne vois pas d’autres ques­tions sauf si je me trompe. Vincent. Merci beau­coup pour cette pré­sen­ta­tion. C’était très en­ri­chis­sant. Et je pense qu’on peut t’ac­cor­der le titre d’in­gé­nieur de bases de don­nées ho­no­raire. Tu as tout bien fait.