Introduction
À partir de Hadoop 2.0, YARN a introduit un nouveau modèle de gestion des ressources. Il améliore l’utilisation du cluster, unifie la gestion des ressources et facilite le partage des données. En vous appuyant sur le cluster Hadoop pseudo-distribué déjà créé, vous allez découvrir l’architecture et le fonctionnement de YARN, ainsi que sa configuration, son développement et les techniques de surveillance du framework.
Ce laboratoire nécessite des bases en programmation Java.
Les étapes de développement fournissent les fichiers source Java complets. Collez chaque fichier dans son intégralité dans votre éditeur, puis observez comment le client soumet une application et comment l’ApplicationMaster demande et lance un conteneur de tâche.
Architecture et composants de YARN
Dans cette étape, découvrez l’architecture de YARN et le rôle de ses composants.
Introduit dans Hadoop 0.23 dans le cadre de MapReduce 2.0 (MRv2), YARN a profondément transformé la gestion des ressources et l’ordonnancement des tâches dans les clusters Hadoop :
- Décomposition de JobTracker :
MRv2répartit les fonctions deJobTrackerentre plusieurs démons :ResourceManagergère les ressources, tandis queApplicationMasterordonnance et surveille les tâches. - ResourceManager global : chaque application dispose d’un
ApplicationMastercorrespondant. Il peut s’agir d’une tâche MapReduce ou d’un DAG décrivant la tâche. - Framework de calcul des données :
ResourceManager,SlaveetNodeManagerforment un framework dans lequel le ResourceManager gère les ressources de toutes les applications. - Composants de ResourceManager :
Schedulerattribue les ressources en fonction de contraintes telles que la capacité et les files d’attente, tandis queApplicationsManagergère les soumissions de tâches et l’exécution des ApplicationMaster. - Allocation des ressources : les besoins en ressources sont définis à l’aide de conteneurs auxquels sont associées des ressources telles que la mémoire, le processeur, le disque et le réseau.
- Rôle de NodeManager : NodeManager surveille l’utilisation des ressources des conteneurs et transmet ces informations à ResourceManager et à Scheduler.
- Tâches d’ApplicationMaster : ApplicationMaster négocie les conteneurs de ressources avec Scheduler, suit leur état et surveille l’avancement.
La figure suivante illustre les relations entre ces composants :

YARN assure la compatibilité des API avec les versions précédentes, ce qui permet de continuer à exécuter des tâches MapReduce sans transition complexe. Pour gérer efficacement les ressources et ordonnancer les tâches dans les clusters Hadoop, il est essentiel de comprendre l’architecture et les composants de YARN.
Démarrer les démons Hadoop
Dans cette étape, démarrez les démons Hadoop nécessaires à l’exécution de l’application YARN.
Avant d’étudier les paramètres de configuration et les techniques de développement d’applications YARN, démarrez les démons Hadoop afin qu’ils soient disponibles.
Double-cliquez sur le terminal Xfce du bureau, puis exécutez la commande suivante pour passer à l’utilisateur hadoop :
su - hadoop
Conseil : le mot de passe de l’utilisateur hadoop est hadoop.
Une fois le changement d’utilisateur effectué, vous pouvez démarrer les démons Hadoop, notamment ceux des frameworks HDFS et YARN.
Exécutez les commandes suivantes dans le terminal pour démarrer les démons :
/home/hadoop/hadoop/sbin/start-dfs.sh
/home/hadoop/hadoop/sbin/start-yarn.sh
Une fois le démarrage terminé, vous pouvez vérifier que les démons concernés sont actifs à l’aide de la commande jps.
hadoop:~$ jps
3378 NodeManager
3028 SecondaryNameNode
3717 Jps
2791 DataNode
2648 NameNode
3240 ResourceManager
Préparer le fichier de configuration
Dans cette étape, vous allez découvrir yarn-site.xml, l’un des principaux fichiers de configuration de Hadoop, et examiner les paramètres qu’il permet de définir pour le cluster YARN.
Pour éviter de modifier par inadvertance le fichier de configuration, copiez-le dans un autre répertoire avant de l’ouvrir.
Exécutez la commande suivante dans le terminal pour créer un répertoire destiné au fichier de configuration :
mkdir /home/hadoop/hadoop_conf
Copiez ensuite le fichier principal de configuration de YARN, yarn-site.xml, depuis le répertoire d’installation vers le répertoire que vous venez de créer.
Exécutez la commande suivante dans le terminal :
cp /home/hadoop/hadoop/etc/hadoop/yarn-site.xml /home/hadoop/hadoop_conf/yarn-site.xml
Ouvrez ensuite le fichier avec l’éditeur vim pour en consulter le contenu :
vim /home/hadoop/hadoop_conf/yarn-site.xml
Fonctionnement du fichier de configuration
Dans cette étape, examinez les paramètres de configuration utilisés par le cluster Hadoop en cours d’exécution.
Le framework YARN repose sur deux rôles importants : ResourceManager et NodeManager. Les paramètres de ce fichier concernent donc ces deux composants.
Ce fichier peut contenir de nombreux paramètres, mais, par défaut, il ne comporte aucun paramètre personnalisé. Par exemple, le fichier que nous venons d’ouvrir ne contient que l’attribut aux-services, défini lors de la configuration précédente du cluster Hadoop pseudo-distribué, comme le montre l’exemple ci-dessous :
hadoop:~$ cat /home/hadoop/hadoop/etc/hadoop/mapred-site.xml
...
<configuration>
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>
</configuration>
Ce paramètre définit les services auxiliaires qui doivent s’exécuter sur NodeManager. La valeur spécifiée, mapreduce_shuffle, indique que le programme MapReduce doit s’exécuter sur YARN.
Est-ce que les paramètres absents du fichier sont inactifs ? Pas exactement. Si vous ne spécifiez pas explicitement un paramètre dans le fichier, le framework YARN de Hadoop utilise sa valeur par défaut, enregistrée dans des fichiers internes. Tout paramètre défini explicitement dans yarn-site.xml remplace sa valeur par défaut. Ce mécanisme permet au système Hadoop de s’adapter à différents scénarios d’utilisation.
Paramètres de configuration de ResourceManager
Il est essentiel de comprendre et de configurer correctement les paramètres de ResourceManager dans le fichier yarn-site.xml pour gérer efficacement les ressources et exécuter les tâches d’un cluster Hadoop. Voici les principaux paramètres associés à ResourceManager :
yarn.resourcemanager.address: adresse utilisée par les clients pour soumettre ou arrêter des applications. Le port par défaut est 8032.yarn.resourcemanager.scheduler.address: adresse utilisée par ApplicationMaster pour demander et libérer des ressources. Le port par défaut est 8030.yarn.resourcemanager.resource-tracker.address: adresse utilisée par NodeManager pour envoyer des signaux de présence (heartbeats) et récupérer des tâches. Le port par défaut est 8031.yarn.resourcemanager.admin.address: adresse utilisée par les administrateurs pour envoyer des commandes de gestion. Le port par défaut est 8033.yarn.resourcemanager.webapp.address: adresse de l’interface Web permettant de consulter les informations du cluster. Le port par défaut est 8088.yarn.resourcemanager.scheduler.class: nom de la classe principale de l’ordonnanceur (par exemple, FIFO, CapacityScheduler ou FairScheduler).- Configuration des threads :
yarn.resourcemanager.resource-tracker.client.thread-countyarn.resourcemanager.scheduler.client.thread-count
- Allocation des ressources :
yarn.scheduler.minimum-allocation-mbyarn.scheduler.maximum-allocation-mbyarn.scheduler.minimum-allocation-vcoresyarn.scheduler.maximum-allocation-vcores
- Gestion de NodeManager :
yarn.resourcemanager.nodes.exclude-pathyarn.resourcemanager.nodes.include-path
- Configuration des signaux de présence :
yarn.resourcemanager.nodemanagers.heartbeat-interval-ms
La configuration de ces paramètres permet d’ajuster le comportement de ResourceManager, l’allocation des ressources, la gestion des threads et des NodeManager, ainsi que la fréquence des signaux de présence dans un cluster Hadoop. Leur compréhension permet d’éviter certains problèmes et de garantir le bon fonctionnement du cluster.
Paramètres de configuration de NodeManager
La configuration des paramètres de NodeManager dans le fichier yarn-site.xml est essentielle pour gérer efficacement les ressources et les tâches d’un cluster Hadoop. Voici les principaux paramètres associés à NodeManager :
yarn.nodemanager.resource.memory-mb: quantité totale de mémoire physique disponible pour NodeManager. Cette valeur reste constante pendant toute l’exécution de YARN.yarn.nodemanager.vmem-pmem-ratio: rapport entre la mémoire virtuelle et la mémoire physique allouées. Le rapport par défaut est2.1.yarn.nodemanager.resource.cpu-vcores: nombre total de processeurs virtuels disponibles pour NodeManager. La valeur par défaut est8.yarn.nodemanager.local-dirs: chemin des répertoires où NodeManager stocke les résultats intermédiaires. Vous pouvez en configurer plusieurs.yarn.nodemanager.log-dirs: chemin du répertoire des journaux de NodeManager. Vous pouvez en configurer plusieurs.yarn.nodemanager.log.retain-seconds: durée maximale de conservation des journaux de NodeManager. La valeur par défaut est de 10 800 secondes (3 heures).
Ces paramètres permettent d’ajuster l’allocation des ressources, la gestion de la mémoire, les chemins des répertoires et la conservation des journaux, afin d’optimiser les performances et l’utilisation des ressources par NodeManager dans un cluster Hadoop. Leur compréhension contribue au bon fonctionnement du cluster et à l’exécution efficace des tâches.
Consulter les paramètres et leurs valeurs par défaut
Pour consulter tous les paramètres disponibles dans YARN et dans les autres composants courants de Hadoop, référez-vous aux fichiers de configuration par défaut fournis par Apache Hadoop. Vous trouverez ces fichiers aux adresses suivantes :
Paramètres de configuration de YARN :
Fichiers de configuration courants :
- core-default.xml (core-site.xml)
- hdfs-default.xml (hdfs-site.xml)
- mapred-default.xml (mapred-site.xml)
Ces fichiers de configuration par défaut décrivent chaque paramètre et son rôle. Leur consultation vous aidera à comprendre la fonction de chaque paramètre dans l’architecture Hadoop.
Après avoir examiné les paramètres, quittez l’éditeur vim pour terminer cette exploration de la configuration Hadoop.
Créer les répertoires et les fichiers du projet
Dans cette étape, créez les fichiers source de l’application. Vous allez construire une application YARN complète et minimale : un client soumet l’ApplicationMaster, qui demande un conteneur de tâche chargé d’afficher un message de bienvenue.
Commencez par créer un répertoire pour le projet. Exécutez la commande suivante dans le terminal :
mkdir /home/hadoop/yarn_app
Créez ensuite les deux fichiers source du projet.
Le premier fichier est Client.java. Créez-le dans le terminal avec la commande touch :
touch /home/hadoop/yarn_app/Client.java
Créez ensuite le fichier ApplicationMaster.java :
touch /home/hadoop/yarn_app/ApplicationMaster.java
hadoop:~$ tree /home/hadoop/yarn_app/
/home/hadoop/yarn_app/
├── ApplicationMaster.java
└── Client.java
0 directories, 2 files
Écrire le code du client
Dans cette étape, écrivez le client complet qui soumet l’application. Continuez en tant qu’utilisateur hadoop. Ouvrez le fichier source :
vim /home/hadoop/yarn_app/Client.java
Remplacez tout le contenu du fichier par le code ci-dessous, déclaration de package et imports compris. Dans Vim, tapez :set paste et appuyez sur Entrée avant d’appuyer sur i pour passer en mode insertion. Collez le fichier complet et attendez que toutes les lignes apparaissent. Appuyez ensuite sur Échap, tapez :wq et appuyez sur Entrée pour enregistrer le fichier et quitter Vim.
package com.labex.yarn.app;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.yarn.api.ApplicationConstants;
import org.apache.hadoop.yarn.api.records.*;
import org.apache.hadoop.yarn.client.api.YarnClient;
import org.apache.hadoop.yarn.client.api.YarnClientApplication;
import org.apache.hadoop.yarn.conf.YarnConfiguration;
import org.apache.hadoop.yarn.util.ConverterUtils;
public class Client {
public static void main(String[] args) throws Exception {
if (args.length != 1) {
throw new IllegalArgumentException("Usage: Client /absolute/path/to/yarn-app.jar");
}
YarnConfiguration conf = new YarnConfiguration();
YarnClient client = YarnClient.createYarnClient();
client.init(conf);
client.start();
try {
YarnClientApplication application = client.createApplication();
ApplicationSubmissionContext context = application.getApplicationSubmissionContext();
ApplicationId id = context.getApplicationId();
FileSystem fs = FileSystem.get(conf);
Path destination = new Path(fs.getHomeDirectory(), "yarn-app/" + id + "/app.jar");
fs.mkdirs(destination.getParent());
fs.copyFromLocalFile(new Path(args[0]), destination);
FileStatus status = fs.getFileStatus(destination);
LocalResource jar = LocalResource.newInstance(
ConverterUtils.getYarnUrlFromPath(fs.makeQualified(destination)),
LocalResourceType.FILE, LocalResourceVisibility.APPLICATION,
status.getLen(), status.getModificationTime());
Map<String, LocalResource> resources = new HashMap<>();
resources.put("app.jar", jar);
Map<String, String> environment = new HashMap<>();
// The single-node lab uses the same Hadoop installation in every container.
environment.put("CLASSPATH", "./app.jar:" + System.getProperty("java.class.path"));
String command = ApplicationConstants.Environment.JAVA_HOME.$$()
+ "/bin/java -Xmx128m com.labex.yarn.app.ApplicationMaster"
+ " 1>" + ApplicationConstants.LOG_DIR_EXPANSION_VAR + "/stdout"
+ " 2>" + ApplicationConstants.LOG_DIR_EXPANSION_VAR + "/stderr";
ContainerLaunchContext launch = ContainerLaunchContext.newInstance(
resources, environment, Collections.singletonList(command), null, null, null);
context.setApplicationName("LabEx YARN Hello");
context.setQueue("default");
context.setResource(Resource.newInstance(256, 1));
context.setAMContainerSpec(launch);
client.submitApplication(context);
System.out.println("Application ID: " + id);
long deadline = System.currentTimeMillis() + 180000;
while (System.currentTimeMillis() < deadline) {
ApplicationReport report = client.getApplicationReport(id);
YarnApplicationState state = report.getYarnApplicationState();
if (state == YarnApplicationState.FINISHED
|| state == YarnApplicationState.FAILED
|| state == YarnApplicationState.KILLED) {
System.out.println("Final status: " + report.getFinalApplicationStatus());
if (report.getFinalApplicationStatus() != FinalApplicationStatus.SUCCEEDED) {
throw new IllegalStateException(report.getDiagnostics());
}
return;
}
Thread.sleep(1000);
}
client.killApplication(id);
throw new IllegalStateException("Application timed out after three minutes");
} finally {
client.stop();
}
}
}
YarnClient se connecte à ResourceManager et récupère un identifiant d’application. Le client copie le fichier JAR dans HDFS et le déclare comme ressource locale app.jar, afin que YARN puisse le placer dans le répertoire de travail d’ApplicationMaster. Le contexte de lancement fournit le classpath et la commande Java ; le contexte de soumission définit la file d’attente et les ressources du conteneur.
Le classpath utilise les bibliothèques Hadoop installées et partagées par les conteneurs de ce laboratoire à nœud unique. Aucun téléchargement avec Maven ou Gradle n’est nécessaire. Cet exemple est conçu pour le cluster du laboratoire, qui n’utilise pas Kerberos.
Après la soumission, le client interroge régulièrement le rapport de l’application jusqu’à ce qu’elle atteigne un état final, puis vérifie son statut final. killApplication n’est utilisé que si l’application dépasse le délai de trois minutes. À la dernière étape, nous compilerons et exécuterons les deux classes.
Écrire le code d’ApplicationMaster
Dans cette étape, écrivez l’ApplicationMaster complet. Il s’enregistre auprès de ResourceManager, demande un conteneur, lance une commande de bienvenue via NodeManager, puis transmet le résultat de la tâche.
Ouvrez le fichier en tant qu’utilisateur hadoop :
vim /home/hadoop/yarn_app/ApplicationMaster.java
Remplacez tout le contenu du fichier par le code ci-dessous. Tapez :set paste et appuyez sur Entrée avant d’appuyer sur i. Collez le fichier complet et attendez que toutes les lignes apparaissent. Appuyez ensuite sur Échap, tapez :wq et appuyez sur Entrée pour enregistrer le fichier et quitter Vim.
package com.labex.yarn.app;
import java.util.Collections;
import org.apache.hadoop.yarn.api.ApplicationConstants;
import org.apache.hadoop.yarn.api.protocolrecords.AllocateResponse;
import org.apache.hadoop.yarn.api.records.*;
import org.apache.hadoop.yarn.client.api.AMRMClient;
import org.apache.hadoop.yarn.client.api.NMClient;
import org.apache.hadoop.yarn.conf.YarnConfiguration;
public class ApplicationMaster {
public static void main(String[] args) throws Exception {
YarnConfiguration conf = new YarnConfiguration();
AMRMClient<AMRMClient.ContainerRequest> rm = AMRMClient.createAMRMClient();
NMClient nm = NMClient.createNMClient();
rm.init(conf);
nm.init(conf);
rm.start();
nm.start();
try {
rm.registerApplicationMaster("", 0, "");
AMRMClient.ContainerRequest request = new AMRMClient.ContainerRequest(
Resource.newInstance(256, 1), null, null, Priority.newInstance(0));
rm.addContainerRequest(request);
boolean launched = false;
long deadline = System.currentTimeMillis() + 120000;
while (System.currentTimeMillis() < deadline) {
// Each allocate call also sends a heartbeat to the ResourceManager.
AllocateResponse response = rm.allocate(launched ? 0.5f : 0.0f);
for (Container container : response.getAllocatedContainers()) {
if (launched) {
rm.releaseAssignedContainer(container.getId());
continue;
}
rm.removeContainerRequest(request);
String command = "/bin/echo Hello-from-YARN"
+ " 1>" + ApplicationConstants.LOG_DIR_EXPANSION_VAR + "/stdout"
+ " 2>" + ApplicationConstants.LOG_DIR_EXPANSION_VAR + "/stderr";
ContainerLaunchContext launch = ContainerLaunchContext.newInstance(
Collections.emptyMap(), Collections.emptyMap(),
Collections.singletonList(command), null, null, null);
nm.startContainer(container, launch);
launched = true;
}
for (ContainerStatus status : response.getCompletedContainersStatuses()) {
if (status.getExitStatus() != 0) {
throw new IllegalStateException(status.getDiagnostics());
}
rm.unregisterApplicationMaster(FinalApplicationStatus.SUCCEEDED,
"Hello container completed", "");
return;
}
Thread.sleep(1000);
}
rm.unregisterApplicationMaster(FinalApplicationStatus.FAILED,
"No successful container within two minutes", "");
throw new IllegalStateException("Container timed out");
} finally {
nm.stop();
rm.stop();
}
}
}
AMRMClient gère l’enregistrement et les demandes de ressources. Chaque appel à allocate envoie un signal de présence et renvoie les conteneurs nouvellement attribués ainsi que les statuts des conteneurs terminés. NMClient lance la commande dans le conteneur attribué. Cette boucle d’interrogation synchrone rend l’exemple autonome, sans classes de rappel ni méthodes auxiliaires non définies.
La tâche écrit Hello-from-YARN dans le journal de son conteneur. Si elle se termine avec un code de sortie égal à zéro, ApplicationMaster se désenregistre avec le statut SUCCEEDED. Le client affiche ensuite ce statut final. ResourceManager peut arrondir les 256 Mo demandés à son allocation minimale ; la boucle continue d’envoyer des signaux de présence pendant l’attente.
Déroulement du lancement d’une application
Dans cette étape, compilez et exécutez les deux classes Java que vous avez écrites, puis consultez l’application dans l’interface Web de ResourceManager. Continuez dans le terminal en tant qu’utilisateur hadoop.
Compiler et lancer l’application
Placez-vous dans le répertoire source :
cd /home/hadoop/yarn_app
Créez le répertoire de sortie :
mkdir -p classes
Compilez les deux fichiers source complets avec les bibliothèques Hadoop déjà installées dans la machine virtuelle. L’option --release 8 produit des classes compatibles avec l’environnement Java 8 utilisé par Hadoop, même si le compilateur par défaut est plus récent :
javac --release 8 -cp "$(/home/hadoop/hadoop/bin/hadoop classpath --glob)" -d classes Client.java ApplicationMaster.java
Un avertissement concernant une API obsolète n’est pas problématique ; la compilation ne doit afficher aucune erreur. Empaquetez les classes compilées :
jar cf yarn-app.jar -C classes .
Soumettez l’application avec le client et enregistrez sa sortie. Le dernier argument est le fichier JAR que le client téléverse dans HDFS pour ApplicationMaster :
set -o pipefail
/home/hadoop/hadoop/bin/yarn jar /home/hadoop/yarn_app/yarn-app.jar com.labex.yarn.app.Client /home/hadoop/yarn_app/yarn-app.jar | tee /home/hadoop/yarn_app/application.log
Laissez l’application s’exécuter jusqu’à son terme. Parmi les messages des journaux Hadoop, vous devriez voir :
Application ID: application_<timestamp>_<sequence>
Final status: SUCCEEDED
L’identifiant varie à chaque exécution. Le message de bienvenue est écrit dans le journal du conteneur de la tâche, tandis que le client affiche l’identifiant de l’application et son résultat final. Cette exécution met en œuvre votre propre client et votre propre ApplicationMaster, et non un exemple MapReduce précompilé distinct.
Consulter les résultats de l’exécution de l’application
Ouvrez Firefox sur le bureau et accédez à l’adresse suivante :
http://localhost:8088
Dans la liste des applications, repérez LabEx YARN Hello à l’aide de l’identifiant affiché dans le terminal. Son état doit être FINISHED et son statut final SUCCEEDED. Cliquez sur l’identifiant de l’application pour consulter ses détails. ResourceManager suit l’application, ApplicationMaster gère son conteneur de tâche et NodeManager exécute ce conteneur.
Résumé
En vous appuyant sur le cluster Hadoop pseudo-distribué déjà créé, ce laboratoire vous a permis de découvrir l’architecture et le fonctionnement de YARN, ainsi que sa configuration, son développement et les techniques de surveillance du framework. Le cours fournit de nombreux exemples de code et fichiers de configuration : prenez le temps de les lire attentivement.



