Introducción
A partir de Hadoop 2.0, se introdujo el nuevo modelo de gestión de recursos de YARN, que mejora el uso del clúster, la gestión unificada de recursos y el intercambio de datos. Sobre la base de un clúster Hadoop seudodistribuido, en esta sección aprenderá la arquitectura, el funcionamiento y la configuración del framework YARN, así como técnicas de desarrollo y supervisión.
Este laboratorio requiere conocimientos básicos de programación en Java.
En los pasos de desarrollo se proporcionan archivos Java completos. Pegue cada archivo entero en su editor y, a continuación, revise cómo el cliente envía una aplicación y cómo el ApplicationMaster solicita e inicia un contenedor de tareas.
Arquitectura y componentes de YARN
En este paso, explore la arquitectura de YARN y las funciones de sus componentes.
YARN, que se introdujo en Hadoop 0.23 como parte de MapReduce 2.0 (MRv2), transformó la gestión de recursos y la planificación de trabajos en los clústeres Hadoop:
- Descomposición de JobTracker:
MRv2separa las funciones deJobTrackeren demonios independientes:ResourceManagerse encarga de la gestión de recursos, yApplicationMaster, de la planificación y supervisión de trabajos. - ResourceManager global: Cada aplicación tiene un
ApplicationMastercorrespondiente. La aplicación puede ser un trabajo de MapReduce o un DAG que describe el trabajo. - Framework de cálculo de datos:
ResourceManager,SlaveyNodeManagerforman un framework en el que ResourceManager administra los recursos de todas las aplicaciones. - Componentes de ResourceManager:
Schedulerasigna recursos según restricciones como la capacidad y las colas, mientras queApplicationsManagergestiona el envío de trabajos y la ejecución de ApplicationMaster. - Asignación de recursos: Los requisitos de recursos se definen mediante contenedores de recursos con elementos como memoria, CPU, disco y red.
- Función de NodeManager: NodeManager supervisa el uso de recursos de los contenedores e informa a ResourceManager y Scheduler.
- Tareas de ApplicationMaster: ApplicationMaster negocia contenedores de recursos con Scheduler, registra su estado y supervisa el progreso.
La siguiente figura muestra las relaciones entre estos componentes:

YARN garantiza la compatibilidad de la API con las versiones anteriores, lo que permite migrar sin problemas los trabajos de MapReduce existentes. Comprender la arquitectura y los componentes de YARN es esencial para gestionar los recursos y planificar los trabajos de forma eficiente en los clústeres Hadoop.
Inicio de los demonios de Hadoop
En este paso, inicie los demonios de Hadoop necesarios para ejecutar la aplicación YARN.
Antes de estudiar los parámetros de configuración correspondientes y las técnicas de desarrollo de aplicaciones YARN, debe iniciar los demonios de Hadoop para poder utilizarlos.
Primero, haga doble clic en el terminal Xfce del escritorio y ejecute el siguiente comando para cambiar al usuario hadoop:
su - hadoop
Nota: La contraseña del usuario hadoop es 'hadoop'.
Cuando haya cambiado de usuario, podrá iniciar los demonios relacionados con Hadoop, incluidos los de los frameworks HDFS y YARN.
Ejecute los siguientes comandos en el terminal para iniciar los demonios:
/home/hadoop/hadoop/sbin/start-dfs.sh
/home/hadoop/hadoop/sbin/start-yarn.sh
Cuando termine el inicio, puede ejecutar el comando jps para comprobar si los demonios correspondientes están en ejecución.
hadoop:~$ jps
3378 NodeManager
3028 SecondaryNameNode
3717 Jps
2791 DataNode
2648 NameNode
3240 ResourceManager
Preparación del archivo de configuración
En este paso, conocerá yarn-site.xml, uno de los principales archivos de configuración de Hadoop, y verá qué parámetros del clúster YARN se pueden establecer en él.
Para evitar modificar por error el archivo de configuración, es mejor copiarlo a otro directorio antes de abrirlo.
Ejecute el siguiente comando en el terminal para crear un directorio para el archivo de configuración:
mkdir /home/hadoop/hadoop_conf
A continuación, copie el archivo principal de configuración de YARN, yarn-site.xml, desde el directorio de instalación al directorio que acaba de crear.
Ejecute este comando en el terminal:
cp /home/hadoop/hadoop/etc/hadoop/yarn-site.xml /home/hadoop/hadoop_conf/yarn-site.xml
Luego, abra el archivo con el editor vim para ver su contenido:
vim /home/hadoop/hadoop_conf/yarn-site.xml
Funcionamiento del archivo de configuración
En este paso, revise los parámetros de configuración que utiliza el clúster Hadoop en ejecución.
El framework YARN tiene dos funciones importantes: ResourceManager y NodeManager. Por eso, cada elemento de configuración del archivo establece un parámetro para uno de estos dos componentes.
Este archivo admite muchos elementos de configuración, pero, de forma predeterminada, no contiene ninguno personalizado. Por ejemplo, el archivo que acaba de abrir solo tiene el atributo aux-services, especificado al configurar anteriormente el clúster Hadoop seudodistribuido, como se muestra a continuación:
hadoop:~$ cat /home/hadoop/hadoop/etc/hadoop/mapred-site.xml
...
<configuration>
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>
</configuration>
Este elemento de configuración establece los servicios dependientes que deben ejecutarse en NodeManager. El valor que especificamos es mapreduce_shuffle, lo que indica que MapReduce debe ejecutarse en YARN con su valor predeterminado.
¿Significa esto que los elementos de configuración que no aparecen en el archivo no funcionan? No exactamente. Si los parámetros de configuración no se especifican explícitamente en el archivo, el framework YARN de Hadoop lee sus valores predeterminados de archivos internos. Los elementos especificados explícitamente en yarn-site.xml sustituyen esos valores predeterminados. Esto permite que el sistema Hadoop se adapte a distintos escenarios de uso.
Elementos de configuración de ResourceManager
Comprender y configurar correctamente los parámetros de ResourceManager en el archivo yarn-site.xml es fundamental para gestionar los recursos y ejecutar trabajos de forma eficiente en un clúster Hadoop. A continuación se resumen los principales elementos de configuración relacionados con ResourceManager:
yarn.resourcemanager.address: Dirección que se ofrece a los clientes para enviar aplicaciones y finalizarlas. El puerto predeterminado es 8032.yarn.resourcemanager.scheduler.address: Dirección que se ofrece a ApplicationMaster para solicitar y liberar recursos. El puerto predeterminado es 8030.yarn.resourcemanager.resource-tracker.address: Dirección que se ofrece a NodeManager para enviar señales de actividad y solicitar tareas. El puerto predeterminado es 8031.yarn.resourcemanager.admin.address: Dirección que se ofrece a los administradores para ejecutar comandos de gestión. El puerto predeterminado es 8033.yarn.resourcemanager.webapp.address: Dirección de la interfaz web para consultar información del clúster. El puerto predeterminado es 8088.yarn.resourcemanager.scheduler.class: Nombre de la clase principal del planificador (por ejemplo, FIFO, CapacityScheduler o FairScheduler).- Configuración de subprocesos:
yarn.resourcemanager.resource-tracker.client.thread-countyarn.resourcemanager.scheduler.client.thread-count
- Asignación de recursos:
yarn.scheduler.minimum-allocation-mbyarn.scheduler.maximum-allocation-mbyarn.scheduler.minimum-allocation-vcoresyarn.scheduler.maximum-allocation-vcores
- Gestión de NodeManager:
yarn.resourcemanager.nodes.exclude-pathyarn.resourcemanager.nodes.include-path
- Configuración de señales de actividad:
yarn.resourcemanager.nodemanagers.heartbeat-interval-ms
La configuración de estos parámetros permite ajustar el comportamiento de ResourceManager, la asignación de recursos, la gestión de subprocesos, la administración de NodeManager y los intervalos entre señales de actividad en un clúster Hadoop. Comprender estos elementos ayuda a evitar problemas y a garantizar que el clúster funcione correctamente.
Elementos de configuración de NodeManager
Configurar los parámetros de NodeManager en el archivo yarn-site.xml es fundamental para gestionar los recursos y las tareas de forma eficiente en un clúster Hadoop. A continuación se resumen los principales elementos de configuración relacionados con NodeManager:
yarn.nodemanager.resource.memory-mb: Especifica la memoria física total disponible para NodeManager. Este valor permanece constante durante la ejecución de YARN.yarn.nodemanager.vmem-pmem-ratio: Establece la proporción entre la memoria virtual y la memoria física asignada. El valor predeterminado es2.1.yarn.nodemanager.resource.cpu-vcores: Define el número total de CPU virtuales disponibles para NodeManager. El valor predeterminado es8.yarn.nodemanager.local-dirs: Ruta donde NodeManager almacena los resultados intermedios. Se pueden configurar varios directorios.yarn.nodemanager.log-dirs: Ruta al directorio de registros de NodeManager. Se pueden configurar varios directorios.yarn.nodemanager.log.retain-seconds: Tiempo máximo de conservación de los registros de NodeManager. El valor predeterminado es 10800 segundos (3 horas).
La configuración de estos parámetros permite ajustar la asignación de recursos, la gestión de memoria, las rutas de los directorios y el periodo de conservación de los registros para optimizar el rendimiento y el uso de recursos de NodeManager en un clúster Hadoop. Comprender estos elementos ayuda a garantizar el funcionamiento correcto del clúster y la ejecución eficiente de las tareas.
Consulta de elementos de configuración y referencias de valores predeterminados
Para consultar todos los elementos de configuración disponibles en YARN y en otros componentes habituales de Hadoop, puede consultar los archivos de configuración predeterminados de Apache Hadoop. Estos son los enlaces a dichos archivos:
Elementos de configuración de YARN:
Archivos de configuración comunes:
- core-default.xml (core-site.xml)
- hdfs-default.xml (hdfs-site.xml)
- mapred-default.xml (mapred-site.xml)
Al consultar estos archivos de configuración predeterminados, encontrará descripciones detalladas de cada elemento y su propósito. Esto le ayudará a comprender la función de cada parámetro en el diseño de la arquitectura de Hadoop.
Cuando termine de revisar la configuración, cierre el editor vim para concluir la exploración de los parámetros de configuración de Hadoop.
Creación de directorios y archivos del proyecto
En este paso, cree los archivos de código fuente de la aplicación. Crearemos una aplicación YARN completa y mínima: un cliente envía el ApplicationMaster, que solicita un contenedor de tareas para imprimir un saludo.
Primero, cree un directorio para el proyecto. Ejecute el siguiente comando en el terminal:
mkdir /home/hadoop/yarn_app
A continuación, cree por separado los dos archivos de código fuente del proyecto.
El primero es Client.java. Use el comando touch en el terminal para crear el archivo:
touch /home/hadoop/yarn_app/Client.java
Luego, cree el archivo 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
Escritura del código del cliente
En este paso, escriba el cliente completo que envía la aplicación. Continúe con el usuario hadoop y abra el archivo de código fuente:
vim /home/hadoop/yarn_app/Client.java
Reemplace todo el contenido del archivo con el código siguiente, incluida la declaración del paquete y las importaciones. En Vim, escriba :set paste y pulse Enter; luego pulse i para entrar en el modo de inserción. Pegue el archivo completo y espere a que aparezcan todas las líneas. Después, pulse Esc y escriba :wq para guardar los cambios y salir.
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 conecta a ResourceManager y obtiene un ID de aplicación. El cliente copia el JAR a HDFS y lo declara como el recurso local app.jar, para que YARN pueda colocarlo en el directorio de trabajo de ApplicationMaster. El contexto de inicio proporciona el classpath y el comando de Java; el contexto de envío especifica la cola y los recursos del contenedor.
El classpath utiliza las bibliotecas de Hadoop instaladas y compartidas por los contenedores de este laboratorio de un solo nodo. No es necesario descargar dependencias con Maven ni Gradle. Este ejemplo está pensado para el clúster del laboratorio, que no utiliza Kerberos.
Después de enviar la aplicación, el cliente consulta periódicamente el informe hasta que se alcanza un estado terminal y comprueba el estado final. killApplication solo se utiliza si la aplicación supera el límite de tres minutos. En el último paso, compilaremos y ejecutaremos ambas clases.
Escritura del código de ApplicationMaster
En este paso, escriba el ApplicationMaster completo. Este se registra con ResourceManager, solicita un contenedor, inicia un saludo mediante NodeManager e informa del resultado de la tarea.
Abra el archivo como usuario hadoop:
vim /home/hadoop/yarn_app/ApplicationMaster.java
Reemplace todo el contenido del archivo con el código siguiente. Escriba :set paste y pulse Enter; luego pulse i. Pegue el archivo completo y espere a que aparezcan todas las líneas. Después, pulse Esc y escriba :wq para guardar los cambios y salir.
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 gestiona el registro y las solicitudes de recursos. Cada llamada a allocate envía una señal de actividad y devuelve los contenedores asignados recientemente y los estados de los contenedores completados. NMClient inicia el comando en el contenedor asignado. Este bucle de sondeo síncrono mantiene el ejemplo autocontenido, sin clases de callback ni métodos auxiliares sin definir.
La tarea imprime Hello-from-YARN en el registro de su contenedor. Si el código de salida es cero, ApplicationMaster se da de baja con el estado SUCCEEDED. A continuación, el cliente informa de ese estado final. ResourceManager puede redondear los 256 MB solicitados hasta su asignación mínima; mientras espera, el bucle continúa enviando señales de actividad.
Proceso de inicio de la aplicación
En este paso, compile y ejecute las dos clases Java que ha escrito y, después, consulte la aplicación en la interfaz web de ResourceManager. Continúe en el terminal como usuario hadoop.
Compilación e inicio de la aplicación
Cambie al directorio del código fuente:
cd /home/hadoop/yarn_app
Cree el directorio de salida:
mkdir -p classes
Compile los dos archivos de código fuente completos con las bibliotecas de Hadoop ya instaladas en la máquina virtual. --release 8 genera clases compatibles con el entorno de ejecución Java 8 de Hadoop, aunque el compilador predeterminado sea más reciente:
javac --release 8 -cp "$(/home/hadoop/hadoop/bin/hadoop classpath --glob)" -d classes Client.java ApplicationMaster.java
Un aviso sobre API obsoletas no supone ningún problema; la compilación no debería mostrar errores. Empaquete las clases compiladas:
jar cf yarn-app.jar -C classes .
Envíe la aplicación con el cliente y guarde su salida. El último argumento es el JAR que el cliente carga en HDFS para 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
Espere a que termine la aplicación. Entre los mensajes de registro de Hadoop, debería ver:
Application ID: application_<timestamp>_<sequence>
Final status: SUCCEEDED
El ID cambia en cada ejecución. El saludo se escribe en el registro del contenedor de tareas, mientras que el cliente muestra el ID de la aplicación y el resultado final. Esta ejecución prueba el cliente y ApplicationMaster que usted ha creado, no un ejemplo de MapReduce precompilado independiente.
Consulta de los resultados de ejecución de la aplicación
Abra Firefox en el escritorio y visite:
http://localhost:8088
Busque LabEx YARN Hello en la lista de aplicaciones utilizando el ID que aparece en el terminal. Su estado debería ser FINISHED y el estado final, SUCCEEDED. Haga clic en el ID de la aplicación para consultar sus detalles. ResourceManager realiza el seguimiento de la aplicación; ApplicationMaster gestiona su contenedor de tareas y NodeManager ejecuta ese contenedor.
Resumen
A partir de la configuración de un clúster Hadoop seudodistribuido, este laboratorio le ha permitido conocer la arquitectura, el funcionamiento y la configuración del framework YARN, así como técnicas de desarrollo y supervisión. El curso incluye numerosos ejemplos de código y archivos de configuración; léalos con atención.



