Automatiser votre infrastructure Kafka pour l'Event Streaming

Magazine
Marque
Linux Pratique
HS n°
Numéro
57
Mois de parution
avril 2023
Spécialité(s)


Résumé

Le projet open source Apache Kafka est une plateforme, distribuée, d’event streaming, employée par de nombreuses entreprises pour implémenter leurs solutions logicielles. Mais, de manière concrète de quoi s’agit-il ? Qu’est-ce que Kafka entend par la notion d’event streaming ? Quelques éléments de réponse dans cet article d’introduction à son déploiement et utilisation.


Body

Comme de nombreuses solutions logicielles élaborées, Kafka vient avec son jargon et ses concepts clés. Afin de bien appréhender son fonctionnement interne, nous allons donc commencer cet article en explicitant les éléments de son architecture et la terminologie utilisée par le projet pour désigner ceux-ci ainsi que la manière dont il conceptualise les données qu’il manipule.

1. Concepts clés de Kafka

Le projet Kafka se définit, avant tout, comme une plateforme d’event streaming, donc nous allons commencer par expliciter la signification de ce terme. En essence, il s’agit de capturer des données, en temps réel, depuis des sources diverses et variées, telles que des bases de données, des capteurs, des appareils mobiles, des microservices, et toutes autres sources logiciels. Après cette capture, ces informations peuvent être stockées pour être utilisées plus tard, ou être directement manipulées ou éditées, ou peuvent encore simplement déclencher d’autres processus associés, le tout, en temps réel. Dans ce contexte, il importe également de proprement diriger ou rediriger les informations vers les systèmes appropriés. En essence, cette technologie garantit un flux continu de données, et de leurs interprétations, afin que l’information adéquate soit disponible dès que possible.

Sans surprise, cette approche a de nombreux cas d’utilisation. On peut traiter ainsi des paiements en ligne ou des transactions financières, ou encore l’échange de stock. On peut également l’employer afin de suivre et observer une flotte de véhicules, le déplacement de colis en temps réel, ou bien collecter les données des clients et utilisateurs d’une application, pour réagir immédiatement à tout problème. Il y a même des applications médicales, on peut utiliser cette approche dans l’intention de surveiller les patients d’un hôpital et s’assurer que l’ensemble des traitements nécessaires soit dispensé, à la cadence requise. Dans notre industrie, on trouve aussi ce type de technologie au cœur d’architectures dites event driven et/ou de l’implémentation de microservices.

Revenons maintenant à Kafka en lui-même. Ce projet combine trois capacités clés, qui vont permettre à son utilisateur de construire sa solution logicielle, avec l’approche event streaming, en respectant le processus suivant :

  1. Publier (opération d’écriture) et souscrire (opération de lecture) à un flux d’évènements, incluant l’import ou l’export, en continu, des données depuis ou vers d’autres systèmes.
  2. Persister ces flux d’événements de manière durable, et fiable.
  3. Et effectuer le traitement nécessaire de ceux-ci, directement lorsqu’ils sont émis, ou plus tard, à la demande.

Kafka fournit l’ensemble de ses fonctionnalités de manière distribuée, et est ainsi en mesure de tenir la montée en charge, et d’être également résistant aux pannes. Le logiciel peut être déployé librement sur un système physique, une machine virtuelle, et bien sûr sous forme de conteneur, qu’il s’agisse d’un déploiement en interne ou sur un cloud.

Évoquons maintenant, dans ses grandes lignes, le fonctionnement interne de Kafka. Il est constitué d’une collection de clients et de serveurs distribués, qui communiquent à l’aide d’un protocole TCP. Celui-ci a été développé afin d’être le plus performant possible, quel que soit le contexte d’usage du logiciel. Ainsi, il n’y a pas de prérequis réseau à son fonctionnement, qui interdirait son utilisation au sein de cloud ou d’infrastructure physique ou virtuelle.

Au sein de son architecture, les serveurs de Kafka ont différentes fonctions, et peuvent être déployés au travers de plusieurs datacenters ou de zones d’un cloud. Certains d’entre eux forment une couche de stockage, que l’on désigne par le terme brokers. D’autres importent de manière continue des données, et s’intègrent ainsi avec des systèmes existants tels que des bases de données, ou d’autres instances de Kafka.

Tout ceci a été conçu avec la robustesse et la tolérance aux pannes à l’esprit. Ce qui veut dire que, si l’un de ces serveurs devient indisponible, les autres sont en mesure de reprendre sa charge et ses opérations, garantissant également la continuité des traitements en cours, sans aucune perte d’information.

De l’autre côté de son architecture, on trouve les clients. Ceux-ci permettent aux utilisateurs de Kafka de construire leur application distribuée et leurs microservices, qui vont lire ou écrire (ou traiter) les événements reçus, en parallèle, et de manière, encore une fois, tolérante aux pannes, qu’il s’agisse d’un incident réseau ou de l’indisponibilité d’une ou plusieurs machines.

Il faut noter que Kafka vient également avec plusieurs logiciels clients, prêts à l’emploi. Ceux-ci sont implémentés dans différentes technologies typiques de l’écosystème Java, telles que Scala, mais aussi d’autres, comme Go, Python ou encore C/C++. En outre, le logiciel disposant de nombreuses API REST, il est possible de l’intégrer à pratiquement toute technologie.

1.1 Terminologie

L’outil et sa problématique, décrits dans les grandes lignes, développons maintenant ses concepts clés et sa terminologie. Le premier élément de son lexique à appréhender correctement est, évidemment, la notion d’event. En essence, elle désigne l’enregistrement d’une information émise au sein d’un système. Celle-ci peut être une donnée purement logicielle ou le reflet d’une action ou d’un changement d’état dans le monde « physique ». Il peut s’agir, par exemple, de l’arrivée d’un colis à destination, de la souscription par un client d’une police d’assurance, de la réception de fonds sur un compte en banque, ou encore simplement de l’enregistrement d’une ligne dans une base de données. Notons sur ce point que la documentation réfère à ces événements également sous le terme d’enregistrements (record) ou de messages.

D’une manière générale, si une application lit ou écrit des données avec Kafka, ceux-ci prennent la forme d’événements. En termes de modèle de données, ces informations sont associées à une clé, une valeur, et un timestamp. On peut aussi ajouter un ensemble de métadonnées sous forme d’en tête (headers).

Voici, un exemple simple, d’un événement :

  • Clé : “DoorOpens”
  • Valeur : “la clé de Sophie a ouvert la porte de la maison, de l’intérieur.”
  • Timestamp : "Mar. 25, 2022 at 7:06 a.m."

Toujours dans le jargon du logiciel, le terme suivant à retenir est celui de producteurs (Producers). Dans le contexte de Kafka, il s’agit d’applications clientes qui publient des données (opération en écriture) et qui en consomment d’autres, en souscrivant auprès d’autres systèmes. Il s’agit alors, dans ce dernier cas, d’opérations de lecture et de traitement de données. Il est important de retenir que, dans le cadre d’un déploiement du logiciel, les consommateurs comme les producteurs sont entièrement séparés. L’un ignore tout de l’implémentation de l’autre, ce qui est un élément essentiel au fonctionnement distribué et tolérant en panne de Kafka.

Un autre terme à bien comprendre dans le contexte de ce logiciel est la notion de sujet de discussion ou topic en anglais. Ceux-ci permettent d’organiser et de stocker de manière durable les événements enregistrés par le système. De manière simpliste, un topic est comparable à un répertoire d’un système de fichiers pour l’ensemble des événements. Ces derniers ne sont, dans cette analogie, que des fichiers au sein de celui-ci. Ainsi, on peut imaginer un topic « employé » contenant les informations de chaque membre du personnel d’une société.

Un point important à retenir ici est que les topics sont toujours des producteurs multiples et des souscripteurs multiples. Ainsi, l’un d’eux peut souscrire à aucun producteur, un seul ou plusieurs, et réciproquement.

Les lecteurs familiers avec le monde des Middleware Oriented Messaging (MOM), tels que les implémentations de la spécification JMS comme Apache MQ, verront une analogie directe avec la notion de topics au sein de ce type de système. Cependant, il y a une différence cruciale avec ceux-ci : les événements peuvent être lus et relus autant de fois que nécessaire. À l’intérieur d’un MOM, un message ne peut être consommé qu’une seule fois.

En outre, les événements ne sont pas automatiquement effacés après leur utilisation. Leur durée de vie au sein du système est définie selon le paramétrage du topic. Celui-ci indique combien de temps un événement doit être conservé avant d’être retiré du système. Il faut souligner ici que, grâce à son architecture, les performances de Kafka sont constantes, quelle que soit la taille du jeu de données, ainsi préserver celles-ci, sur une longue période, n’a pas d’impact sur l’efficacité du système.

Ces topics peuvent être partitionnés (partitioned), ce qui signifie que l’un d’entre eux peut être réparti sur un certain nombre de composants, désignés par le terme de buckets. Ces derniers peuvent être situés au sein de différents brokers. Cette organisation, fondamentalement distribuée des données, est clé, car elle permet au logiciel de tenir la montée en charge. Cette approche autorise, en effet, aux applications de lire et d’écrire des données de ou vers différents brokers au même instant.

Lorsqu’un nouvel événement est publié au sein d’un topic, il est, en fait, ajouté à l’une de ces partitions. Un événement doté de la même clé qu’un autre, par exemple l’identifiant d’une voiture, est écrit dans la même partition. En outre, le logiciel assure que tout consommateur d’un topic et de sa partition récupère les événements dans l’ordre exact dans lequel ils ont été ajoutés.

1.2 Distribution et réplication des données

Le dernier élément de langage à retenir dans le cadre de l’étude de Kafka est la notion de réplication. En effet, pour garantir la tolérance aux pannes et une haute disponibilité du système, chaque topic peut être répliqué, et ceci même sur différents centres de données ou zones d’un cloud. Ainsi, il y a toujours de multiples brokers détenant une copie des données, au cas où l’un d’eux devient indisponible. La plupart des systèmes en production ont jusqu’à trois instances du même jeu de données. Notez que cette réplication est réalisée au niveau de la partition d’un topic.

Les concepts clés et les cas d’utilisations de Kafka désormais explicités, la suite de cet article va se concentrer sur la mise en place et le déploiement de la solution. Afin de garantir une installation documentée et reproductible, nous emploierons Ansible pour effectuer les différentes étapes nécessaires à celle-ci. La syntaxe de l’outil d’automatisation ne sera pas expliquée dans cet article, pour rester concentrés sur notre cas d’étude, Kafka. Cependant, celle-ci est simple à appréhender. Le lecteur intéressé par le sujet pourra se référer aux précédents articles publiés sur Ansible.

2. Déploiement à l’aide d’Ansible

2.1 Prérequis

Nous allons commencer le déploiement de Kafka par la mise en place des prérequis suivants :

  • récupération de l’archive Kafka depuis le site du projet ;
  • décompression de celle-ci dans le répertoire d’installation ;
  • installation dans la machine virtuelle Java requise pour son fonctionnement.
---
- name: "Automate Kafka install setup"
  hosts: localhost
  vars:
    kafka_archive_file: kafka_2.13-3.3.1.tgz
    kafka_download_url: "https://dlcdn.apache.org/kafka/3.3.1/{{ kafka_archive_file }}"
    kafka_download_dir: /opt
    kafka_install_dir: /opt
    kafka_openjdk_version: 17
    kafka_home: "{{ kafka_install_dir }}/kafka_2.13-3.3.1/"
    ...
  tasks:
    - name: "Download Kafka: {{ kafka_download_url }}."
      ansible.builtin.get_url:
        url: "{{ kafka_download_url }}"
        dest: "{{ kafka_download_dir }}"
 
    - name: "Unarchive software to {{ kafka_install_dir }}"
      ansible.builtin.unarchive:
        src: "{{ kafka_download_dir }}/{{ kafka_archive_file }}"
        dest: "{{ kafka_install_dir }}"
 
    - name: "Ensure OpenJDK is installed."
      ansible.builtin.package:
        name: "java-{{ kafka_openjdk_version }}-openjdk-headless"
        state: present
      when:
- kafka_openjdk_version is defined

Ces opérations réalisées lors de l’exécution du playbook Ansible, nous avons tous les éléments nécessaires pour déployer, sur le système cible (en l’occurrence, le poste de travail utilisé) les différents composants de Kafka.

2.2 Démarrage des services de Kafka

Par sa nature profondément distribuée, Kafka requiert l’usage de plusieurs services, qui vont interagir les uns avec les autres. Tous ceux-ci peuvent être démarrés, à l’aide de scripts fournis par le projet.

Nous allons donc commencer par concevoir un playbook Ansible dédié à leur démarrage, que nous utiliserons ensuite pour lancer chaque composant :

# cat start_server.yml
---
- ansible.builtin.assert:
    that:
      - server_name is defined
      - server_config is defined
      - server_started is defined
      - server_config
    quiet: True
 
- block:
    - name: "Ensure {{ server_name }} is running"
      ansible.builtin.shell: "{{ server_start }} -daemon {{ server_config }}"
      register: server_start_status
  
    - ansible.builtin.debug:
        var: server_start_status
 
    - name: "Ensures server started successfully"
      ansible.builtin.assert:
        that:
          - server_start_status is defined
          - server_start_status.rc is defined
          - server_start_status.rc == 0
  when:
    - server_started is defined and not server_started

Par souci de simplicité, et pour rester didactiques, nous avons choisi de ne pas gérer, au sein du playbook, l’état du serveur. Ainsi, si nous avons exécuté le script ci-dessus auparavant et que le serveur associé est déjà démarré, il est nécessaire d’ajouter la variable dédiée à celui-ci qui indique qu’il a été préalablement lancé, afin que l’outil d’automatisation n’exécute pas à nouveau cette opération. Cette approche est loin d’être élégante et de respecter les bonnes pratiques de l’utilisation d’Ansible, mais elle nous permet ici, dans le cadre de cet article, de ne pas nous égarer en devant intégrer complètement chacun des services dans systemd, ou un autre gestionnaire de service.

Voyons maintenant la mise en place du premier service requis par Kafka, Zookeeper :

- name: "Automate Kafka install setup"
  hosts: localhost
  vars:
    ...
    kafka_zookeeper_config: "{{ kafka_home }}/config/zookeeper.properties"
    kafka_zookeeper_server_start: "{{ kafka_home }}/bin/zookeeper-server-start.sh"
    ...
    - ansible.builtin.include_tasks: start_server.yml
      vars:
        server_name: 'kafka_zookeeper'
        server_start: "{{ kafka_zookeeper_server_start }}"
        server_config: "{{ kafka_zookeeper_config }}"
        server_started: "{{ kafka_zookeeper_already_running | default(False) }}"

Une fois Zookeeper démarré sans incident, nous pouvons maintenant mettre en place le second service requis par l’architecture de Kafka, le broker :

- name: "Automate Kafka install setup"
  hosts: localhost
  vars:
    ...
    kafka_broker_server_start: "{{ kafka_home }}/bin/kafka-server-start.sh"
    kafka_broker_config: "{{ kafka_home }}/config/server.properties"
    ...
    - ansible.builtin.include_tasks: start_server.yml
      vars:
        server_name: 'kafka_broker'
        server_start: "{{ kafka_broker_server_start }}"
        server_config: "{{ kafka_broker_config }}"
        server_started: "{{ kafka_broker_already_running | default(False) }}"

En guise d’alternative à Zookeeper, Kafka autorise également l’utilisation de Kraft, que nous ne présenterons pas ici.

2.3 Déploiement d’un topic

Le broker désormais fonctionnel, nous pouvons maintenant mettre en place un topic dans lequel nous ajouterons des événements par la suite. Là encore, Kafka vient avec un script, simple d’utilisation, qui permet de créer un topic :

---
- name: "Automate Kafka install setup"
  hosts: localhost
  vars:
    ...
    topic_name: first-topic
    topic_already_exists_err_msg: "Topic '{{ topic_name }}' already exists"
    bootstrap_server_host: localhost
    boostrap_server_port: 9092
...
    - block:
        - name: "Ensures topic '{{ topic_name }}' exists."
          ansible.builtin.command: "{{ kafka_home }}/bin/kafka-topics.sh --create --topic {{ topic_name }} --bootstrap-server {{ bootstrap_server_host }}:{{ boostrap_server_port }}"
          register: topic_status
      rescue:
        - name: "Ensures errors are only due to the topic already existing."
          ansible.builtin.assert:
            that:
              - topic_status is defined and topic_status.stdout is defined
              - topic_already_exists_err_msg in topic_status.stdout
            fail_msg: "{{ topic_status.stdout }}"

On notera que, ici, nous avons pris soin de placer l’exécution de ce script au sein d’un bloc, afin de détecter l’erreur associée à l’existence du topic. Ainsi, lors de la seconde exécution de notre playbook, celle-ci ne sera pas interrompue par l’erreur retournée par le script.

2.4 Vérification du topic

Afin de confirmer que le topic a bien été créé sans erreur et que celui-ci est bien disponible, nous allons ajouter quelques tâches de vérification à notre playbook Ansible :

- name: "Load information on topic: {{ topic_name }}."
       ansible.builtin.command: "{{ kafka_home }}/bin/kafka-topics.sh --describe --topic {{ topic_name }} --bootstrap-server {{ bootstrap_server_host }}:{{ boostrap_server_port }}"
       register: topic_info
       changed_when: False
 
- name: "Verify that information on {{ topic_name }} could be retrieved without any errors."
       ansible.builtin.assert:
         that:
           - topic_info is defined
           - topic_info.rc is defined and topic_info.rc == 0
           - topic_info.stdout is defined
         quiet: True
  
- name: "Display information on topic: {{ topic_name }}."
       ansible.builtin.debug:
         var: topic_info.stdout

Avec ces deux éléments (Zookeeper et le broker) proprement configurés, installés et démarrés, nous pouvons maintenant placer des données au sein de notre topic. Pour ce faire, là encore, le projet Kafka fournit un script, simple d’utilisation, qui permet d’ajouter directement des événements :

$ /opt/kafka_2.13-3.3.1/bin/kafka-console-producer.sh --topic quickstart-events --bootstrap-server localhost:9092
First Event
Second One
Third One

Notez qu’il s’agit d’un script interactif, il faut donc, après l’avoir lancé, saisir les données à ajouter, un événement par ligne, puis interrompre l’exécution de celui-ci.

Observons également que nous avons opté pour associer un numéro à chaque évènement, afin de démontrer, lors de la prochaine étape, ci-dessous, que l’ordre d’arrivée des événements est bien respecté.

$ /opt/kafka_2.13-3.3.1/bin/kafka-console-consumer.sh --topic quickstart-events --from-beginning --bootstrap-server localhost:9092
First Event
Second One
Third One

Conclusion

Cet article, nous l’espérons, aura présenté, dans ses grandes lignes, tout l’intérêt de déployer et utiliser Kafka, mais également de la facilité de son automatisation, à l’aide d’Ansible. Bien évidemment, il ne s’agit ici que d’une simple introduction, décrivant comment mettre en place les composants élémentaires de la solution. Il reste encore à découvrir comment intégrer ses brokers avec des sources d’événements et d’étudier ses capacités de haute disponibilité, en employant plusieurs brokers et en simulant des incidents sur le système. Cependant, ces premiers pas effectués dans cet article nous donnent les bases requises pour une telle exploration, plus en profondeur, de Kafka.



Article rédigé par

Par le(s) même(s) auteur(s)

Déployer une application Quarkus avec Ansible

Magazine
Marque
Linux Pratique
Numéro
139
Mois de parution
septembre 2023
Spécialité(s)
Résumé

Le cadre de développement et d’exécution Java nommé Quarkus, déjà évoqué dans les pages de ce magazine, est une fabuleuse solution pour implémenter des microservices, de manière légère et efficace. Aujourd’hui, dans ce nouvel article, nous proposons d’automatiser la construction et le déploiement de ce type d’application à l’aide d’Ansible.

Automatiser le déploiement d'un MOM avec Wildfly et Ansible

Magazine
Marque
Linux Pratique
Numéro
137
Mois de parution
mai 2023
Spécialité(s)
Résumé

Dans de nombreuses organisations et grandes entreprises, les solutions logicielles de gestion de messages (ou MOM pour « Messaging Oriented Middleware ») sont omniprésentes. Dans cet article, nous proposons donc d’évoquer le déploiement d’une telle solution, à l’aide du serveur Java open source, Wildfly, et de manière entièrement automatisée grâce à Ansible…

Getting Things Done... avec Bash !

Magazine
Marque
Linux Pratique
HS n°
Numéro
57
Mois de parution
avril 2023
Spécialité(s)
Résumé

Depuis la parution de l’ouvrage du même nom, il y a 22 ans, la méthodologie Getting Things Done a fait son bonhomme de chemin. L’utilisant depuis plus de dix ans, nous vous proposons d’en faire, dans cet article, non pas une présentation détaillée, mais un retour d’expérience sur comment nous l’utilisons au quotidien et, en particulier, comment notre interpréteur shell favori, Bash, est au cœur de son outillage !

Les derniers articles Premiums

Les derniers articles Premium

La place de l’Intelligence Artificielle dans les entreprises

Magazine
Marque
Contenu Premium
Spécialité(s)
Résumé

L’intelligence artificielle est en train de redéfinir le paysage professionnel. De l’automatisation des tâches répétitives à la cybersécurité, en passant par l’analyse des données, l’IA s’immisce dans tous les aspects de l’entreprise moderne. Toutefois, cette révolution technologique soulève des questions éthiques et sociétales, notamment sur l’avenir des emplois. Cet article se penche sur l’évolution de l’IA, ses applications variées, et les enjeux qu’elle engendre dans le monde du travail.

Petit guide d’outils open source pour le télétravail

Magazine
Marque
Contenu Premium
Spécialité(s)
Résumé

Ah le Covid ! Si en cette période de nombreux cas resurgissent, ce n’est rien comparé aux vagues que nous avons connues en 2020 et 2021. Ce fléau a contraint une large partie de la population à faire ce que tout le monde connaît sous le nom de télétravail. Nous avons dû changer nos habitudes et avons dû apprendre à utiliser de nombreux outils collaboratifs, de visioconférence, etc., dont tout le monde n’était pas habitué. Dans cet article, nous passons en revue quelques outils open source utiles pour le travail à la maison. En effet, pour les adeptes du costume en haut et du pyjama en bas, la communauté open source s’est démenée pour proposer des alternatives aux outils propriétaires et payants.

Sécurisez vos applications web : comment Symfony vous protège des menaces courantes

Magazine
Marque
Contenu Premium
Spécialité(s)
Résumé

Les frameworks tels que Symfony ont bouleversé le développement web en apportant une structure solide et des outils performants. Malgré ces qualités, nous pouvons découvrir d’innombrables vulnérabilités. Cet article met le doigt sur les failles de sécurité les plus fréquentes qui affectent même les environnements les plus robustes. De l’injection de requêtes à distance à l’exécution de scripts malveillants, découvrez comment ces failles peuvent mettre en péril vos applications et, surtout, comment vous en prémunir.

Bash des temps modernes

Magazine
Marque
Contenu Premium
Spécialité(s)
Résumé

Les scripts Shell, et Bash spécifiquement, demeurent un standard, de facto, de notre industrie. Ils forment un composant primordial de toute distribution Linux, mais c’est aussi un outil de prédilection pour implémenter de nombreuses tâches d’automatisation, en particulier dans le « Cloud », par eux-mêmes ou conjointement à des solutions telles que Ansible. Pour toutes ces raisons et bien d’autres encore, savoir les concevoir de manière robuste et idempotente est crucial.

Les listes de lecture

9 article(s) - ajoutée le 01/07/2020
Vous désirez apprendre le langage Python, mais ne savez pas trop par où commencer ? Cette liste de lecture vous permettra de faire vos premiers pas en découvrant l'écosystème de Python et en écrivant de petits scripts.
11 article(s) - ajoutée le 01/07/2020
La base de tout programme effectuant une tâche un tant soit peu complexe est un algorithme, une méthode permettant de manipuler des données pour obtenir un résultat attendu. Dans cette liste, vous pourrez découvrir quelques spécimens d'algorithmes.
10 article(s) - ajoutée le 01/07/2020
À quoi bon se targuer de posséder des pétaoctets de données si l'on est incapable d'analyser ces dernières ? Cette liste vous aidera à "faire parler" vos données.
Voir les 125 listes de lecture

Abonnez-vous maintenant

et profitez de tous les contenus en illimité

Je découvre les offres

Déjà abonné ? Connectez-vous