Construire votre distribution Big Data open source avec Hadoop, Hive, HBase, Spark et Zeppelin
18 déc. 2020
- Catégories
- Big Data
- Infrastructure
- Tags
- Maven
- Hadoop
- HBase
- Hive
- Spark
- Git
- Versions et évolutions
- TDP
- Tests unitaires [plus][moins]
Ne ratez pas nos articles sur l'open source, le big data et les systèmes distribués, fréquence faible d’un email tous les deux mois.
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
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
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
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
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
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.