Que ce soit pour nos besoins propres ou pour nos clients, nous concevons des solutions typées BigData. Elles sont par essence composites (parce que la pertinence vient de l’association de technologies excellentes) et déployées sur de multiples machines (la puissance vient de la répartition).

Pour en tirer profit Il faut savoir : créer des images ( des exécutables packagés pour simplifier), les déployer, adapter à l’environnement, les fédérer, les faire communiquer, les monter en charge.

 Enchaîner ces opérations manuellement requiert du temps et se révèle source d’erreur. Nous avons automatisé entièrement ce processus en tirant profit des dernières innovations de Docker et des containers et notamment Docker Swarm dont l’utilisation a été révolutionnée par Docker 1.13. Nous sommes en mesure de créer en 10 minutes une architecture applicative complètement opérationnelle qui inclut :

  • Kafka :  Solution d’échanges de messages ultra performantes,
  • ElasticSearch : Intelligence, Exploration, Recherche,
  • Spark : pour transformer et valoriser, ETL + Machine Learning
  • mais aussi : Microservices en Java,  Avro (sérialisation des données), Schema Registry (intégrité et validation des données), API REST pour Kafka

Un petit rappel sur Docker et son écosystème

i. Docker Engine

Docker Engine est le moteur de base permettant de faire tourner des conteneurs sur une machine seule ou un cluster. Ci-contre le schéma très simlpifié de l’architecture de Docker.
Docker se base donc sur un démon s’exécutant en arrière plan offrant une API s’utilisant avec un client en ligne de commande.

Pour lancer un container il y a deux solutions :

  • Utiliser une image publique de la communautée sur https://hub.docker.com/
  • Construire une image à partir d’un Docker File (suite d’instruction permettant d’ajouter des éléments au container

ii. Docker Compose

Il est fréquent lors de l’utilisation de conteneur de vouloir en lancer plusieurs en même temps (par exemple un stack très classique PHP + APACHE + MYSQL). Cette fonctionnalité est présente grâce à Docker Compose qui permet grâce à la syntaxe YAML de créer un fichier de déploiement précisant tous les conteneurs et leurs options exécutable en une seule fois.

Cet aspect est fondamental pour l’automatisation du déploiement ainsi que la création de cluster avec Docker Swarm…

iii. Docker Swarm

Depuis la version 1.13 la façon de créer un cluster avec Docker Swarm a été complètement révolutionnée et simplifiée.
Ce déploiement se décline en Trois étapes :

  • Tout d’abord la création du cluster avec les différentes machines la composant en se basant sur une architecture Slave Master comme sur le schéma ci dessous

  • Ensuite la création d’un réseau commun que partageront tous les conteneurs.
  • Enfin le déploiement en tant que tel en se basant sur le fichier YAML utilisé par Docker Compose et la commande `docker stack deploy`. C’est la GROSSE nouveauté de docker Swarm, le déploiement devient extrêmement rapide et facile et surtout offre une couche d’abstraction entre le déploiement et le type d’architecture. En effet le même fichier YAML sert pour le déploiement sur un serveur seul ou sur un cluster. Les seules différences pour le déploiement sur un cluster étant les options de déploiement avec le choix du nombre de réplicas (correspondant par exemple au nombre de broker Kafka).

Docker Swarm gère nativement le load balancing (répartition de la charge sur les différents noeuds) et n’est pas soumis au Single Point Of Failure (si le master tombe il sera automatiquement remplacé par un des noeuds qui deviendra le nouveau master)

Mise en oeuvre

1. Définir les images qui vont supporter notre service

  1. Kafka : Elle associe le broker de message et le code Kafka Connect pour consommer les informations. Nous avons choisi cette option pour traiter l’information au plus près du flux de données

Pour mettre en oeuvre le cluster Kafka nous avons besoin de 4 images :

Ces images vont être assemblée ensemble via un fichier à la syntaxe YAML : docker-compose.yml
Ce fichier est disponible sur mon github, n’hésitez pas à le cloner nous en aurons besoin dans la phase d’après
https://github.com/lucienfregosi/kafka-demo

Pour travailler avec ces services conteneurisé et faire communiquer les conteneurs ensemble, on travaille à l’intérieur d’un réseau. Par exemple Zookeeper doit être relié à Kafka (dans notre cas dans le docker compose) et pour cela doit être présent sur le même réseau.

Kafka est supporté par la société Confluent qui a été créé par les concepteurs de Kafka lorsqu’ils travaillaient chez Linkedin. Ils éditent un certain nombre de service autour de Kafka comme une API, Kafka Streaming, Schema Registry. Ils possèdent également une version entreprise qui ajoutent du support et une interface de monitoring.

2. ElasticSearch

Elasticsearch permet d’enregistrer les données dans une base de données distribuée. La connexion à Kafka se fait grâce à Kafka Connect. C’est une API de développement qui permet de créer soit même ses connecteurs. Ainsi un certain nombre de connecteurs sont proposé nativement par la plateforme Confluent ou bien développé par la communautée.

Point d’attention : Les connecteurs entre Kafka et un autre système de base de données sont systématiquement proposés en deux version : standalone ou distribué.
Le connecteur standalone est facile à mettre en place mais perd l’avantage d’un système distribué comme Kafka et crée un goulot d’étranglement entre Kafka et Elasticsearch.
Pour le connecteur distribué il fonctionne grâce à l’API REST de Kafka proposé par Confluent. Une fois le serveur REST lancé on peut créer le connecteur via une requête POST.

3. Autres technologies

Pour que notre solution soit robuste, résiliente et fonctionnelle, il est nécessaire d’y ajouter :

Avro : C’est est un format de donnée encodé et binarisé. L’avantage d’envoyer des messages Avro avec kafka est d’alléger la charge sur le serveur et de standardiser les échanges. Dans le consommateur Kafka les messages sont ensuite décodé, converti en JSON et envoyé vers elasticsearch avec le connecteur

Schéma Registry : permet de définir un schéma pour les échanges de messages et de contrôler leur intégrité tout au cours du temps.

Java et Maven

Pour écrire le code des producer et consumer, on utilise l’API Java de Kafka qui permet de définir les actions, de se connecter à des clients (par exemple pour récupérer des tweets).
Les projets sont buildé avec un gestionnaire de dépendances type Maven qui permettent de générer des JAR qui sont ensuite inclus au connecteur (par exemple)

2 – Les grandes étapes de la mise en place de cette architecture

Installation des serveurs, Initialisation du master

Avant toute chose et de monter notre serveur, il faut pouvoir lancer les différents logiciel tels que docker, java, python etc… Cette étape fastidieuse est facilement automatisable avec Ansible.

On doit cloner aussi le repository (ou dépôt d’images) contenant le fichier docker-compose écrit en YAML qui va permettre de déployer des services https://github.com/lucienfregosi/kafka-demo.

Création du cluster Swarm

Une fois Docker installé on peut mettre en place le cluster et ceci très facilement :

  • Lancer la commande `docker swarm init` sur le master. Cette commande en renvoie une autre de la forme
    docker swarm join token SWMTKN-1-2jwrn7w69azffclbaouu6gvdn7t7nhs15nv0py8a1li3mbypgl-ddrijlpzsrl0crkty1lo70q18 137.74.24.155:2377
  • Utiliser la commande renvoyée sur une nouvelle machine pour que le noeud rejoigne le cluster.

Déploiement des services Docker

Pour déployer les services, rien de plus simple quand on a écrit son fichier docker-compose.yml.
Néanmoins avant le déploiement il faut créer un réseau commun qui sera utilisé par Swarm pour faire communiquer les services entre eux.

`docker network create –attachable -d overlay cluster_network`

Ensuite exécuter la commande suivante pour le déploiement effectif :

`docker stack deploy -c docker-compose.yml`

La commande docker service ls permet de voir les services, leur nombre et leur état.

Ajout d’un consumer ou producer aux services

Pour ajouter un conteneur ou un producer il faut avoir au préalable avoir créer un réseau en lui passant l’option attachable qui va permettre de relier des conteneurs au réseau existant.
Pour créer un Consumer qui va se mettre en attente de messages à consommer, on utilise l’image transformée par nos soins :
https://hub.docker.com/r/lucienfregosi/kafka-consumer-connector-elasticsearch/

Pour lancer cette image rien de plus simple avec Docker

`docker run –rm –network cluster_network -v /var/run/docker.sock:/var/run/docker.sock -i -t lucienfregosi/kafka-consumer-connector-elasticsearch bin/bash`

Une fois l’image lancée, toute la plateforme Confluent est embarquée dans ce conteneur et on peut lancer facilement des consumer ou des producer.

Lancement de l’écoute des flux entrant (ici un client Twitter stream)

Un cas d’étude classique du Big Data est de récupérer des tweets via l’API de stream de Twitter. Ceci s’adapte parfaitement à la captation de signaux type IoT. Dans notre architecture nous pouvons nous connecter dans un consumer à l’API Kafka puis consommer les tweets et de les envoyer dans Kafka.
Pour ce faire nous avons modifié un conteneur avec maven embarqué auquel on ajoute le code d’un consumer envoyant des tweets dans kafka. L’image qui correspond est  : https://hub.docker.com/r/lucienfregosi/maven-twitter/

`docker run –rm –network cluster_network -v /var/run/docker.sock:/var/run/docker.sock -i -t lucienfregosi/maven-twitter bin/bash`

 

Ce conteneur est constitué d’un projet Java construit avec Maven à exécuter via la commande mvn et qui va se connecter à l’API Twitter pour ensuite envoyer les messages dans Kafka.

Connexion à Elasticsearch

Une fois les messages transportés par Kafka on cherche à les envoyer dans Elasticsearch en utilisant le connecteur donnée par Confluent Platform (comme expliqué plus haut).
De la même façon il faut lancer le conteneur contenant les fichier Confluent :

`docker run –rm –network cluster_network -v /var/run/docker.sock:/var/run/docker.sock -i -t lucienfregosi/kafka-consumer-connector-elasticsearch bin/bash`

Une fois le conteneur activé, on peut lancer l’API REST pour venir la requêter en créant un connecteur grâce à la requête suivante :

curl -XPOST -H ‘Content-type:application/json’ ‘10.0.0.15:8083/connectors’ -d ‘{
″name″ : ″elasticsearch-sink″,
″config″ : {
″connector.class″ : ″io.confluent.connect.elasticsearch.ElasticsearchSinkConnector″,
″tasks.max″ : ″1″,
″topics″ : ″topic-test″,
″topic.index.map″ : ″topic-test:index″,
″connection.url″ : ″http://10.0.0.4:9200″,
″type.name″ : ″true″,
″key.ignore″ : ″true″,
″schema.ignore″ : ″true″
}
}’

Nous aboutissons à l’architecture applicative ci-dessous :

Toutes ces étapes sont automatisables grâce à un outil d’automatisation comme Ansible. Pour notre exemple nous avons réduit les exécutions à un seul lancement de script Ansible qui va : faire les installations, créer le cluster, commencer à produire des tweets et à les consommer pour les envoyer dans elasticsearch.