Skip to content

~/bda/m01 $ cat 01-hadoop-y-hdfs.md

  • Big Data Aplicado
  • M01
  • lección 01/09

Hadoop y HDFS

Logotipo oficial de Apache Hadoop: elefante amarillo junto al nombre Hadoop.

Logo de Apache Hadoop, proyecto de la Apache Software Foundation.

Hadoop se distribuye bajo la Apache License 2.0, una licencia de software libre de tipo permisivo: permite reutilizar el software con pocas restricciones, siempre que se respeten sus condiciones.

  • Uso y modificación: puedes utilizarlo, estudiar su código, modificarlo y distribuirlo, también con fines comerciales, sin pagar regalías por esa licencia.
  • Redistribución: debes incluir una copia de la licencia, conservar los avisos aplicables de autoría y atribución y, cuando corresponda, los del archivo NOTICE.
  • Cambios identificados: si distribuyes archivos modificados, debes indicar de forma visible que los has cambiado.
  • Sin obligación general de publicar tus cambios: puedes integrarlos en productos con otra licencia, incluso cerrados, respetando las condiciones de Apache 2.0 sobre el material reutilizado.
  • Patentes y garantías: incluye una concesión de determinadas patentes de los contribuidores, con condiciones. El software se entrega sin garantías y con limitación de responsabilidad, salvo las excepciones previstas.

La distribución puede incluir componentes de terceros con otras licencias. Puedes consultar el archivo de licencia de Hadoop 3.4.1 y el texto completo de Apache License 2.0.

Apache Hadoop agrupa componentes para almacenar y procesar conjuntos de datos que superan la capacidad práctica de una única máquina. HDFS almacena los datos; YARN asigna recursos; MapReduce ejecuta procesamiento por lotes; Hive aporta una capa de consulta similar a SQL.

Componente Responsabilidad
HDFS Almacena ficheros grandes distribuidos por bloques.
YARN Decide dónde se ejecutan aplicaciones y qué recursos reciben.
MapReduce Ejecuta transformaciones y agregaciones por lotes.
Hive Consulta ficheros de HDFS con HiveQL.

La idea central es acercar el procesamiento a los datos: se distribuyen bloques entre nodos y se ejecutan tareas cerca de ellos, en vez de mover un fichero masivo a un solo equipo.

Imagina un histórico de registros de varios terabytes que debes recorrer para calcular totales diarios. Al repartir archivos grandes entre equipos, HDFS permite que distintas tareas lean partes del histórico en paralelo. Su diseño prioriza el caudal de datos —cuántos datos se transfieren por unidad de tiempo— sobre la latencia —cuánto tarda en responder una petición concreta—. El beneficio depende también del procesamiento, de la red y del equilibrio de la carga: diez nodos no garantizan dividir por diez el tiempo.

Este patrón encaja con archivos grandes que se escriben y después se leen muchas veces, normalmente mediante recorridos secuenciales. HDFS permite añadir datos al final y truncar archivos, pero no actualizar bytes en posiciones arbitrarias como si fueran registros de una base de datos. Para modificar con frecuencia una fila o resolver consultas puntuales con baja latencia, una base de datos como PostgreSQL puede ser más adecuada.

Muchos archivos pequeños también tienen un coste: cada archivo y sus bloques requieren metadatos que administra el NameNode. El problema no es que cada archivo reserve físicamente 128 MiB, sino la sobrecarga de gestionar y abrir un número elevado de archivos. Más adelante estudiaremos cómo los formatos y la organización física influyen en esas lecturas.

Fuente: arquitectura de HDFS 3.4.1.

HDFS divide los ficheros en bloques —habitualmente de 128 MiB— y reparte esos bloques entre DataNodes. Cada bloque puede replicarse varias veces para mantener disponibilidad si falla un nodo.

METADATOS
Cliente ── solicita ubicaciones ──► NameNode
Cliente ◄─ devuelve ubicaciones ─── NameNode
DATOS: ejemplo de lectura de una réplica
Cliente ◄──── bytes del bloque A ── DataNode 1
COLOCACIÓN: copias existentes del mismo bloque
DataNode 1: A DataNode 2: A DataNode 3: A

El cliente consulta al NameNode y lee los bytes directamente de un DataNode que tenga una réplica disponible. Las copias enumeradas al final representan dónde reside el bloque, no un recorrido a través del NameNode. En la escritura, los DataNodes propagan las réplicas mediante el pipeline que explicaremos después.

  • NameNode: mantiene el espacio de nombres y metadatos; no guarda bloques de usuario.
  • DataNode: conserva bloques físicos, atiende lecturas/escrituras y envía heartbeats.
  • Secondary NameNode: genera checkpoints de metadatos; no es un NameNode de respaldo.

Secondary NameNode: un contable asistente, no un relevo

Section titled “Secondary NameNode: un contable asistente, no un relevo”

El NameNode conserva una imagen ordenada del espacio de nombres (fsimage) y un registro de los cambios recientes (edits). Para que ese registro no crezca indefinidamente, el Secondary NameNode realiza periódicamente un checkpoint: obtiene ambos, integra los cambios y genera una imagen consolidada que conserva como punto de recuperación de metadatos.

La metáfora útil es la de un contable asistente. El NameNode lleva el libro de cuentas principal y anota las operaciones recientes en una libreta; el Secondary NameNode toma una copia de ambos, ordena esas anotaciones y prepara una versión consolidada del libro. No atiende clientes ni guarda bloques de usuario.

NameNode: fsimage + edits ──► Secondary NameNode: checkpoint consolidado

Si el NameNode falla, el Secondary NameNode no ocupa automáticamente su lugar. La alta disponibilidad requiere una arquitectura específica de NameNodes activos/en espera y mecanismos de conmutación; un checkpoint solo ayuda a mantener los metadatos consolidados.

Un fichero de 300 MiB se divide en tres bloques con tamaño de 128 MiB. Con factor de replicación tres, HDFS intenta mantener tres copias de cada bloque en nodos distintos; el espacio distribuido usado será aproximadamente tres veces el tamaño lógico.

Cuando un DataNode deja de enviar heartbeats, el NameNode detecta bloques subreplicados y puede solicitar una nueva copia desde una réplica sana. Añadir DataNodes incrementa capacidad y paralelismo: es escalabilidad horizontal.

Un fichero de 300 MiB se divide en tres bloques y cada bloque se replica en los tres DataNodes con factor de replicación 3.

Lee el esquema de izquierda a derecha. El fichero original contiene 300 MiB, de modo que se forman dos bloques completos de 128 MiB y un último bloque de 44 MiB: 128 + 128 + 44 = 300. El último bloque no reserva otros 128 MiB de datos útiles. Las flechas representan la colocación final de copias: el bloque 1 aparece en A, B y C, y ocurre lo mismo con los bloques 2 y 3. Hay nueve copias de bloques, pero no nueve ficheros distintos en el espacio de nombres. El tamaño lógico continúa siendo 300 MiB y el almacenamiento de los datos replicados es aproximadamente 900 MiB, sin contar metadatos ni otras sobrecargas.

Este dibujo describe dónde terminan los bloques, no todos los mensajes de la escritura. El cliente solicita destinos al NameNode y los DataNodes transmiten las réplicas mediante un pipeline. Tampoco demuestra que A, B y C sean máquinas físicas distintas: eso depende del despliegue que construyamos.

Qué ocurre al escribir y al leer un fichero

Section titled “Qué ocurre al escribir y al leer un fichero”

Cuando subes un fichero con hdfs dfs -put, el cliente no lo envía primero como un único archivo al NameNode. El NameNode decide qué DataNodes pueden alojar cada bloque y devuelve esa información al cliente. Después, el cliente transmite los bloques a los DataNodes siguiendo la política de réplicas. El NameNode conserva el mapa; los DataNodes conservan los bytes.

Escritura
cliente ── consulta destinos ──► NameNode
cliente ── bloques y réplicas ─► DataNodes
Lectura
cliente ── consulta ubicaciones ► NameNode
cliente ◄──── bloques ───────── DataNodes

Esta separación explica dos ideas que se repetirán durante el módulo:

  • el NameNode es esencial aunque no guarde los ficheros de usuario;
  • una réplica no es una copia que el alumnado deba gestionar manualmente: HDFS controla su ubicación y su estado.

Un nodo para comprender; varios para comprobar

Section titled “Un nodo para comprender; varios para comprobar”

Antes de instalar, distingue los modos de ejecución de Hadoop:

Modo Procesos y almacenamiento Qué permite comprobar
Local o standalone Un trabajo MapReduce se ejecuta en una JVM y utiliza archivos locales, sin demonios HDFS. Algoritmos y resultados sin desplegar un clúster.
Pseudodistribuido Los demonios se ejecutan como procesos separados en una misma máquina. HDFS gestiona los archivos. Configuración, comunicación entre procesos y operaciones HDFS.
Distribuido Los servicios se reparten entre varios nodos. Coordinación, distribución de bloques y ejecución de tareas entre nodos.

Una JVM es una máquina virtual de Java: ejecuta programas Java y no equivale a una máquina virtual de sistema operativo. En nuestro laboratorio, los nodos distribuidos serán contenedores de un mismo equipo. Esa separación lógica permite observar mecanismos, pero conserva un único punto de fallo físico en el anfitrión.

Primero ejecutaremos un WordCount en modo local para comprobar que Hadoop funciona como programa. Después construiremos un clúster pseudodistribuido clásico, con NameNode y DataNode en la misma máquina: escribiremos su configuración, formatearemos el NameNode y arrancaremos los procesos que forman HDFS. En el bloque 02 retomaremos este mismo HDFS para practicar operaciones, administración y recuperación.

Fuente: modos local y pseudodistribuido en Hadoop 3.4.1.

M01-HDFS-01 — Instalar HDFS manualmente en un contenedor

Section titled “M01-HDFS-01 — Instalar HDFS manualmente en un contenedor”

Vamos a preparar Hadoop y probar primero su ejecución local con WordCount. Después construiremos un laboratorio pseudodistribuido: NameNode, DataNode y Secondary NameNode se ejecutarán como procesos Java separados dentro de un mismo contenedor. Usaremos Ubuntu 22.04 con Java 11 (eclipse-temurin:11-jdk-jammy) y Hadoop 3.4.1. Docker proporciona el sistema aislado; la instalación, configuración y comprobación de Hadoop se realizan manualmente. El bloque 02 reutilizará esta instalación.

Recupera de M00 las diferencias entre anfitrión y contenedor, usuario root y usuario ordinario, variable de entorno y archivo de configuración. En esta práctica no se usa sudo: las tareas de instalación se ejecutan como root, y Hadoop se administra con la cuenta hadoop.

1. Crear el contenedor desde el anfitrión

Section titled “1. Crear el contenedor desde el anfitrión”

En Bash/Zsh del equipo anfitrión, crea el contenedor:

Terminal window
docker run --name hadoop-manual --hostname hadoop \
-p 127.0.0.1:9870:9870 -p 127.0.0.1:9000:9000 \
-it eclipse-temurin:11-jdk-jammy bash

En PowerShell, la misma orden se escribe en una línea:

Terminal window
docker run --name hadoop-manual --hostname hadoop -p 127.0.0.1:9870:9870 -p 127.0.0.1:9000:9000 -it eclipse-temurin:11-jdk-jammy bash

--name permite recuperar el contenedor en otra sesión; --hostname establece el nombre que usarán los servicios dentro de él. -p publica las interfaces solo en el propio anfitrión. -it abre una terminal y bash es el proceso principal. No añadimos --rm: al detenerlo se conservan las herramientas, configuraciones y datos de su capa de escritura. Esa conservación dura mientras exista el contenedor; más adelante un volumen desacoplará los datos de su ciclo de vida.

El prompt cambia y las siguientes órdenes se ejecutan dentro del contenedor, como root. Comprueba el punto de partida:

Terminal window
whoami
hostname
cat /etc/os-release
java -version

Debes reconocer el usuario root, el nombre hadoop, Ubuntu 22.04 y Java 11. No continúes desde una terminal del anfitrión por tener ambas ventanas abiertas.

Volver a entrar si el contenedor está detenido

Section titled “Volver a entrar si el contenedor está detenido”

Si cierras el Bash principal con exit, el contenedor queda detenido. Para recuperar el mismo contenedor en otra sesión, ejecuta desde el anfitrión, en Bash/Zsh o PowerShell:

Terminal window
docker start -ai hadoop-manual
  • docker start arranca el contenedor que ya creaste y conserva los archivos, herramientas y ajustes guardados en él.
  • -a conecta la salida del contenedor a tu terminal y -i conecta la entrada. Juntas te devuelven al Bash del contenedor, como root, para retomar la práctica.

Si ya habías configurado los servicios de SSH y HDFS, arráncalos siguiendo el paso 9. El arranque del contenedor inicia su Bash principal y los servicios se preparan desde esa sesión.

Recuperar el acceso web si falta el puerto 9870

Section titled “Recuperar el acceso web si falta el puerto 9870”

Con el contenedor en marcha, comprueba desde el anfitrión si tiene publicado el puerto de la web del NameNode:

Terminal window
docker port hadoop-manual 9870/tcp

Si devuelve 127.0.0.1:9870, el puerto ya está publicado. La web responderá cuando el NameNode esté disponible. Si Docker indica que falta la publicación, puedes recuperar la instalación en un contenedor nuevo con los puertos correctos. Comprueba primero los montajes:

Terminal window
docker inspect --format '{{json .Mounts}}' hadoop-manual

Si devuelve [], los archivos de la práctica están en la capa de escritura del contenedor y puedes conservarlos en una imagen local. Si aparecen montajes, revisa cómo conservarlos antes de continuar, porque docker commit solo guarda los cambios del contenedor fuera de los montajes.

Si HDFS ya está en marcha, detenlo con stop-dfs.sh como hadoop y sal de las shells según el paso 9. Con el contenedor original detenido, ejecuta desde el anfitrión:

Terminal window
docker commit hadoop-manual hadoop-manual:con-puertos
docker run --name hadoop-manual-web --hostname hadoop -p 127.0.0.1:9870:9870 -p 127.0.0.1:9000:9000 -it hadoop-manual:con-puertos bash
  • docker commit guarda la instalación y los archivos del contenedor en la imagen local hadoop-manual:con-puertos.
  • docker run crea hadoop-manual-web desde esa imagen y publica los puertos en el anfitrión. El contenedor original queda como respaldo.

Retoma la práctica donde la dejaste. Si ya habías formateado el NameNode, reutiliza sus metadatos y sigue el arranque de SSH y HDFS del paso 9. Cuando el NameNode esté disponible, abre http://localhost:9870. Para sesiones posteriores, usa docker start -ai hadoop-manual-web.

2. Preparar herramientas, identidad y directorios

Section titled “2. Preparar herramientas, identidad y directorios”

La imagen ya proporciona Java, pero necesitamos herramientas para descargar Hadoop, editar su configuración, arrancar sus servicios e inspeccionar procesos. apt-get update actualiza el catálogo de paquetes disponibles; no actualiza por sí solo los programas instalados. Después, apt-get install instala los paquetes indicados y sus dependencias. La opción -y acepta automáticamente las confirmaciones de instalación.

Para empezar, instalaremos los siguientes paquetes:

Paquete Para qué sirve Uso en este laboratorio
ca-certificates Proporciona certificados de autoridades de confianza para verificar la identidad de servidores HTTPS. Permite que curl compruebe el certificado del servidor de Apache al descargar Hadoop. No cifra por sí mismo la conexión: aporta los certificados de confianza que usa la herramienta.
curl Transfiere datos desde o hacia una dirección URL; admite, entre otros, HTTP y HTTPS. Descargaremos el archivo comprimido de Hadoop desde el archivo oficial de Apache.
nano y vim Editores de texto de terminal. Editaremos la configuración de SSH, las variables del usuario y los archivos XML de Hadoop.
diffutils Proporciona cmp. En el bloque 02 compararemos byte a byte el original local y una copia descargada de HDFS.
openssh-client Incluye el cliente ssh y herramientas como ssh-keygen y ssh-keyscan. Crearemos las claves y comprobaremos las conexiones a localhost y hadoop que necesitan los scripts clásicos de arranque.
openssh-server Incluye el servidor sshd, que recibe y autentica conexiones SSH. Permitirá que el cliente SSH se conecte al propio contenedor para arrancar los demonios de HDFS. No publicaremos el puerto 22 en el anfitrión.
procps Incluye utilidades para consultar procesos y recursos, como ps, top y free. Podremos inspeccionar los procesos del contenedor y diagnosticar si un servicio está ejecutándose. jps, que usaremos para identificar procesos Java, procede del JDK, no de este paquete.
Terminal window
apt-get update
apt-get install -y ca-certificates coreutils curl diffutils nano openssh-client openssh-server procps sed vim
groupadd --system hadoop
useradd --create-home --shell /bin/bash --gid hadoop hadoop
passwd -d hadoop
mkdir -p /run/sshd /var/lib/hadoop/namenode /var/lib/hadoop/datanode
chmod 0755 /run/sshd
chown -R hadoop:hadoop /var/lib/hadoop

La cuenta hadoop separa el servicio de la cuenta administradora. passwd -d desbloquea la cuenta recién creada para este laboratorio. Más adelante configuraremos SSH para admitir únicamente claves públicas y arrancaremos su servidor; la primera ejecución local de Hadoop no lo necesita.

Como root, sitúate en /tmp y descarga la versión fijada desde el archivo oficial de Apache. curl -f informa de errores HTTP, -L sigue redirecciones y -O conserva el nombre del archivo. En curl, -C - calcula el punto de reanudación a partir del archivo local: si la descarga se interrumpe, repite la misma orden desde /tmp para continuar con los bytes que faltan, siempre que el servidor admita la reanudación. Si el archivo todavía no existe, la descarga empieza desde el principio.

Terminal window
cd /tmp
curl -fLO -C - https://archive.apache.org/dist/hadoop/common/hadoop-3.4.1/hadoop-3.4.1.tar.gz

Continúa solo cuando curl termine sin errores. No extraigas un archivo cuya descarga siga incompleta. tar -xzf extrae un archivo comprimido y -C elige el directorio de destino; esta opción de tar es distinta de la reanudación de curl.

Terminal window
tar -xzf hadoop-3.4.1.tar.gz -C /opt
mv /opt/hadoop-3.4.1 /opt/hadoop
chown -R hadoop:hadoop /opt/hadoop
ls /opt/hadoop

Al hacer el ls /opt/hadoop debes encontrar bin, sbin, etc y share.

  • bin contiene los clientes
  • sbin los scripts de administración
  • etc/hadoop la configuración
  • share las bibliotecas y ejemplos.

4. Preparar el entorno de la cuenta de servicio

Section titled “4. Preparar el entorno de la cuenta de servicio”

Ahora cambia de identidad (vamos a acceder como hadoop). su - abre una sesión del usuario y sitúa su directorio personal como punto de partida:

Terminal window
su - hadoop
whoami
pwd
nano ~/.bashrc

Asegúrate que estas en la home de hadoop /home/hadoop. Añade al final de .bashrc estas líneas, guarda y cierra el editor:

.bashrc
export HADOOP_HOME=/opt/hadoop
export HADOOP_CONF_DIR=$HADOOP_HOME/etc/hadoop
export JAVA_HOME=/opt/java/openjdk
export PATH=$JAVA_HOME/bin:$HADOOP_HOME/bin:$HADOOP_HOME/sbin:$PATH

HADOOP_HOME localiza la instalación; HADOOP_CONF_DIR, sus XML; JAVA_HOME, Java. Ampliar PATH permite escribir hdfs sin anteponer /opt/hadoop/bin/ y encontrar herramientas del JDK como java y jps. Definir JAVA_HOME señala dónde está Java, pero no añade por sí solo sus ejecutables a PATH.

Carga la configuración en la sesión actual y comprueba el resultado:

Terminal window
source ~/.bashrc
command -v hdfs
"$JAVA_HOME/bin/java" -version

Hasta ahora has escrito las órdenes en una shell interactiva: tienes un prompt y Bash espera tus comandos. Al ejecutar source ~/.bashrc, las variables quedan disponibles en esa shell y en los procesos que lance después.

Sin embargo, los scripts de arranque de Hadoop también ejecutan órdenes mediante SSH. Esa conexión crea una sesión distinta en el destino, aunque el destino sea el mismo contenedor. No hereda automáticamente todas las variables de la terminal desde la que has iniciado SSH. Además, una shell que recibe una orden para ejecutarla sin interacción puede cargar otros archivos de inicio o dejar de leer .bashrc antes de llegar a las líneas que añadiste. Por eso, comprobar que java funciona en tu terminal no garantiza que los procesos arrancados mediante SSH encuentren Java.

Hadoop dispone de su propio archivo de entorno, hadoop-env.sh, que sus scripts cargan al preparar la ejecución. Vamos a indicar allí también la ubicación de Java para que el arranque tenga esa información sin depender de la configuración de tu terminal. Como hadoop, abre:

Terminal window
nano /opt/hadoop/etc/hadoop/hadoop-env.sh

Añade al final:

hadoop-env.sh
export JAVA_HOME=/opt/java/openjdk

Las dos configuraciones tienen destinatarios distintos: .bashrc prepara tu terminal de trabajo y hadoop-env.sh prepara el entorno de los scripts de Hadoop. Ambas deben señalar a la misma instalación de Java.

Primera ejecución: Hadoop standalone y WordCount

Section titled “Primera ejecución: Hadoop standalone y WordCount”

Hadoop standalone, también llamado modo local, ejecuta un trabajo Hadoop en un único proceso Java y utiliza el sistema de archivos local. Basta con disponer de Java, la distribución de Hadoop y sus variables de entorno. No requiere arrancar NameNode, DataNode, YARN ni un servidor SSH.

Esto permite probar un programa y comprobar su resultado antes de desplegar servicios. El trabajo empieza al lanzar la orden y termina al obtener la salida: no queda un servicio Hadoop atendiendo peticiones. Aunque lo ejecutemos dentro de Docker, el procesamiento sigue siendo local al contenedor; no reparte tareas entre máquinas ni replica los archivos.

Vamos a ejecutar WordCount, un programa incluido en los ejemplos de Hadoop que cuenta cuántas veces aparece cada palabra. No tienes que programarlo todavía: ahora nos interesa reconocer entrada, ejecución y salida. Su funcionamiento MapReduce se desarrollará en el bloque 04.

Continúa dentro del contenedor, como hadoop. Prepara una carpeta local y un texto pequeño:

Terminal window
mkdir -p /home/hadoop/wordcount-local/entrada
cd /home/hadoop/wordcount-local
printf 'hadoop datos hadoop\ndatos archivo\n' > entrada/texto.txt
cat entrada/texto.txt

La muestra contiene cinco palabras en dos líneas. Usamos minúsculas y evitamos puntuación para que el recuento sea fácil de comprobar. Tanto la carpeta como el archivo son locales al contenedor.

Lanza el programa de ejemplo:

Terminal window
hadoop jar "$HADOOP_HOME/share/hadoop/mapreduce/hadoop-mapreduce-examples-3.4.1.jar" wordcount -Dmapreduce.framework.name=local -Dfs.defaultFS=file:/// entrada salida
  • hadoop jar ejecuta un programa Java empaquetado en un archivo JAR.
  • La ruta identifica el paquete de ejemplos de Hadoop 3.4.1, incluido en share; no es necesario descargar otro programa.
  • wordcount selecciona el ejemplo que cuenta palabras.
  • -Dmapreduce.framework.name=local indica que el trabajo se ejecute localmente, sin solicitar recursos a YARN.
  • -Dfs.defaultFS=file:/// indica que se utilicen archivos locales. Así este ejemplo mantiene su comportamiento aunque lo repitas después de configurar HDFS.
  • entrada es el directorio local que contiene el texto y salida es el directorio local donde el trabajo escribirá su resultado. Las dos rutas se resuelven desde /home/hadoop/wordcount-local.

Durante la ejecución aparecerán registros de progreso. Espera a que termine y comprueba los archivos de salida:

Terminal window
ls salida
cat salida/part-r-00000
jps

El trabajo debe generar part-r-00000, con pares palabra/recuento separados por una tabulación, y el marcador _SUCCESS si termina correctamente.

  • jps permite contrastar que no hemos necesitado arrancar los demonios NameNode, DataNode, ResourceManager o NodeManager. En este contenedor de la práctica, una vez terminado el trabajo, normalmente solo aparecerá el propio Jps.

El contenido esperado de part-r-00000 es:

part-r-00000

archivo 1
datos 2
hadoop 2

Actividad: contar las palabras de Romeo y Julieta

Section titled “Actividad: contar las palabras de Romeo y Julieta”

Aplica el ejemplo anterior a un archivo real: la edición en inglés de Romeo and Juliet, de William Shakespeare, disponible en Project Gutenberg, libro 1513. Debes descargar la versión Plain Text (TXT en UTF-8), no la página HTML ni un EPUB.

Resuelve estas tareas utilizando las órdenes del ejemplo anterior:

  1. Ejecuta WordCount en modo standalone sobre el directorio entrada. Adapta la orden del JAR de Hadoop 3.4.1, conserva las opciones de ejecución y almacenamiento locales y utiliza un directorio de salida nuevo, por ejemplo salida-romeo.
  2. Comprueba que se ha creado _SUCCESS y consulta part-r-00000. Selecciona cinco entradas del resultado y registra el texto exacto de cada una junto con su número de apariciones.
  3. Explica dónde están el archivo descargado y el resultado, y por qué no has necesitado subir el libro a HDFS ni arrancar sus servicios.
  4. ¿Esperas que Romeo, ROMEO y Romeo, se agrupen como una única palabra? Justifica tu respuesta observando el resultado: este ejemplo separa por espacios en blanco, pero no convierte a minúsculas ni elimina puntuación.
  5. ¿Cuáles son las palabras que más se repiten?

Entrega la URL y fecha de descarga, la orden ejecutada, la comprobación de finalización y una tabla con las cinco entradas elegidas y sus recuentos. Añade las respuestas breves a las preguntas. Conserva el TXT y el resultado para poder reproducir tu trabajo.

El archivo hadoop-mapreduce-examples-3.4.1.jar es un archivo JAR que agrupa clases Java compiladas y otros recursos. Podemos consultar su contenido sin extraerlo. Dentro del contenedor, como hadoop, ejecuta:

Terminal window
cd "$HADOOP_HOME/share/hadoop/mapreduce"
jar tf hadoop-mapreduce-examples-3.4.1.jar
  • jar es una herramienta del JDK para trabajar con archivos JAR.
  • t solicita listar su contenido y f indica que el argumento siguiente es el archivo que queremos consultar. Se pueden escribir juntas como tf.
  • La salida muestra rutas de archivos, entre ellas clases terminadas en .class. No es una lista de métodos Java ni una ayuda de los programas disponibles. Una clase puede contener varios métodos y muchas clases del JAR son auxiliares.

Para conocer los programas de ejemplo que podemos ejecutar por su nombre, llama al paquete sin seleccionar ninguno:

Terminal window
hadoop jar hadoop-mapreduce-examples-3.4.1.jar
  • hadoop jar ejecuta el punto de entrada del paquete.
  • Al no indicar un ejemplo, el programa muestra un mensaje de uso y una lista de nombres con descripciones, como wordcount, grep o sudoku. Puede terminar con un estado distinto de cero porque falta seleccionar un programa; aquí estamos consultando esa ayuda.
  • Esos nombres seleccionan programas registrados por el paquete. No todos reciben los mismos argumentos ni todos ejecutan trabajos MapReduce.

Puedes localizar las clases relacionadas con el sudoku sin revisar toda la lista:

Terminal window
jar tf hadoop-mapreduce-examples-3.4.1.jar | grep -i sudoku

Entre las coincidencias debe aparecer org/apache/hadoop/examples/dancing/Sudoku.class, junto con las clases auxiliares del solucionador.

Fuente: herramienta jar de Java 11.

Recuperamos el sudoku de los apuntes del curso anterior. Utiliza el programa sudoku incluido en el mismo JAR, sin instalar otra aplicación ni arrancar servicios Hadoop.

Primero prepara un archivo local, dentro del contenedor y como hadoop:

Terminal window
mkdir -p /home/hadoop/sudoku-local
cd /home/hadoop/sudoku-local
nano puzzle.txt

Guarda en puzzle.txt exactamente estas nueve filas, con espacios entre las casillas y ? para las vacías. No añadas títulos ni líneas en blanco al archivo.

puzzle.txt

8 5 ? 3 9 ? ? ? ?
? ? 2 ? ? ? ? ? ?
? ? 6 ? 1 ? ? ? 2
? ? 4 ? ? 3 ? 5 9
? ? 8 9 ? 1 4 ? ?
3 2 ? 4 ? ? 8 ? ?
9 ? ? ? 8 ? 5 ? ?
? ? ? ? ? ? 2 ? ?
? ? ? ? 4 5 ? 7 8

Ejecuta el ejemplo y observa su resultado:

Terminal window
hadoop jar "$HADOOP_HOME/share/hadoop/mapreduce/hadoop-mapreduce-examples-3.4.1.jar" sudoku puzzle.txt
  • sudoku selecciona el programa que resuelve el tablero.
  • puzzle.txt es la ruta al archivo local de entrada, relativa al directorio de trabajo actual.
  • Este programa muestra las soluciones y su número en la terminal. No necesita un directorio de salida ni genera part-r-00000 o _SUCCESS como WordCount.
  • No añadas las opciones -D de WordCount: este ejemplo interpreta sus argumentos como nombres de archivos de sudoku, no como opciones de un trabajo MapReduce.

Fuente técnica: implementación de Sudoku en Hadoop 3.4.1.

Ya has ejecutado Hadoop como programa local con una muestra pequeña y con un libro. Ahora prepararemos SSH y HDFS para que el almacenamiento funcione mediante servicios y puedas comparar ambos modos. El mismo trabajo MapReduce puede utilizar almacenamiento local o HDFS según su configuración; ejecutar un ejemplo no demuestra por sí solo procesamiento distribuido.

Fuente: modo standalone de Hadoop 3.4.1.

5. Autorizar SSH dentro del mismo contenedor

Section titled “5. Autorizar SSH dentro del mismo contenedor”

Para preparar el servidor, vuelve temporalmente a la shell root del contenedor. Estás en la sesión hadoop abierta con su - hadoop; un solo exit vuelve a la cuenta anterior (root):

Terminal window
exit
whoami
  • exit cierra la sesión de hadoop, sin cerrar todavía el contenedor.
  • whoami debe devolver root. Las órdenes de configuración del servidor siguientes se realizan con esta cuenta.

Antes de iniciar el servidor SSH, configura la autenticación para admitir claves y desactivar las contraseñas. Como root, abre el siguiente archivo:

Terminal window
nano /etc/ssh/sshd_config.d/10-hadoop-laboratorio.conf

Escribe estas tres directivas. Guardar en Nano se hace con Ctrl+O, confirmar con Intro y salir con Ctrl+X:

10-hadoop-laboratorio.conf
PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no

El servidor admitirá la clave pública de hadoop, no accesos SSH con contraseña ni accesos SSH de root. No publicamos el puerto 22 en el anfitrión: la conexión de arranque será interna al contenedor.

Terminal window
ssh-keygen -A
/usr/sbin/sshd -t
/usr/sbin/sshd

ssh-keygen -A prepara las claves de identidad del servidor si no existen. sshd -t valida la configuración sin iniciar otro servidor; si informa de un error, corrígelo antes de arrancar sshd.

Aclaración: El archivo principal del servidor sigue siendo /etc/ssh/sshd_config (es el que solemos editar normalmente). El siguiente fragmento muestra la directiva que incluye al principio:

# sshd_config
Include /etc/ssh/sshd_config.d/*.conf

Por lo que los cambios que hemos introducido en el nuevo archivo 10-hadoop-laboratorio.conf se cargarán. Al crear este nuevo archivo dejamos más “limpia” la configuración por defecto y podemos identificar de una manera más clara las modificaciones que hemos realizado para esta práctica

Vuelve a la cuenta de trabajo y carga sus variables antes de generar las claves:

Terminal window
su - hadoop
source ~/.bashrc
  • su - hadoop abre la sesión de la cuenta de servicio.
  • source ~/.bashrc carga las variables preparadas en el paso 4.

HDFS funciona mediante procesos de servicio, llamados demonios, como NameNode y DataNode. Necesitamos iniciarlos antes de almacenar archivos y detenerlos de forma ordenada cuando terminemos. Los scripts start-dfs.sh y stop-dfs.sh coordinan esas operaciones: averiguan en qué destinos deben actuar y utilizan SSH para ejecutar allí las órdenes de arranque o parada.

En un clúster con varios equipos, esos destinos pueden ser máquinas distintas. En nuestra práctica, localhost y hadoop identifican el mismo contenedor. Aunque no salimos de él, el script sigue utilizando el cliente SSH para conectarse al servidor SSH que hemos preparado dentro. Más adelante configuraremos workers con localhost para el DataNode y los XML con el nombre hadoop para los otros servicios.

Cuando ejecutes start-dfs.sh, las conexiones deben autenticarse sin detenerse a pedir una contraseña por cada destino. Para ello crearemos una pareja de claves de la cuenta hadoop y autorizaremos su clave pública en esa misma cuenta. La clave privada permitirá al cliente demostrar su identidad; el servidor comprobará la autorización en authorized_keys.

Vamos a configurar el inicio de sesión por SSH sin tener que escribir una contraseña, utilizando autenticación mediante claves. El cliente demostrará que posee una clave privada y el servidor comprobará que su clave pública está autorizada. Así, los scripts de Hadoop podrán iniciar y detener procesos sin esperar una respuesta del teclado.

Continúa como hadoop, dentro del contenedor, con el servidor SSH arrancado. Aquí ~ representa /home/hadoop: si ejecutaras estas órdenes como root, estarías preparando las claves de otra cuenta.

Terminal window
mkdir -p ~/.ssh
chmod 700 ~/.ssh
ssh-keygen -t ed25519 -N '' -f ~/.ssh/id_ed25519
cat ~/.ssh/id_ed25519.pub >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
ssh-keyscan -H localhost hadoop >> ~/.ssh/known_hosts
ssh localhost whoami
ssh hadoop whoami
  • mkdir -p ~/.ssh crea el directorio donde esta cuenta guarda sus claves y archivos de configuración SSH. -p permite que ya exista sin producir un error.
  • chmod 700 ~/.ssh permite al propietario leer, escribir y acceder al directorio, y retira el acceso al grupo y al resto de usuarios. SSH necesita que estos archivos no queden expuestos a otras cuentas.
  • ssh-keygen -t ed25519 -N '' -f ~/.ssh/id_ed25519 genera una pareja de claves:
    • -t ed25519 elige el tipo de clave.
    • -N '' deja vacía la frase de paso de la clave privada, para que su uso no pida otra contraseña durante el arranque automático. No cambia la contraseña de la cuenta hadoop.
    • -f elige el archivo de la clave privada, id_ed25519. La clave pública se guarda en id_ed25519.pub. La privada permanece en esta cuenta; la pública es la que se puede autorizar en el servidor.
  • cat ~/.ssh/id_ed25519.pub >> ~/.ssh/authorized_keys añade la clave pública a la lista de claves que el servidor admite para iniciar sesión como hadoop. >> añade contenido al final, conservando las autorizaciones existentes. En esta práctica, cliente y servidor están en el mismo contenedor: por eso autorizamos la clave pública en la misma cuenta que la ha generado.
  • chmod 600 ~/.ssh/authorized_keys permite leer y modificar esa lista únicamente a su propietario. El grupo y los demás usuarios no tienen acceso.
  • ssh-keyscan -H localhost hadoop >> ~/.ssh/known_hosts recoge las claves públicas de identidad del servidor bajo los dos nombres que utilizará Hadoop y las añade a known_hosts. -H guarda esos nombres mediante un hash. Esto permite al cliente reconocer el servidor sin detenerse a preguntar si acepta su identidad en la primera conexión. No autoriza usuarios: esa función corresponde a authorized_keys.
  • ssh localhost whoami abre una conexión al servidor del propio contenedor y ejecuta allí whoami. Al no indicar otro usuario, utiliza el de la sesión actual, hadoop. Debe devolver hadoop y cerrar la conexión, sin pedir contraseña.
  • ssh hadoop whoami repite la prueba usando hadoop como nombre de equipo. En esta orden, el primer hadoop es el destino, no un argumento que seleccione el usuario. También debe devolver hadoop: ambos nombres identifican nuestro contenedor.

Usamos ssh-keyscan sobre el contenedor local que acabamos de preparar. Esta orden recoge claves, pero no verifica por sí misma que pertenezcan al servidor legítimo; en una conexión a un servidor externo habría que contrastar su identidad por un medio fiable.

Las dos últimas pruebas deben funcionar sin pedir contraseña antes de continuar: los scripts de Hadoop utilizarán esos mismos destinos. Si ssh-keygen avisa de que id_ed25519 ya existe, no sobrescribas la clave para repetir la práctica; comprueba si ya puedes conectar. La clave privada nunca se entrega como evidencia ni se copia a otras cuentas.

6. Configurar el destino y los directorios HDFS

Section titled “6. Configurar el destino y los directorios HDFS”

Ya están preparados Java, la cuenta de servicio y las conexiones de administración. Ahora debemos responder a dos preguntas diferentes:

  • ¿A qué servicio se conecta el cliente? Lo indicaremos en core-site.xml mediante la dirección del NameNode.
  • ¿Dónde guardan los servicios su información en el disco local? Lo indicaremos en hdfs-site.xml mediante directorios separados para metadatos y bloques.

HDFS presenta al usuario un árbol de archivos distribuido, pero necesita apoyarse en el sistema de archivos local de cada nodo para conservar físicamente su información. Por eso creamos antes /var/lib/hadoop/namenode y /var/lib/hadoop/datanode, y asignamos su propiedad a hadoop: los procesos de esa cuenta deben poder escribir en ellos. Crear esas carpetas prepara el espacio local, pero todavía no inicializa HDFS.

Continúa como hadoop. Abre el primer archivo y sustituye su contenido por el XML completo siguiente:

Terminal window
nano /opt/hadoop/etc/hadoop/core-site.xml

core-site.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<property>
<name>fs.defaultFS</name>
<value>hdfs://hadoop:9000</value>
</property>
</configuration>

fs.defaultFS indica al cliente qué sistema y qué servidor utilizar cuando una ruta no incluye un URI completo. /datos/prueba será una ruta HDFS porque el destino predeterminado es hdfs://hadoop:9000.

Abre el segundo archivo:

Terminal window
nano /opt/hadoop/etc/hadoop/hdfs-site.xml

hdfs-site.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<property>
<name>dfs.replication</name>
<value>1</value>
</property>
<property>
<name>dfs.namenode.name.dir</name>
<value>file:///var/lib/hadoop/namenode</value>
</property>
<property>
<name>dfs.datanode.data.dir</name>
<value>file:///var/lib/hadoop/datanode</value>
</property>
<property>
<name>dfs.namenode.secondary.http-address</name>
<value>hadoop:9868</value>
</property>
</configuration>

El prefijo file:/// indica una ubicación del sistema de archivos local del contenedor. El prefijo hdfs:// identifica, en cambio, un servicio HDFS. Distingue estos tres usos:

Ubicación Qué representa Quién la administra
file:///var/lib/hadoop/namenode Directorio local donde el NameNode conserva la información persistente del espacio de nombres, como fsimage y edits. El proceso NameNode.
file:///var/lib/hadoop/datanode Directorio local donde el DataNode conserva bloques y sus metadatos. El proceso DataNode.
/datos/prueba al usar hdfs dfs Directorio lógico del árbol HDFS al que accede el cliente mediante fs.defaultFS. HDFS, a petición del usuario.

Por ejemplo, subir /datos/prueba/entrada.txt a HDFS no crea una carpeta local /var/lib/hadoop/datanode/datos/prueba. El NameNode registra la ruta lógica y el DataNode guarda sus bloques con la organización interna de Hadoop. No debemos editar esos archivos internos para cambiar el contenido de un fichero HDFS.

Separar los directorios de NameNode y DataNode permite distinguir sus responsabilidades y conservar su información sin mezclarla con los ejecutables de /opt/hadoop. En esta fase ambos siguen dentro de la capa de escritura del mismo contenedor: separar carpetas no crea discos independientes ni protege frente a su eliminación. En el bloque siguiente conservaremos este mismo contenedor para reutilizar la instalación y los datos.

El factor de replicación 1 corresponde al único DataNode existente. La última propiedad configura la dirección HTTP del Secondary NameNode en hadoop:9868; los scripts de arranque también utilizan ese nombre para localizar el destino donde iniciarlo. Por eso hemos comprobado previamente la conexión SSH a hadoop.

Abre por último /opt/hadoop/etc/hadoop/workers con nano y deja una sola línea: localhost. Es la lista de destinos para iniciar DataNodes con los scripts clásicos; no crea nodos nuevos por escribir más nombres.

El espacio de nombres es el árbol lógico que el NameNode administra: rutas de directorios y archivos, junto con sus metadatos. Antes del primer arranque necesitamos inicializar el almacenamiento del NameNode para que pueda conservar ese árbol y registrar sus cambios.

La orden hdfs namenode -format prepara esa estructura en el directorio local configurado mediante dfs.namenode.name.dir. Crea los metadatos iniciales y los identificadores del sistema, que permiten relacionar el NameNode con los bloques registrados por los DataNodes. No formatea el disco de Ubuntu ni crea todavía el fichero de prueba que subiremos después.

El formato y el arranque son operaciones distintas: formatear inicializa un sistema nuevo; arrancar abre el sistema existente y pone sus servicios en funcionamiento. Al reiniciar el contenedor debemos reutilizar los metadatos y bloques conservados.

En esta primera ejecución, inicializa el NameNode y después arranca los servicios:

Terminal window
hdfs namenode -format
start-dfs.sh
jps
hdfs dfsadmin -report

jps debe mostrar NameNode, DataNode y SecondaryNameNode, además del propio Jps; sus PID cambian entre ejecuciones. El informe debe mostrar un DataNode vivo. Que un proceso Java exista no garantiza que se haya registrado: necesitamos ambas comprobaciones. Si el sistema está todavía en modo seguro, espera a que registre el DataNode y consulta hdfs dfsadmin -safemode get antes de escribir.

8. Seguir un fichero desde el cliente al bloque

Section titled “8. Seguir un fichero desde el cliente al bloque”

Vamos a seguir un mismo contenido en tres vistas: el archivo local de origen, la ruta lógica de HDFS y el bloque físico del DataNode. Continúa dentro del contenedor, como hadoop, con HDFS arrancado.

Dos sistemas de archivos y cómo acceder a ellos

Section titled “Dos sistemas de archivos y cómo acceder a ellos”

Hasta ahora has utilizado órdenes Linux como ls, mkdir y cat para trabajar con los archivos locales del contenedor. Esas órdenes siguen actuando sobre el mismo sistema local: arrancar Hadoop no cambia su significado ni convierte las carpetas locales en directorios HDFS.

Al ejecutar start-dfs.sh en el paso anterior, has puesto en funcionamiento NameNode, DataNode y Secondary NameNode. Ahora el NameNode puede atender operaciones sobre el árbol de directorios HDFS y el DataNode puede guardar y servir bloques. El Secondary NameNode prepara checkpoints de metadatos. Los procesos permanecen ejecutándose después de que termine el script de arranque.

Para utilizar ese almacenamiento necesitamos un cliente: el programa que envía las peticiones a los servicios. El comando hdfs viene con la distribución de Hadoop y permite realizar distintas operaciones; al añadir dfs seleccionamos las operaciones sobre archivos. En este laboratorio, fs.defaultFS=hdfs://hadoop:9000 indica que esas operaciones deben dirigirse a HDFS.

Por tanto, hay dos condiciones distintas: la configuración indica dónde conectarse y los servicios arrancados atienden la petición. start-dfs.sh no instala el comando hdfs ni crea una carpeta local /datos. Si los servicios están detenidos, el cliente sigue existiendo, pero no podrá completar las operaciones que requieran conectarse a ellos.

Empieza con una consulta que no modifica datos:

Terminal window
hdfs dfs -ls /
  • hdfs ejecuta el cliente de Hadoop.
  • dfs selecciona las operaciones sobre archivos.
  • -ls solicita un listado.
  • / es la raíz del sistema configurado: aquí, la raíz de HDFS, no la raíz local de Ubuntu.

En una instalación recién formateada, esa raíz puede estar vacía y el comando no mostrar archivos. Si aparece un error de conexión, revisa que HDFS esté arrancado; un listado vacío y un fallo de conexión no significan lo mismo.

Qué quieres consultar Orden Sistema consultado
Directorios locales del contenedor ls / Sistema de archivos local de Ubuntu.
Directorios del almacenamiento HDFS hdfs dfs -ls / Servicio configurado en fs.defaultFS.

Primero crea el archivo de origen en el sistema local:

Terminal window
printf 'HDFS distribuye bloques.\n' > /tmp/entrada.txt
  • printf escribe el texto y un salto de línea final.
  • > guarda esa salida en el archivo local /tmp/entrada.txt. Todavía no hemos escrito nada en HDFS.

Ahora crea el directorio de destino en HDFS:

Terminal window
hdfs dfs -mkdir -p /datos/prueba
  • hdfs dfs envía la operación al sistema de archivos configurado, HDFS en nuestro caso.
  • -mkdir solicita crear un directorio.
  • -p permite crear los niveles necesarios y que el directorio ya exista.
  • /datos/prueba es una ruta lógica de HDFS. Esta orden no crea /datos/prueba en el disco local de Ubuntu.

Por último, copia el archivo local al directorio HDFS:

Terminal window
hdfs dfs -put /tmp/entrada.txt /datos/prueba/
  • -put copia un archivo desde el sistema local hacia HDFS.
  • /tmp/entrada.txt es el archivo local de origen.
  • /datos/prueba/ es el directorio HDFS de destino. El NameNode gestiona la ruta y el DataNode recibe los bytes del archivo.

El origen de -put es /tmp/entrada.txt, del sistema local del contenedor. El destino es /datos/prueba/, del sistema HDFS indicado por fs.defaultFS. Como el destino es un directorio, se conserva el nombre entrada.txt: la nueva ruta lógica es /datos/prueba/entrada.txt. El archivo original de /tmp permanece en su sitio.

Si repites -put y el archivo ya existe en HDFS, puede informar de ello: comprueba la copia existente antes de decidir qué hacer.

Localizar el archivo desde las dos consolas

Section titled “Localizar el archivo desde las dos consolas”

Primero inspecciona el origen con los comandos Linux, que actúan sobre el disco local:

Terminal window
ls -l /tmp/entrada.txt
cat /tmp/entrada.txt
ls -ld /datos/prueba
  • ls -l muestra los detalles del archivo local de origen.
  • cat lee su contenido desde el sistema local.
  • ls -ld comprueba el propio directorio local /datos/prueba, sin listar su interior. No consulta HDFS.

En este contenedor nuevo, la última orden debe indicar que /datos/prueba no existe en el sistema local. No significa que haya fallado la subida: ls no consulta HDFS. Si alguien ha creado antes una carpeta local con ese mismo nombre, será otra ubicación independiente.

Ahora consulta el espacio HDFS:

Terminal window
hdfs dfs -ls /datos/prueba
hdfs dfs -cat /datos/prueba/entrada.txt
  • hdfs dfs -ls lista los archivos del directorio lógico HDFS.
  • hdfs dfs -cat lee el contenido del archivo a través del cliente HDFS.

Debes encontrar entrada.txt y leer HDFS distribuye bloques.. El prefijo de la orden cambia el sistema consultado: ls y hdfs dfs -ls no recorren el mismo árbol de directorios.

Localizar la misma ruta desde la web del NameNode

Section titled “Localizar la misma ruta desde la web del NameNode”

En el navegador del anfitrión, abre http://localhost:9870. Entra en Utilities → Browse the file system y navega a /datos/prueba o escribe esa ruta en el campo del explorador. Debe aparecer entrada.txt.

La web muestra el espacio de nombres lógico de HDFS, igual que hdfs dfs -ls. Por tanto, aquí sí deben coincidir la carpeta y el nombre que has utilizado al subir el archivo. No estás explorando /tmp ni el disco local del contenedor, aunque abras la web desde tu ordenador.

Haz clic en entrada.txt (marca 1 de la captura). En la ventana File information, abre el selector de Block information y elige Block 0, el primer bloque del archivo. La marca 2 señala el Block ID que vamos a relacionar con la copia física del DataNode.

Ventana File information de entrada.txt. La marca 1 señala el archivo en el listado y la marca 2, su Block ID 1073741825.

Estos son los datos del bloque seleccionado en la captura. Usa los valores que aparezcan en tu propia instalación al realizar la práctica.

  • Block ID (1073741825). Identifica el bloque dentro de su block pool. Para localizar el archivo de datos en el disco local del DataNode, añade el prefijo blk_ al número. Aquí buscaríamos blk_1073741825.
  • Block Pool ID (BP-…). Identifica el grupo de bloques de este HDFS. Verás el mismo identificador en el nombre de una carpeta del DataNode.
  • Generation Stamp (1001). Indica la versión del bloque. Ese número también aparece en el archivo auxiliar blk_1073741825_1001.meta.
  • Size (25). Este bloque contiene 25 bytes. En el ejemplo, ahí cabe todo entrada.txt, incluido el salto de línea final.
  • Availability (localhost). Indica dónde hay una copia del bloque. En la captura aparece nuestro único DataNode.

Ahora contrasta el identificador, el tamaño y la ubicación con la salida de fsck desde la consola del contenedor:

Terminal window
hdfs fsck /datos/prueba/entrada.txt -files -blocks -locations
  • -files incluye los archivos analizados.
  • -blocks añade información de sus bloques.
  • -locations muestra las ubicaciones de las réplicas.

En esta muestra debes encontrar un bloque, factor de replicación 1 y una réplica viva. Un archivo pequeño no ocupa 128 MiB completos de datos.

Recuperación del ejercicio histórico: localizar el bloque en el disco

Section titled “Recuperación del ejercicio histórico: localizar el bloque en el disco”

La ruta lógica ya está identificada. Ahora vamos a buscar cómo ha guardado sus bytes el DataNode. En la salida de fsck encontrarás un identificador de block pool, que agrupa bloques del espacio de nombres, y un identificador de bloque. Por ejemplo:

BP-...:blk_1073741825_1001

Es un ejemplo de formato, no un valor que deba coincidir con el tuyo. En esa representación, blk_1073741825 identifica el bloque y _1001 es su sello de generación, utilizado por HDFS para distinguir versiones del bloque. El archivo local de datos se llama blk_1073741825; el sello aparece también en el nombre del archivo auxiliar .meta.

Primero busca el nombre lógico original bajo el directorio local del DataNode:

Terminal window
find /var/lib/hadoop/datanode -type f -name 'entrada.txt'
  • find /var/lib/hadoop/datanode recorre ese directorio local y sus subdirectorios.
  • -type f selecciona archivos normales.
  • -name 'entrada.txt' filtra por el nombre exacto del archivo.

No debe aparecer: el DataNode no conserva los archivos de usuario con su nombre y sus carpetas originales. Ahora guarda en una variable el identificador de tu bloque, sin el sello de generación. En esta asignación, sustituye el ejemplo por el valor que acabas de observar:

Terminal window
bloque=blk_1073741825
find /var/lib/hadoop/datanode -type f -name "$bloque"
  • bloque=… guarda el identificador observado en una variable de Bash.
  • -name "$bloque" busca el nombre que contiene esa variable, en lugar del nombre lógico entrada.txt.

¿Por qué buscamos en /var/lib/hadoop/datanode y no en /datos/prueba? Porque find es un comando Linux y solo recorre el sistema de archivos local. La propiedad dfs.datanode.data.dir de hdfs-site.xml indica que el DataNode guarda allí los bloques. /datos/prueba pertenece al árbol lógico de HDFS y se consulta mediante hdfs dfs o el explorador de :9870. HDFS no crea en el disco local una carpeta con esa misma ruta: el NameNode relaciona la ruta lógica con los identificadores de sus bloques.

Qué quieres localizar Dónde buscar Herramienta
El archivo por su nombre y ruta lógica /datos/prueba/entrada.txt en HDFS hdfs dfs -ls, hdfs dfs -cat o web :9870.
Los bytes de su bloque en el disco local /var/lib/hadoop/datanode y sus subdirectorios find y, solo para esta inspección, cat.

La búsqueda debe devolver una ruta local semejante a esta, cuyos identificadores y subdirectorios pueden variar:

/var/lib/hadoop/datanode/current/BP-.../current/finalized/subdir0/subdir0/blk_1073741825

No necesitamos adivinar esos subdirectorios: find los recorre. Para leer únicamente el archivo de datos encontrado, ejecuta:

Terminal window
find /var/lib/hadoop/datanode -type f -name "$bloque" -exec cat {} \;
  • find … -type f -name "$bloque" localiza el archivo físico del bloque.
  • -exec ejecuta una orden por cada archivo encontrado.
  • cat {} lee el archivo: find sustituye {} por su ruta real.
  • \; marca el final de la orden de -exec. La barra protege el punto y coma para que Bash lo entregue a find.

Debe aparecer el mismo texto. Esto funciona como demostración porque hemos creado un archivo de texto pequeño que cabe en un único bloque. Un archivo mayor podría repartirse entre varios bloques y nodos; leer uno de sus bloques no reconstruiría el archivo completo. Tampoco debemos interpretar archivos binarios como texto.

Completa esta tabla con tus observaciones como parte de M01-HDFS-01:

Vista Ruta o identificador que debes registrar Qué comprobar
Archivo local de origen /tmp/entrada.txt Existe y conserva el texto después de -put.
Consola HDFS /datos/prueba/entrada.txt El listado y la lectura funcionan.
Explorador web de :9870 /datos/prueba/entrada.txt Coinciden ruta lógica, nombre y tamaño con la consola HDFS.
Disco local del DataNode Ruta real del archivo blk_… Su identificador corresponde a fsck y contiene el texto de esta muestra.

Explica por qué ls /datos/prueba puede fallar mientras hdfs dfs -ls /datos/prueba funciona, y qué relación conserva el NameNode para permitir esa lectura. Guarda el archivo HDFS: lo volveremos a leer tras reiniciar el contenedor en el paso 9.

9. Parar, recuperar la sesión y verificar persistencia

Section titled “9. Parar, recuperar la sesión y verificar persistencia”

Como hadoop, detén HDFS y sal de su shell:

Terminal window
stop-dfs.sh
exit

Ahora estás de nuevo como root dentro del contenedor. Ejecuta otro exit para cerrar su Bash principal y volver al anfitrión:

Terminal window
exit

El contenedor queda detenido y conserva su instalación. En otra sesión, desde el anfitrión, recupéralo:

Terminal window
docker start -ai hadoop-manual

Dentro del contenedor, como root, prepara el directorio de ejecución de SSH y arranca su servidor; después cambia a hadoop:

En primer lugar debemos iniciar el servidor ssh

Terminal window
mkdir -p /run/sshd
chmod 0755 /run/sshd
/usr/sbin/sshd
su - hadoop
source ~/.bashrc
start-dfs.sh
hdfs dfs -cat /datos/prueba/entrada.txt

La lectura debe devolver el fichero anterior sin volver a formatear. Termina de nuevo con stop-dfs.sh y los dos exit. Puedes volver a entrar en este mismo contenedor al empezar el bloque 02. No elimines el contenedor para resolver un fallo de arranque: borrarías la instalación manual y sus datos.

Conserva los XML y un registro breve de whoami, versión de Java/Hadoop, ejecución y resultado del WordCount local, conexiones SSH, procesos, informe, lectura y fsck. Explica qué función cumple cada archivo de configuración y demuestra que el fichero reaparece tras detener y arrancar el mismo contenedor. Los nombres de bloque y PID no tienen que coincidir con los de otra persona; sí la función de cada proceso y el contenido del fichero.

El directorio local del NameNode contiene metadatos. Entre sus ficheros relevantes se encuentran fsimage_* (imagen consistente del espacio de nombres), edits_* (registro de cambios), seen_txid y VERSION. El directorio del DataNode contiene bloques y sus metadatos. En esta primera práctica esas rutas viven en la capa de escritura del contenedor; en el bloque 02 seguiremos usando el mismo contenedor y esas mismas rutas.

Se inspeccionan para comprender el sistema, pero no se editan ni borran manualmente. La administración se realiza con los comandos de HDFS, no modificando archivos internos.

Síntoma Causa habitual Primera comprobación
No aparece el DataNode HDFS no ha arrancado o hay una ruta con permisos incorrectos jps y los archivos de logs/.
No conecta con HDFS NameNode detenido o fs.defaultFS incorrecto hdfs dfsadmin -report.
Solo hay una réplica Es la limitación deliberada de esta primera práctica Pasar al Compose multinodo del bloque 03.
La salida de un job ya existe MapReduce no sobrescribe directorios Crear otra ruta o borrar solo el resultado conocido.

Hemos construido HDFS a mano para identificar qué depende de Java, qué configuración interpreta el cliente y qué procesos conserva el servicio. En el bloque 02 reutilizaremos la instalación y practicaremos operaciones, integridad y recuperación. Después, YARN incorporará la asignación de recursos para ejecutar trabajos.

Investiga un archivo propio y utiliza las evidencias para explicar cómo HDFS relaciona nombres, metadatos y bloques. Después resolverás una incidencia aparente y comprobarás los límites de la arquitectura.

Trabaja como hadoop dentro de hadoop-manual, con HDFS arrancado y un DataNode vivo. Si lo detuviste al terminar la instalación, recupera la sesión siguiendo el paso 9. Utiliza los comandos de esta página y consulta los bloques físicos en modo de solo lectura. La parte A es individual y se entrega en Aules. Las partes B y C se trabajan en clase.

  1. Crea en /tmp un archivo de texto llamado arquitectura.txt. Escribe tu nombre y una frase que permita reconocer tu contenido. Unas pocas líneas bastan para que el archivo quepa en un solo bloque.
  2. Crea en HDFS el directorio /investigacion/tu_nombre, sustituyendo tu_nombre por tu nombre escrito sin espacios, por ejemplo /investigacion/ana_garcia. Sube allí el archivo y conserva el original local.
  3. Localiza y lee el archivo con la consola HDFS. Encuéntralo también en el explorador web de :9870 y contrasta ruta, nombre y tamaño.
  4. Obtén con fsck el identificador del bloque y la ubicación de su réplica. Localiza su archivo físico mediante find bajo el directorio local del DataNode. Lee solo ese bloque de texto, sin editarlo ni confundirlo con el archivo .meta.
  5. Registra tus resultados en esta tabla. Emplea tus rutas e identificadores reales, no los del ejemplo del paso 8.
Vista Ruta o identificador observado Evidencia
Origen local Existencia y contenido del archivo original.
Consola HDFS Listado y lectura del archivo subido.
Web del NameNode Ruta lógica, nombre y tamaño.
Bloque físico del DataNode Identificador de fsck, ruta local y contenido leído.

Explica por qué el bloque no se llama arquitectura.txt y qué información conserva el NameNode para que puedas leer el archivo por su ruta lógica. Indica qué participante entrega los bytes al cliente y por qué el NameNode no necesita almacenarlos.

Entrega individual en Aules. Sube un único archivo .md con la tabla completada, los comandos que ejecutaste, las salidas relevantes y tu explicación. En la fila de la web, anota los datos que observaste en la interfaz del NameNode.

B. Diagnosticar una ruta que «no existe»

Section titled “B. Diagnosticar una ruta que «no existe»”

Una compañera afirma: «He subido el archivo y lo veo en la web, pero al buscar su carpeta con ls aparece “No such file or directory”. Creo que HDFS ha perdido los datos».

  1. Antes de ejecutar comandos, escribe una hipótesis que explique las dos observaciones sin suponer una pérdida de datos.
  2. Reproduce la comprobación con tu ruta propia: compara ls -ld y hdfs dfs -ls sobre esa misma ruta escrita. Registra qué sistema de archivos consulta cada orden y su resultado. Si ya existe una carpeta local con ese nombre, no la borres: explica por qué su existencia no demuestra que sea la carpeta HDFS.
  3. Comprueba la lectura mediante el cliente HDFS y vuelve a localizar el archivo en la web. Utiliza esos resultados y los de la parte A para confirmar o corregir tu hipótesis.
  4. Redacta una respuesta breve a la compañera: qué ha ocurrido, qué evidencias sostienen tu explicación y con qué herramienta debe consultar cada ubicación.

C. Explicar la arquitectura y sus límites

Section titled “C. Explicar la arquitectura y sus límites”
  1. Relaciona cada elemento con su función en tu investigación: cuenta hadoop, SSH, start-dfs.sh, hdfs namenode -format, NameNode, DataNode y cliente HDFS. Distingue preparación inicial, administración de procesos y acceso a los datos.

    Ejemplo de respuesta para la cuenta hadoop: «Durante la preparación inicial creé una cuenta de servicio llamada hadoop y le asigné la propiedad de los directorios donde los servicios guardarían sus metadatos y bloques. Después utilicé esa cuenta para arrancar HDFS y ejecutar el cliente, sin trabajar como root. Comprobé mi identidad con whoami. La cuenta determina con qué usuario se ejecutan esas órdenes; quien conserva los bloques es el proceso DataNode».

    Para los demás elementos, sigue este patrón: cuándo interviene, qué función cumple en tu recorrido y con qué comando o resultado lo has comprobado. Un elemento puede intervenir en más de una fase; justifica su papel sin forzarlo a una única categoría.

  2. Explica qué aporta el Secondary NameNode y por qué no sustituye automáticamente al NameNode si este falla.

  3. A partir del diagrama del fichero de 300 MiB, con bloques de 128 MiB y factor de replicación 3, calcula el tamaño de cada bloque, el número total de copias de bloques y el consumo aproximado de datos replicados. Justifica por qué el espacio lógico sigue mostrando un único archivo. Es un cálculo sobre la arquitectura del diagrama: no crees un archivo grande ni cambies la replicación del laboratorio.

  4. Contrasta ese diagrama con tu entorno real: ¿cuántos DataNodes y réplicas has observado? Explica qué protección frente a fallos no demuestra esta práctica y por qué varios contenedores en un único equipo tampoco bastarían para demostrar independencia física.

Prepara el archivo .md de la parte A para Aules y conserva el diagnóstico de la parte B y las respuestas de la parte C para revisarlos en clase. Selecciona las salidas de terminal que permitan comprobar cada resultado y mantén tus claves SSH dentro del contenedor.

Antes de darlo por terminado, comprueba que:

  • Tu contenido identificativo coincide en el archivo local, la lectura HDFS y el bloque físico de esta muestra.
  • La consola HDFS y la web muestran la misma ruta lógica, relacionada con un bloque localizado mediante su identificador real.
  • El diagnóstico distingue los dos sistemas de archivos y se apoya en resultados, no solo en definiciones.
  • Los cálculos separan tamaño lógico, bloques y réplicas, y no se presentan como una medición del laboratorio.
  • Las funciones de los componentes y los límites de protección corresponden al entorno que has utilizado.

Conserva los archivos y termina deteniendo los servicios de forma ordenada según el paso 9. No borres el contenedor ni sus datos.