On a passé deux chapitres entiers à parler de hautes considérations théoriques et vos petits doigts doivent frétiller d'impatience au-dessus de votre clavier. Comme je vous comprends ! Sans plus attendre, passons à l'installation d'un cluster HDFS en local, puis voyons ensemble comment l'utiliser.
Installation
Installation de Java
HDFS est un logiciel programmé en Java ; pour l'utiliser, vous allez donc avoir besoin d'installer un Java Runtime Environment. Sous Ubuntu 16.04, l'installation se fait simplement en exécutant :
$ sudo apt-get install default-jre
Si vous disposez du binairejava
, alors le JRE est bien installé :
$ which java
/usr/bin/java
Dans la suite, vous aurez besoin de définir la variable d'environnementJAVA_HOME
. Celle-ci doit correspondre au chemin absolu vers le répertoire contenant le JRE. Vous pouvez obtenir ce chemin en exécutant :
$ readlink -f /usr/bin/java
Sur ma machine, cette commande renvoie :
/usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java
Tout ce qui se situe avantbin/
constitue leJAVA_HOME
. Je peux donc définir cette variable d'environnement en écrivant :
$ export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64/jre/
Installation d'HDFS
Passons à l'installation d'HDFS proprement dite. Pour cela, il faut télécharger les binaires d'Hadoop, disponibles sur le site officiel. Dans la suite, nous utiliserons la version 2.8.1 d'Hadoop. De plus, nous nous placerons dans le répertoire~/code
:
$ cd ~
$ mkdir code
$ cd code
$ wget http://apache.crihan.fr/dist/hadoop/common/hadoop-2.8.1/hadoop-2.8.1.tar.gz
Décompressons les binaires :
$ tar xzf hadoop-2.8.1.tar.gz
Configuration
Avant de pouvoir lancer un namenode et un datanode, on a besoin de configurer notre cluster. Cela se fait en modifiant des fichiers de configuration. Pour commencer, on va définir le port sur lequel va écouter le namenode. Le fichiercore-site.xml
est un fichier XML qui ne contient initialement aucune propriété ; on lui ajoute la propriétéfs.defaultFS
:
$ cd ~/code/hadoop-2.8.1
$ vim etc/hadoop/core-site.xml
<configuration>
<property>
<name>fs.defaultFS</name>
<value>hdfs://localhost:9000</value>
</property>
</configuration>
Puis on va configurer l'emplacement sur le disque où le namenode est le datanode vont stocker leurs données. Par défaut ça serait dans/tmp
, ce qui n'est pas franchement une super idée puisque les données peuvent y être effacées à n'importe quel moment. Je vais plutôt stocker les données dans~/code/hdfs/namenode
et~/code/hdfs/datanode
:
$ mkdir ~/code/hdfs ~/code/hdfs/namenode ~/code/hdfs/datanode
Pour utiliser ces répertoires, il faut modifier le fichierhdfs-site.xml
:
$ vim etc/hadoop/hdfs-site.xml
<configuration>
<property>
<name>dfs.name.dir</name>
<value>/home/regis/code/hdfs/namenode/</value>
</property>
<property>
<name>dfs.data.dir</name>
<value>/home/regis/code/hdfs/datanode/</value>
</property>
</configuration>
On est presque prêt à lancer un cluster ! On doit juste formatter le répertoire qui va contenir les données du namenode :
$ ./bin/hdfs namenode -format
Vous pouvez alors vérifier que le répertoire~/code/hdfs/namenode
a été modifié :
$ ls ~/code/hdfs/namenode/
current
$ ls ~/code/hdfs/namenode/current/
fsimage_0000000000000000000 fsimage_0000000000000000000.md5 seen_txid VERSION
Lancement d'un namenode et d'un datanode
Pfiouh ! on est prêt à lancer notre premier namenode. C'est pas très compliqué, on utilise le même exécutablehdfs
qu'on a vu dans la commande précédente :
$ ./bin/hdfs namenode
Dans un autre terminal, on lance un datanode qui va communiquer avec notre namenode :
$ ./bin/hdfs datanode
Victoire ! Vous pouvez vérifier que le namenode et le datanode tournent bien en vérifiant qu'ils écoutent respectivement sur les ports 50070 et 50075:
$ telnet localhost 50070
$ telnet localhost 50075
Les commandes principales
Maintenant qu'on a un cluster fonctionnel, on peut commencer à l'utiliser en exécutant quelques commandes. Toutes les commandes supportées par HDFS sont réalisées en exécutant :
$ ./bin/hdfs dfs -<nom de la commande> [options] <arguments>
Par exemple, pour visualiser le contenu à la racine du système de fichiers :
$ ./bin/hdfs dfs -ls /
Toutes les commandes disponibles sont décrites dans la documentation officielle. En particulier, on trouve :
mkdir
: création d'un répertoire.touchz
: équivalent detouch
sur HDFS (création d'un fichier vide).copyFromLocal
: copie d'un (ou plusieurs) fichier ou répertoire local vers HDFS. Utilisez l'option-f
pour écraser les fichiers existant.copyToLocal
: copie d'un (ou plusieurs) fichiers ou répertoire d'HDFS vers le disque local. Notez que vous pouvez utiliser un wildcard ("*") pour désigner plusieurs fichiers :$ ./bin/hdfs dfs -ls /pouac Found 2 items -rw-r--r-- 3 regis supergroup 0 2017-07-26 17:21 /pouac/file1.txt -rw-r--r-- 3 regis supergroup 0 2017-07-26 17:21 /pouac/file2.txt $ mkdir ./pouac $ ./bin/hdfs dfs -copyToLocal /pouac/*.txt ./pouac $ ls pouac/ file1.txt file2.txt
tail
: affichage des dernières données d'un fichier. L'option-f
est particulièrement utile pour visualiser les changements d'un fichier en temps réel.chmod
etchown
: modifications des permissions, des utilisateurs et des groupes. Les permissions fonctionnent un peu différemment des permissions en local. Pour en apprendre plus, n'hésitez pas à consulter la documentation officielle.rm
: suppression. N'oubliez pas l'option-r
pour supprimer des répertoires.
Comme vous pouvez le voir, la plupart des commandes sont utilisables de la même manière qu'avec un système de fichiers local sous Unix. Plutôt que de détailler longuement les commandes existantes, je vous propose de les découvrir par vous-même sur votre propre cluster !
Pour cela, je vous conseille de télécharger un jeu de données qui va nous être utile dans les chapitres suivants. Il s'agit de l'ensemble des données géographiques de Paris fournies par l'API d'Openstreetmap. Nous avons créé un script qui télécharge ces données ; il vous suffit donc de le télécharger puis de le récupérer sur le dépôt Github du cours puis de l'exécuter :
$ wget https://raw.githubusercontent.com/oc-courses/creez-votre-data-lake/master/paris.py
$ mkdir -p ~/code/data/paris
$ python paris.py ~/code/data/paris/
Le jeu de données sera constitué de fichiers XML dont chacun représente une région rectangulaire dans Paris. Entraînez-vous à déplacer ce jeu de données vers HDFS ainsi qu'à le manipuler ! Ca vous sera très utile par la suite.
HDFS en python
Nous avons vu les commandes nécessaires pour manipuler HDFS depuis un terminal. Mais on va aussi avoir besoin d'écrire et de lire des données depuis des applications créées dans des langages différents. Il existe des librairies pour manipuler des données dans HDFS depuis à peu près n'importe quel langage de programmation ; nous allons voir ici l'exemple de Python.
Commençons par installerhdfs
qui est le package officiel développé par Apache Hadoop :
$ pip install hdfs
La documentation de ce package est disponible sur readthedocs.io. Dans la suite, nous aurons besoin de lire le contenu d'un répertoire, d'écrire des données et de lire des données. Voici un petit programme qui permet de réaliser ces trois opérations :
import hdfs
client = hdfs.InsecureClient("http://0.0.0.0:50070")
# Affichage des données à la racine
# l'appel à "list()" renvoie une liste de noms de fichiers et de
# répertoires
client.list("/")
with client.write("/pouac.txt", overwrite=True) as writer:
# notez que l'appel à "write()" prend en arguments un bytes et non un str
writer.write(b"plonk")
# Lecture d'un fichier complet
with client.read("/pouac.txt") as reader:
print(reader.read())
# Lecture d'un fichier complet
with client.read("/pouac.txt") as reader:
for line in reader:
print(line)
Il s'agit d'un programme très succinct, mais vous pouvez vous en inspirer pour réaliser des opérations plus sophistiquées sur votre cluster. Vous serez alors prêt à découvrir les bonnes pratiques pour administrer un cluster HDFS en production. En avant !