Acerca de como instalar hadoop en modo distribuido

   

1. Introducción

Buenas gente, en un tutorial que escribí no hace mucho, describí cómo configurar un cluster hadoop en modo pseudo distribuido, es decir, instalar en una misma máquina de prueba todos los componentes que conforman un cluster hadoop, a saber, NameNodes, DataNodes, TaskTrackers y JobTrackers. En el mundo real, estos componentes están distribuidos entre distintas máquinas pertenecientes a un cluster, es decir, en el mundo real, Hadoop se instala en modo distribuido que es de lo que va este tutorial.

Para realizar este tutorial, usaré las máquinas que tenemos de Amazon WS y el sistema operativo será Ubuntu 14.04 LTS. La versión de Hadoop será 2.6.0.

En mi humilde opinión, la mejor manera para instalar y configurar una instalación con lo necesario para un cluster hadoop es configurar docker o ansible para ejecutar las tareas necesarias para instalar en cada máquina lo que hicimos en el tutorial del modo pseudo distribuido, es decir, crear playbooks con instrucciones a ejecutar en cada uno de los nodos del cluster.

Este tutorial va de como usar la configuración pseudo cluster de nodo simple para pasar a tener un cluster multi nodo distribuido, en el que uno de los nodos actuará como el maestro (pero también haremos que actúe como esclavo pues queremos que este nodo pueda almacenar datos y procesarlos) y el otro nodo actuará como esclavo. La idea es acabar teniendo un playbook ansible o docker que nos permita tener automatizado esta tarea.

2. Prerrequisitos

Seguir los pasos del tutorial pseudo distribuido en cada una de las máquinas que conforman nuestro cluster, en este caso concreto, voy a considerar que tengo dos maquinas, maestro y esclavo, en los cuales, quiero que el maestro haga los papeles del NameNode, DataNode, JobTracker y TaskTracker, mientras que el esclavo hará los papeles de DataNode y TaskTracker. Es absolutamente recomendable que usemos la misma configuración de rutas y dependencias necesarias en cada una de las máquinas.

Asumo que vas a poner a las maquinas en el mismo subrango de red, es decir, el maestro tendrá una ip del estilo 192.168.0.1 y el esclavo 192.168.0.2.

Ya tienes dos máquinas en modo pseudo distribuido corriendo en el mismo subrango de red? podemos continuar con el tutorial…

3. Trabajo en red

Como es normal, cada máquina perteneciente al cluster debe ser capaz de hablar una con otra, para ello, lo más sencillo es poner ambas máquinas en la misma red con la misma configuración hardware y software, por ejemplo conectar ambas máquinas a través de un concentrador (hub) o un switch.

Para hacerlo simple, asignaré la ip 192.168.0.1 al maestro y la 2 al esclavo. Actualiza los ficheros /etc/hosts en ambas máquinas con estas líneas:

192.168.0.1    master

192.168.0.2    slave

4. Asegurar acceso SSH

El usuario hduser en el maestro (hduser@master) debe ser capaz de conectar a:

a) a su propia cuenta en la máquina maestro, es decir, poder conectar usando el comando ssh master.

b) a la cuenta hduser en la máquina esclavo (hduser@slave) sin necesidad de proporcionar el password.

Si te acuerdas de lo que hicimos en el primer tutorial, generamos una clave pública ssh de lo que sería el nodo maestro y lo copiamos en la carpeta donde el demonio sshd puede usarlo para verificar la identidad del cliente que se quiere conectar. Ahora necesitamos copiar la clave del nodo maestro, el cual debería ser $HOME/.ssh/id_rsa.pub, en cada uno de los nodos esclavos que queramos añadir a nuestro cluster, es decir, a la carpeta $HOME/.ssh/authorized_keys de cada uno de los esclavos. Para ello, puedes usar el siguiente comando:

hduser@master:~$ ssh-copy-id -i $HOME/.ssh/id_rsa.pub hduser@slave

Este comando te preguntará el password del usuario hduser en la máquina esclavo, copiará la clave pública, creará el directorio que necesita y ajustará los permisos necesarios. El paso final es comprobar que todo va bien conectando con el usuario hduser desde el maestro a la cuenta de usuario hduser en la máquina esclavo.

(cuidado con esto porque no estoy al 100% seguro de que sea necesario, cuando puedas tener las máquinas reales donde confrontar este texto y hacer la revisión, podras comprobarlo. Creo que el comando ssh-copy que has lanzado desde el maestro basta para tener copiada la clave del esclavo en el maestro)

Atención, antes de lanzar el siguiente comando ssh-copy, intenta conectar desde el maestro al maestro, desde el maestro al esclavo y desde el esclavo al maestro. Si puedes, perfecto, no ejecutes estos comandos que vienen a continuación, en caso contrario, será necesario copiar la clave pública de cada uno de los nodos esclavos en el almacén de claves de la maquina o maquinas que hagan de maestro, para ello, debes lanzar este comando desde cada una de las máquinas esclavas del cluster:

hduser@slave:~$ ssh-copy-id -i $HOME/.ssh/id_rsa.pub hduser@master

Conectando al maestro desde el maestro:

hduser@master:~$ ssh master

The authenticity of host ‘master (192.168.0.1)’ can’t be established.

RSA key fingerprint is 3b:21:b3:c0:21:5c:7c:54:2f:1e:2d:96:79:eb:7f:95.

Are you sure you want to continue connecting (yes/no)? yes

Warning: Permanently added ‘master’ (RSA) to the list of known hosts.

hduser@master:~$

…y desde el maestro al esclavo:

hduser@master:~$ ssh slave

The authenticity of host ‘slave (192.168.0.2)’ can’t be established.

RSA key fingerprint is 74:d7:61:86:db:86:8f:31:90:9c:68:b0:13:88:52:72.

Are you sure you want to continue connecting (yes/no)? yes

Warning: Permanently added ‘slave’ (RSA) to the list of known hosts.

Ubuntu 14.04

5. Visión de conjunto del cluster.

Las siguientes secciones describen cómo configurar una máquina ubuntu como maestro y la otra máquina ubuntu como esclavo. El nodo maestro también actuará como esclavo porque quiero tener dos máquinas disponibles en nuestro cluster para poder dispersar la capacidad de almacenamiento y procesamiento.

Figura 1: Imagen del cluster multi nodo, como acabará siendo.

El nodo maestro ejecutará los demonios maestros para cada capa:

   

    El NameNode para la capa de almacenamiento HDFS y

    El jobtracker para la capa de procesamiento MapReduce.

Ambas máquinas correrán los mismos demonios esclavos:

    El DataNode para la capa de almacenamiento HDFS y

    El TaskTracker para la capa de  procesamiento MapReduce.

Básicamente, los demonios maestro son responsables de coordinar y manejar los demonios esclavos, mientras que los demonios esclavos son responsables del trabajo de almacenar datos y procesarlos.

Maestros contra esclavos:

   

Típicamente al menos una máquina en el cluster se designa como NameNode y otra máquina exclusivamente es el JobTracker. Estos dos nodos (namenode y jobtracker) son nodos maestros (master nodes). El resto de máquinas en el cluster actúan como DataNode y TaskTrackers y se les conoce como nodos trabajadores (worker nodes).

6. Configuración

6.1 etc/hadoop/masters (únicamente en el maestro)

A pesar de su nombre, el fichero etc/hadoop/masters define en cuál máquina Hadoop arrancará el NameNode secundario en nuestro cluster multi nodo. En nuestro caso, el namenode secundario también hace de namenode primario. El NameNode primario y el JobTracker siempre serán las máquinas en las que ejecutarán los scripts bin/start-dfs.sh y bin/start-mapred.sh, respectivamente (el NameNode primario y el JobTracker empezarán a correr en la misma máquina si ejecutas el script bin/start-all.sh).

Nota: Puedes arrancar un demonio Hadoop manualmente en una máquina usando el script bin/hadoop-daemon.sh start [namenode | secondarynamenode | datanode | jobtracker | tasktracker], el cual no tendrá en cuenta los ficheros etc/hadoop/masters o conf/slaves.

Si te preguntas qué demonios hace un NameNode secundario, te diré que básicamente se encarga de mergear los distintos ficheros fsimage y los ficheros de log de manera que éstos siempre tengan un tamaño razonable. Normalmente este nodo corre en una máquina distinta del NameNode primario pues sus requerimientos de memoria son casi iguales al del primario. El NameNode secundario se arranca usando el script bin/start-dfs.sh en los nodos especificados en el fichero etc/hadoop/masters.

En la máquina que has elegido como primario, edita el fichero /usr/local/hadoop/etc/hadoop/masters (atención, puede que no exista por defecto y lo tengas que crear tu):

hduser@HadoopMaster:/usr/local/hadoop/etc/hadoop$ sudo gedit masters

## Add name of master nodes

master

6.2 etc/hadoop/slaves (únicamente en el maestro)

Este fichero lista los nodos, uno por línea, donde los demonios Hadoop (DataNodes y TaskTrackers) correrán. En este caso, quiero que tanto el maestro como el esclavo actúen como esclavos porque quiero que ambos nodos almacenen y procesen datos.

En la máquina que hace de maestro, actualiza el fichero etc/hadoop/slaves con este contenido.

hduser@HadoopMaster:/usr/local/hadoop/etc/hadoop$ sudo gedit slaves

## Add name of slaves nodes

master

slave

Si tuviéramos nodos esclavos adicionales, solo tienes que añadirlos a este fichero, un nombre de máquina por línea:

## Add name of slaves nodes

master

slave

anotherslave01

anotherslave02

anotherslave03

Nota: el fichero etc/hadoop/slaves en la máquina maestro se usa únicamente por algunos scripts, como bin/start-dfs.sh o bin/stop-dfs.sh. Por ejemplo, si quieres añadir nodos de datos al vuelo (para un futuro tutorial lo explico en profundidad), puedes arrancar manualmente el demonio DataNode en una nueva máquina esclavo usando el script con estos parámetros:

bin/hadoop-daemon.sh start datanode

6.3 etc/hadoop/core-site.xml (todos los nodos)

Añade la propiedad fs.default.name tal y como sale en este ejemplo.

Este fichero core-site.xml especifica propiedades específicas acerca de este nodo, por ejemplo:

<configuration>

<property>

 <name>fs.default.name</name>

 <value>hdfs://master:54310</value>

 <description>The name of the default file system.  A URI whose

 scheme and authority determine the FileSystem implementation.  The

 uri’s scheme determines the config property (fs.SCHEME.impl) naming

 the File System implementation class.  The uri’s authority is used to

 determine the host, port, etc. for a filesystem.</description>

</property>

<property>

 <name>hadoop.tmp.dir</name>

 <value>/app/hadoop/tmp</value>

 <description>A base for other temporary directories.</description>

</property>

</configuration>

6.4 etc/hadoop/mapred-site.xml (todos los nodos)

En este fichero que tenemos que actualizar en todos los nodos, indicamos que nodo es el que se va a encargar de ser el JobTracker, en este caso, el nodo maestro.

<configuration>

<property>

 <name>mapred.job.tracker</name>

 <value>master:54311</value>

 <description>The host and port that the MapReduce job tracker runs

 at.  If “local”, then jobs are run in-process as a single map

 and reduce task.

 </description>

</property>

<property>

 <name>mapred.local.dir</name>

 <value>/app/hadoop/mapred-local</value>

 <description>Determines where temporary MapReduce data is written. It also may be a list of directories.

 </description>

</property>

<property>

 <name>mapred.map.tasks</name>

 <value>20</value>

 <description>As a rule of thumb, use 10x the number of slaves (i.e., number of TaskTrackers).

 </description>

</property>

<property>

 <name>mapred.reduce.tasks</name>

 <value>10</value>

 <description>As a rule of thumb, use num_tasktrackers * num_reduce_slots_per_tasktracker * 0.99. If num_tasktrackers is small (as in the case of this tutorial), use (num_tasktrackers – 1) * num_reduce_slots_per_tasktracker.

 </description>

</property>

</configuration>

6.5 etc/hadoop/hdfs-site.xml (todos los nodos)

Tenemos que cambiar la propiedad dfs.replication, que nos indica el nivel de replicación, es decir, en cuantas maquinas se va a replicar el fichero antes de volverse disponible en el cluster.

Atención, si te da por introducir un número superior al número de Data Nodes disponibles, empezarás a ver errores en los ficheros de log como “Zero targets found, forbidden1.size=1”.

Por defecto, esta propiedad está configurada con el valor “3”, pero en nuestro ejemplo solo tenemos dos maquinas, por lo que tenemos que cambiar esta propiedad.

<configuration>

<property>

 <name>dfs.replication</name>

 <value>2</value>

 <description>Default block replication.

 The actual number of replications can be specified when the file is created.

 The default is used if replication is not specified in create time.

 </description>

</property>

</configuration>

6.6 etc/hadoop/yarn-site.xml  (opcional, solo si se va a usar yarn)

## To edit file, fire the below given command

hduser@HadoopMaster:/usr/local/hadoop/etc/hadoop$ sudo gedit yarn-site.xml

## Paste/Update these lines into <configuration> tag

<property>

       <name>yarn.resourcemanager.resource-tracker.address</name>

       <value>master:8025</value>

</property>

<property>

       <name>yarn.resourcemanager.scheduler.address</name>

       <value>master:8035</value>

</property>

<property>

       <name>yarn.resourcemanager.address</name>

       <value>master:8050</value>

</property>

7. Formateando el sistema de ficheros HDFS a través del NameNode

Antes de que arranquemos nuestro nuevo cluster multi nodo, debemos formatear el sistema de ficheros distribuido entre todos los nodos de datos del cluster. Necesitas hacer esto la primera vez que configuras este nuevo cluster y recuerda, si haces esto con un cluster en producción que tiene datos reales, los vas a borrar.

Para formatear el sistema de ficheros (el cual simplemente inicializa el directorio especificado por la propiedad dfs.name.dir), debes lanzar el siguiente comando:

hduser@master:/usr/local/hadoop$ bin/hadoop namenode -format

… INFO dfs.Storage: Storage directory /app/hadoop/tmp/dfs/name has been successfully formatted.

Atención: El nombre de la tabla HDFS se almacena en el sistema de ficheros local del NameNode, concretamente en el directorio especificado por dfs.name.dir. El nombre de la tabla se usa por el NameNode para almacenar los rastreos (trackings) y la información de coordinación para los Data Nodes.

8. Arrancando el clúster multi-nodo

Arrancar el cluster se realiza en dos pasos. Empezamos arrancando los demonios HDFS, a saber, el demonio NameNode se arranca en el maestro, todos los demonios DataNode se arrancan en todos los esclavos (en este ejemplo, master y slave). Después se arrancan los demonios MapReduce, es decir, el JobTracker se arranca en el maestro, y los Task Trackers se arrancan en todos los esclavos (en este ejemplo, master y slave)

8.1 Demonios HDFS

Ejecuta el comando bin/start-dfs.sh en la maquina que quieres que sea el NameNode primario. Este comando levantará el HDFS con el NameNode corriendo y los Data Nodes se inicializan  en las máquinas que pusimos en el fichero etc/hadoop/slaves del NameNode.

En este caso, ejecutamos bin/start-dfs.sh en la maquina master:

hduser@master:/usr/local/hadoop$ bin/start-dfs.sh

starting namenode, logging to /usr/local/hadoop/bin/../logs/hadoop-hduser-namenode-master.out

slave: Ubuntu 14.04

slave: starting datanode, logging to /usr/local/hadoop/bin/../logs/hadoop-hduser-datanode-slave.out

master: starting datanode, logging to /usr/local/hadoop/bin/../logs/hadoop-hduser-datanode-master.out

master: starting secondarynamenode, logging to /usr/local/hadoop/bin/../logs/hadoop-hduser-secondarynamenode-master.out

En la máquina esclavo, podemos examinar el fichero de log logs/hadoop-hduser-datanode-slave.log para saber si todo ha ido bien o no.

… INFO org.apache.hadoop.dfs.Storage: Storage directory /app/hadoop/tmp/dfs/data is not formatted.

… INFO org.apache.hadoop.dfs.Storage: Formatting …

… INFO org.apache.hadoop.dfs.DataNode: Opened server at 50010

… INFO org.mortbay.util.Credential: Checking Resource aliases

… INFO org.mortbay.http.HttpServer: Version Jetty/5.1.4

… INFO org.mortbay.util.Container: Started org.mortbay.jetty.servlet.WebApplicationHandler@17a8a02

… INFO org.mortbay.util.Container: Started WebApplicationContext[/,/]

… INFO org.mortbay.util.Container: Started HttpContext[/logs,/logs]

… INFO org.mortbay.util.Container: Started HttpContext[/static,/static]

… INFO org.mortbay.http.SocketListener: Started SocketListener on 0.0.0.0:50075

… INFO org.mortbay.util.Container: Started org.mortbay.jetty.Server@56a499

… INFO org.apache.hadoop.dfs.DataNode: Starting DataNode in: FSDataset{dirpath=’/app/hadoop/tmp/dfs/data/current’}

… INFO org.apache.hadoop.dfs.DataNode: using BLOCKREPORT_INTERVAL of 3538203msec

Como puedes ver en la salida anterior del esclavo, se formateará automáticamente su directorio de almacenamiento (el que especificamos con la propiedad dfs.data.dir) si no se encuentra ya formateado. También creará el directorio si no existe.

En este punto, podemos usar el comando jps en el master y ver la salida:

Procesos java en el nodo maestro después de arrancar los demonios HDFS:

   

hduser@master:/usr/local/hadoop$ jps

14799 NameNode

15314 Jps

14880 DataNode

14977 SecondaryNameNode

Procesos java en el nodo esclavo después de arrancar los demonios HDFS:

hduser@slave:/usr/local/hadoop$ jps

15183 DataNode

15616 Jps

8.2 Demonios MapReduce

Ejecuta el comando bin/start-mapred.sh en la maquina que quieres que haga de JobTracker.

hduser@master:/usr/local/hadoop$ bin/start-mapred.sh

starting jobtracker, logging to /usr/local/hadoop/bin/../logs/hadoop-hadoop-jobtracker-master.out

slave: Ubuntu 14.04

slave: starting tasktracker, logging to /usr/local/hadoop/bin/../logs/hadoop-hduser-tasktracker-slave.out

master: starting tasktracker, logging to /usr/local/hadoop/bin/../logs/hadoop-hduser-tasktracker-master.out

En la máquina esclavo, puedes examinar el estado del comando inspeccionando el fichero log logs/hadoop-hduser-tasktracker-slave.log.

… INFO org.mortbay.util.Credential: Checking Resource aliases

… INFO org.mortbay.http.HttpServer: Version Jetty/5.1.4

… INFO org.mortbay.util.Container: Started org.mortbay.jetty.servlet.WebApplicationHandler@d19bc8

… INFO org.mortbay.util.Container: Started WebApplicationContext[/,/]

… INFO org.mortbay.util.Container: Started HttpContext[/logs,/logs]

… INFO org.mortbay.util.Container: Started HttpContext[/static,/static]

… INFO org.mortbay.http.SocketListener: Started SocketListener on 0.0.0.0:50060

… INFO org.mortbay.util.Container: Started org.mortbay.jetty.Server@1e63e3d

… INFO org.apache.hadoop.ipc.Server: IPC Server listener on 50050: starting

… INFO org.apache.hadoop.ipc.Server: IPC Server handler 0 on 50050: starting

… INFO org.apache.hadoop.mapred.TaskTracker: TaskTracker up at: 50050

… INFO org.apache.hadoop.mapred.TaskTracker: Starting tracker tracker_slave:50050

… INFO org.apache.hadoop.ipc.Server: IPC Server handler 1 on 50050: starting

… INFO org.apache.hadoop.mapred.TaskTracker: Starting thread: Map-events fetcher for all reduce tasks on tracker_slave:50050

En este punto, los siguientes procesos java deberian correr en el master:

hduser@master:/usr/local/hadoop$ jps

16017 Jps

14799 NameNode

15686 TaskTracker

14880 DataNode

15596 JobTracker

14977 SecondaryNameNode

Y los siguientes en el esclavo:

hduser@slave:/usr/local/hadoop$ jps

15183 DataNode

15897 TaskTracker

16284 Jps

9. Parando el cluster multi nodo

Igual que la operación de arranque, pararlo se hace en dos pasos. Aun así, el flujo de trabajo es justo el contrario del que tiene el de arranque.

Primero hay que parar los demonios MapReduce, el demonio JobTracker se para en el maestro y los demonios de los Task Trackers se paran en todos los esclavos.

Recuerda que en este ejemplo de configuración, el nodo maestro también actúa de nodo esclavo.

9.1 Demonios MapReduce

Ejecuta el comando bin/stop-mapred.sh en la máquina que hayas definido como JobTracker.

Ejecutando stop-mapred.sh en la maquina master:

hduser@master:/usr/local/hadoop$ bin/stop-mapred.sh

stopping jobtracker

slave: Ubuntu 14.04

master: stopping tasktracker

slave: stopping tasktracker

Ejecutando jps en el master:

hduser@master:/usr/local/hadoop$ jps

14799 NameNode

18386 Jps

14880 DataNode

14977 SecondaryNameNode

Ejecutando jps en el esclavo:

hduser@slave:/usr/local/hadoop$ jps

15183 DataNode

18636 Jps

9.2 Demonios HDFS

Ejecuta este comando bin/stop-dfs.sh en la máquina NameNode. Este comando apagará el HDFS parando todos los demonios de los Data Nodes tal y como aparecen listados en el fichero etc/hadoop/slaves.

En nuestro caso, ejecutamos bin/stop-dfs.sh en la maquina master:

hduser@master:/usr/local/hadoop$ bin/stop-dfs.sh

stopping namenode

slave: Ubuntu 14.04

slave: stopping datanode

master: stopping datanode

master: stopping secondarynamenode

Lanzando jps en el master:

hduser@master:/usr/local/hadoop$ jps

18670 Jps

Lanzando jps en el esclavo:

   

hduser@slave:/usr/local/hadoop$ jps

18894 Jps

Como puedes ver, los procesos en el esclavo se han terminado.

10. Ejecutar una tarea MapReduce spark en el nuevo cluster multi nodo

PENDIENTE

enlaces de interés:

http://www.michael-noll.com/tutorials/running-hadoop-on-ubuntu-linux-multi-node-cluster/

ANEXO

Este tutorial va de como pasar de un cluster en modo pseudodistribuido a un cluster distribuido y para ello hemos configurado dos maquinas siguiendo el enlace sobre como configurar un cluster pseudodistribuido. Tambien podriamos haber configurado una sola maquina, una maestra de tipo Name Node y luego usando el comando rsync copiar el directorio /usr/local/hadoop a los otros nodos.

Para ello, lo primero es instalar rsync:

alonso@alonso:/usr/local/hadoop/etc/hadoop$ sudo apt-get install rsync

[sudo] password for alonso:

Leyendo lista de paquetes… Hecho

Creando árbol de dependencias

Leyendo la información de estado… Hecho

rsync ya está en su versión más reciente.

0 actualizados, 0 se instalarán, 0 para eliminar y 0 no actualizados.

Como podeis ver, rsync está instalado y listo para funcionar.

Use rsync for distributing configured Hadoop source among rest of nodes via network.

# In Slave machine

sudo rsync -avxP /usr/local/hadoop/
hduser@slave:/usr/local/hadoop/

Si tuvieramos mas esclavos…

# In HadoopSlave2 machine

sudo rsync -avxP
/usr/local/hadoop/ hduser@HadoopSlave2:/usr/local/hadoop/

Este comando compartirá los ficheros almacenados dentro de la carpeta hadoop a los nodos que hayamos elegidos como esclavos, concretamente en las carpetas de los esclavos /usr/local/hadoop.

De esta manera, no tienes que descargar ni configurar multiples nodos, bueno, hay que configurarlos un poquito. Solo necesitas tener java y rsync en todos los nodos. Debes asegurarte que la variable JAVA_HOME en todos los nodoso sea igual a la que aparece en $HADOOP_HOME/etc/hadoop/hadoop-env.sh.

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s