Construire votre distribution Big Data open source avec Hadoop, Hive, HBase, Spark et Zeppelin

Construire votre distribution Big Data open source avec Hadoop, Hive, HBase, Spark et Zeppelin

SCHOUKROUN Leo

By SCHOUKROUN Leo

18 déc. 2020

L’écosystème Hadoop a donné naissance à de nombreux projets populaires tels que HBase, Spark et Hive. Bien que des technologies plus récentes commme Kubernetes et les stockages objets compatibles S3 gagnent en popularité, HDFS et YARN restent très présents pour les use cases à forte volumétrie et sur les architectures on-premises. Vous souhaitez compiler vous-même votre distribution basée sur Hadoop à partir des sources ? Cet article est conçu pour vous montrer comment faire et détaillera toutes les spécificités du processus de build.

Pour faire suite à nos articles Installation d’Hadoop depuis le code source and Reconstruction de Hive dans HDP, cet article approfondi le sujet en examinant le procédé pour compiler plusieurs projets open source Big Data tout en gérant les dépendances qu’ils ont entre eux. L’objectif étant de créer une “mini” distribution Big Data composés d’outils qui fonctionnent autour d’Hadoop en compilant les projets à partir de leurs sources tout en s’assurant qu’ils dépendent les uns des autres. Les projets selectionnés pour cette article sont :

Pourquoi ces projets en particulier ? Hadoop nous fourni un filesystem et un ordonnanceur de resource distribués avec HDFS et YARN. HBase est un projet référence lorsqu’il s’agit de NoSQL. Hive apporte une couche de SQL sur Hadoop avec laquelle les developeurs sont à l’aise. Sans oublier l’interface JDBC/ODBC pour la partie analytique. Spark est l’outil idéal pour effectuer du traitement in-memory et de la transformation de données. Enfin, Zeppelin offre une interface utilisateur via une Web UI qui permet d’intéragir avec tous les composants susnommés.

Les instructions pour compiler ces projets Apache sont parfois difficiles à trouver. Par exemples celles de Apache Hive sont obsolètes.

Cet article parcourt les étapes importantes de compilation de ces projets Apache. Chaque commande lancée sera partagée et toutes les étapes sont reproductibles.

Versions des projets

Bien que tous les projets Apache ci-dessus soient indépendants, ils sont conçus pour fonctionner ensemble et suivent une roadmap commmunes autour des grosses nouveautés. Par example, Hive 3 est fait pour fonctionner avec Hadoop 3. Il est très important de maintenir une consistance lorsque l’on sélectionne les versions à compiler. Toutes les releases officielles Apache sont marquées avec un tag sur le dépôt git officiel, elles portent des noms différents selon les projets.

Les versions que nous avons selectionné pour notre distribution sont résumées dans le tableau suivant :

Component Version Git tag
Apache Hadoop 3.1.1 rel/release-3.1.1
Apache HBase 2.2.3 rel/2.2.3
Apache Spark 2.4.0 v2.4.0
Apache Hive 3.1.2 rel/release-3.1.2
Apache Zeppelin 0.8.2 v0.8.2

Commençons par cloner tous les projets en visant les tags qui nous intéressent :

git clone --branch rel/release-3.1.1 https://github.com/apache/hadoop.git
git clone --branch rel/2.2.3 https://github.com/apache/hbase.git
git clone --branch rel/release-3.1.2 https://github.com/apache/hive.git
git clone --branch v2.4.0 https://github.com/apache/spark.git
git clone --branch v0.8.2 https://github.com/apache/zeppelin.git

Note : Dans cet article, nous compilons tous les projets “tels quels”. Si vous êtes interessé par les étapes consistant à patcher et tester un projet, notre précédent article “Installation d’Hadoop depuis le code source” aborde ces sujets.

Version de distribution

Une distribution est un ensemble de plusieurs composants qui sont compilés, assemblés, et configurés comme une seule unité logique. Chaque composant est identifié par un nom et une version. Une distribtion est une combinaison unique de composants de versions données. Une distribution est également identifiée par un nom et une version.

Pour illustrer cette définition, le nom d’un composant peut être du style {project_name}-{project_version}-{distrib_name}-{distrib_version}.tar.gz, par example hadoop-3.1.1-mydistrib-0.1.0.tar.gz.

Le nom de la release est défini dans le fichier pom.xml de tous les sous modules d’un projet. Ils doivent tous avoir le même nom de release. Pour mettre à jour tous les pom.xml de manière consistante, nous utiliserons la commande mvn suivante plusieurs fois durant l’article :

mvn versions:set -DgenerateBackupPoms=false -DnewVersion=3.1.1-mydistrib-0.1.0

Le paramètre -DgenerateBackupPoms=false est optionnel : il permet d’éviter de générer des fichiers pom.xml.versionsBackup après le changement.

Une fois les fichiers pom.xml à jour, nous pouvons compiler et packager les différents projets en suivant leurs instructions respectives.

Environnement de build

Afin de bénéficier d’un environment de build reproductible, toutes les compilations décrites dans cette article seront executées dans un container Docker. Le project Apache Hadoop fourni une image Docker qui contient tout ce qu’il faut pour compiler Hadoop. Nous utiliserons cette image pour compiler tous les projets de notre distribution.

Pour démarrer ce container, le dépôt git hadoop fourni le script start-build-env.sh.

À partir du dossier hadoop que nous venons de cloner :

./start-build-env.sh

 _   _           _                    ______
| | | |         | |                   |  _  \
| |_| | __ _  __| | ___   ___  _ __   | | | |_____   __
|  _  |/ _` |/ _` |/ _ \ / _ \| '_ \  | | | / _ \ \ / /
| | | | (_| | (_| | (_) | (_) | |_) | | |/ /  __/\ V /
\_| |_/\__,_|\__,_|\___/ \___/| .__/  |___/ \___| \_(_)
                              | |
                              |_|

This is the standard Hadoop Developer build environment.
This has all the right tools installed required to build
Hadoop from source.

Important : La commande docker run du script start-build-env.sh monte en volume le dossier actuel. Par défault, on ne retrouvera que le dossier hadoop. Pour monter les autres dépôts, il faut modifier le script ./start-build-env.sh et monter le répertoire parent. Ainsi tous les dépôts clonés seront accessibles dans le container.

Compiler une release Hadoop

Hadoop logo

Apache Hadoop (HDFS/YARN) est une dépendance de tous les autres projets de notre distribution. Nous devons donc le compiler en premier.

Nous voulons être capable de différencier notre version de Apache Hadoop de la release officielle, pour cela nous allons changer le nom de la version. Utilisons la commande versions:set de mvn pour mettre à jour les pom.xml :

mvn versions:set -DgenerateBackupPoms=false -DnewVersion=3.1.1-mydistrib-0.1.0

Nous pouvons ensuite compiler et packager notre release Hadoop en version mydistrib-0.1.0 avec :

mvn clean install -Pdist -Dtar -DskipTests -Dmaven.javadoc.skip=true

-Pdist and -Dtar sont des profils définis dans hadoop-project-dist/pom.xml. Ils déclenchent un script après la compilation qui copie tous les fichiers nécéssaires (JARs, fichier de configuration, etc.) et en fait une archive .tar.gz. Pourquoi avoir utilisé le goal maven install et non package ? Nous répondrons à cette question dans la suite de l’article.

Une fois la compilation terminée, l’archive est disponible sur votre machine à cet emplacement :

./hadoop-dist/target/hadoop-3.1.1-mydistrib-0.1.0.tar.gz

L’archive est disponible à l’extérieur du container car le dossier est monté depuis la machine hôte (voir ./start-build-env.sh).

Quelle est la suite ? Hive est dépendant de Hadoop et HBase tandis que Spark et HBase dépendent uniquement d’Hadoop. Nous allons donc compiler HBase puis Spark.

Compiler une release HBase

HBase logo

Avant de compiler Apache HBase à partir du code source, nous devons changer le nom et la version de la release pour la différencier de celle d’Apache :

mvn versions:set -DgenerateBackupPoms=false -DnewVersion=2.2.3-mydistrib-0.1.0

Nous devons nous assurer que ce build de HBase soit dépendant de notre version the Hadoop.

La version d’Hadoop utilisé lors de la compilation est définie dans le fichier pom.xml à la racine du projet. Il faut remplacer la version indiquée dans le profile “hadoop-3.0” :

<profile>
  <id>hadoop-3.0</id>
  <activation>
    <property>
      <name>hadoop.profile</name>
      <value>3.0</value>
    </property>
  </activation>
  [...]
  <properties>
    <hadoop.version>${hadoop-three.version}</hadoop.version>

Pour modifier cette valeur, nous avons le choix entre modifier le pom.xml ci-dessus ou changer la valeur de la propriété hadoop.version lors de la commande de build. Essayons avec la deuxième options :

mvn clean \
  -DskipTests -Dhadoop.profile=3.0 -Dhadoop-three.version=3.1.1-mydistrib-0.1.0 \
  package assembly:single install

Remarquons que le paramètre utilisé pour faire une archive des JARs compilés (assembly:single) est différent de celui que nous avons utilisé pour Hadoop dans la précédente section. Chaque projet à sa propre façon de packager une release.

Notre release HBase se trouve être le fichier ./hbase-assembly/target/hbase-2.2.3-mydistrib-0.1.0-bin.tar.gz. Nous pouvons vérifier qu’elle dispose bien des bon JARs Hadoop :

cp ./hbase-assembly/target/hbase-2.2.3-mydistrib-0.1.0-bin.tar.gz /tmp
cd /tmp
tar -xvzf hbase-2.2.3-mydistrib-0.1.0-bin.tar.gz
cd hbase-2.2.3-mydistrib-0.1.0
find . -name "*hadoop*"
[...]
./lib/hadoop-yarn-client-3.1.1-mydistrib-0.1.0.jar
./lib/hadoop-mapreduce-client-core-3.1.1-mydistrib-0.1.0.jar
./lib/hadoop-hdfs-3.1.1-mydistrib-0.1.0.jar
./lib/hadoop-auth-3.1.1-mydistrib-0.1.0.jar
[...]

Les JARs de la release HBase sont bien ceux de notre version d’Hadoop. La version “mydistrib” de HBase est dépendante de la version “mydsitrib” de Hadoop comme nous le souhaitions.

Compiler une release Spark

Spark logo

Comme pour HBase, nous devons nous assurer que la distribution de Apache Spark que nous allons compiler est dépendante de notre version de Hadoop.

Dans le fichier pom.xml de Spark, les dépendances Hadoop sont définies dans un profile. Celui qui nous intéresse se trouve lignes 2691-2698 :

<profile>
  <id>hadoop-3.1</id>
  <properties>
    <hadoop.version>3.1.0</hadoop.version>
    <curator.version>2.12.0</curator.version>
    <zookeeper.version>3.4.9</zookeeper.version>
  </properties>
</profile>

Il faut paramétrer le à 3.1.1-mydistrib-0.1.0, une commande sed permet de le faire :

sed -i "s/<hadoop.version>3.1.0<\\/hadoop.version>/<hadoop.version>3.1.1-mydistrib-0.1.0<\\/hadoop.version>/" pom.xml

Cela donne le résultat suivant :

<profile>
  <id>hadoop-3.1</id>
  <properties>
    <hadoop.version>3.1.1-mydistrib-0.1.0</hadoop.version>
    <curator.version>2.12.0</curator.version>
    <zookeeper.version>3.4.9</zookeeper.version>
  </properties>
</profile>

Bien sûr, les fichiers JAR de la version Hadoop 3.1.1-mydistrib-0.1.0 ne sont pas disponibles sur le repository Maven mais la commande mvn install que nous avons lancé précédemment a copié ces fichiers vers notre cache Maven local, dans le répertoire ~/.m2.

Essayons de localiser ces JARs :

ll ~/.m2/repository/org/apache/hadoop/hadoop-hdfs-client/3.1.1-mydistrib-0.1.0 
total 6.4M
-rw-r--r-- 1 leo leo 4.8M Oct 14 17:55 hadoop-hdfs-client-3.1.1-mydistrib-0.1.0.jar
-rw-r--r-- 1 leo leo 5.9K Oct 14 17:53 hadoop-hdfs-client-3.1.1-mydistrib-0.1.0.pom
-rw-r--r-- 1 leo leo 1.4M Oct 14 17:55 hadoop-hdfs-client-3.1.1-mydistrib-0.1.0-sources.jar
-rw-r--r-- 1 leo leo 153K Oct 14 17:55 hadoop-hdfs-client-3.1.1-mydistrib-0.1.0-tests.jar
-rw-r--r-- 1 leo leo  94K Oct 14 17:55 hadoop-hdfs-client-3.1.1-mydistrib-0.1.0-test-sources.jar

Le container de build partage son répertoire ~/.m2 avec la machine hôte (voir le script start-build-env.sh de Hadoop)

Note : Si la commande du build Hadoop avait été mvn package au lieu de mvn install, les JARs n’auraient pas pu être trouvés dans le dossier ~/.m2 et nous aurions rencontré l’erreur suivante lors de la compilation de HBase :

[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  01:09 min
[INFO] Finished at: 2020-12-02T10:42:46Z
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal on project hbase-hadoop2-compat: Could not resolve dependencies for project org.apache.hbase:hbase-hadoop2-compat:jar:2.2.3-mydistrib-0.1.0: Could not find artifact org.apache.hadoop:hadoop-hdfs-client:jar:3.1.1-mydistrib-0.1.0 in central (https://repo.maven.apache.org/maven2) -> [Help 1]

Encore une fois, changeons le nom de la version de notre release Spark :

mvn versions:set -DgenerateBackupPoms=false -DnewVersion=2.4.0-mydistrib-0.1.0

Spark 2.x doit être compilé avec le JDK 8 (voir SPARK-25820), il est impératif de changer la version de java active dans le container avant de compiler :

sudo update-java-alternatives --set /usr/lib/jvm/java-1.8.0-openjdk-amd64

Note : Par défault, OpenJDK 11 est la version active dans le container de build. Si celle-ci n’est pas changée, la compilation échouera avec la stack trace suivante :

[ERROR] import sun.misc.Cleaner;
[ERROR]                ^
[ERROR]   symbol:   class Cleaner
[ERROR]   location: package sun.misc

Le project Apache Spark embarque un script make-distribution.sh qui est un wrapper autour de mvn. Nous allons l’utiliser pour compiler et packager Spark :

./dev/make-distribution.sh \
  --name my-release --tgz \
  -Phive -Phive-thriftserver -Pyarn -Phadoop-3.1

Le paramètre -Phadoop-3.1 charge le profile que nous avons edité, les autres sont obligatoires pour pouvoir utiliser Spark avec YARN et SparkSQL avec Hive.

Une fois la compilation terminée, l’achive est disponible :

./spark-2.4.0-mydistrib-0.1.0-bin-my-release.tgz

Compiler une release Hive

Hive logo

Passons maintenant à Apache Hive. Comme indiqué dans le fichier pom.xml du projet, Hive dépend de Hadoop et de Spark. Il faut changer les propriétés *.version pour qu’elles correspondent à nos précédents builds.

sed -i "s/<hadoop.version>3.1.0<\\/hadoop.version>/<hadoop.version>3.1.1-mydistrib-0.1.0<\\/hadoop.version>/" pom.xml
sed -i "s/<spark.version>2.3.0<\\/spark.version>/<spark.version>2.4.0-mydistrib-0.1.0<\\/spark.version>/" pom.xml

Le sub-module Maven standalone-metastore dépend également de Hadoop, ne l’oublions pas :

sed -i "s/<hadoop.version>3.1.0<\\/hadoop.version>/<hadoop.version>3.1.1-mydistrib-0.1.0<\\/hadoop.version>/" standalone-metastore/pom.xml

La commande pour compiler et packager Hive est :

mvn clean install -Pdist -DskipTests

Une fois la compilation terminée, l’achive est disponible :

./packaging/target/apache-hive-3.1.2-mydistrib-0.1.0-bin.tar.gz

Compiler une release Zeppelin

Zeppelin logo

Apache Zeppelin est le dernier composant de notre distribution. Il s’agit d’un notebook accessible via une Web UI.

Par rapport aux précédents projets, il est un peu plus complexe de compiler Zeppelin avec nos versions en dépendances.

Le fichier pom.xml de Zeppelin fourni des profils utiles pour sélectionner les versions de Hadoop et Spark. Dans notre cas la commande est :

-Pspark-2.4 -Dspark.version=2.4.0-mydistrib-0.1.0 -Phadoop-3.1 -Dhadoop.version=3.1.1-mydistrib-0.1.0

En plus des profils, l’étape de package de Zeppelin est configurée pour récupérer une release compilée de Spark sur internet et copier son fichier python/lib/py4j-0.10.7-src.zip dans Zeppelin.

Cet étape se trouve ligne 397 du fichier spark/interpreter/pom.xml :

<configuration>
  <target>
    <delete dir="../../interpreter/spark/pyspark" />
    <copy file="${project.build.directory}/${spark.archive}/python/lib/py4j-${py4j.version}-src.zip" todir="${project.build.directory}/../../../interpreter/spark/pyspark" />
    <zip basedir="${project.build.directory}/${spark.archive}/python" destfile="${project.build.directory}/../../../interpreter/spark/pyspark/pyspark.zip" includes="pyspark/*.py,pyspark/**/*.py" />
  </target>
</configuration>

Par défault, l’archive ciblée est https://archive.apache.org/dist/spark/${spark.archive}/${spark.archive}-bin-without-hadoop.tgz, il s’agit du paramètre spark.bin.download.url. Il faut ici changer cette valeur car le site des archives Apache n’héberge pas notre version de Spark. Pour l’écriture de cet article nous avons utilisé Nexus repository. Si l’on ne paramètre pas cet URL, l’erreur suivante est rencontrée :

[ERROR] Failed to execute goal com.googlecode.maven-download-plugin:download-maven-plugin:1.6.0:wget (download-sparkr-files) on project r: IO Error: Error while expanding /dataclan/zeppelin/rlang/target/spark-2.4.0-mydistrib-0.1.0-bin-without-hadoop.tgz: Not in GZIP format -> [Help 1]

Note : Le nom de l’archive par défaut mentionne “without-hadoop” car il est possible de packager Spark sans les librairies Hadoop/YARN (avec le profile -Phadoop-provided). Dans notre cas, nous pouvons utiliser l’archive que nous avons déjà crée. En effet, seuls les fichiers pyspark nous intéressent.

La commande finale pour compiler et packager est :

mvn clean package -DskipTests -Pbuild-distr -Pspark-2.4 -Dspark.version=2.4.0-mydistrib-0.1.0 -Phadoop-3.1 -Dhadoop.version=3.1.1-mydistrib-0.1.0 -Dspark.bin.download.url=https://nexus*****.com/repository/mydistrib-releases/mydistrib-0.1.0/spark-2.4.0-mydistrib-0.1.0.tgz

Une fois la compilation terminée, l’achive est disponible :

./zeppelin-distribution/target/zeppelin-0.8.2-mydistrib-0.1.0.tar.gz

Conclusion

Nous avons parcouru les étapes permettant de construire une distribtion Big Data fonctionnelle avec des composants tels que HDFS, Hive et HBase. Comme indiqué dans l’introduction, les projets sont compilés “tels quels”. Aucune fonctionnalité n’est ajoutée et les builds ne sont pas testés. Quelle est la prochaine étape ? Si vous êtes intéressé par le sujet, notre précédent article Installation d’Hadoop depuis le code source explique comment appliquer un patch sur Hadoop et aborde également la question des tests unitaires.

Canada - Maroc - France

International locations

10 rue de la Kasbah
2393 Rabbat
Canada

Nous sommes une équipe passionnée par l'Open Source, le Big Data et les technologies associées telles que le Cloud, le Data Engineering, la Data Science le DevOps…

Nous fournissons à nos clients un savoir faire reconnu sur la manière d'utiliser les technologies pour convertir leurs cas d'usage en projets exploités en production, sur la façon de réduire les coûts et d'accélérer les livraisons de nouvelles fonctionnalités.

Si vous appréciez la qualité de nos publications, nous vous invitons à nous contacter en vue de coopérer ensemble.