Cuando finalicemos estas configuraciones y arranquemos los demonios Hadoop, podremos trabajar en un clúster en modo pseudo-distribuído.
Esta instalación es bastante genérica y un compañero ha probado a hacer la misma instalación en Linux y ha funcionado a la perfección.
En el caso de Windows no voy a entrar porque las instalaciones de Hadoop en este entorno son demasiado complejas.
Remarcar también que esta instalación se ha hecho a medida para mi portátil personal, con sus limitaciones hardware. En ningún caso se pretende tener una configuración para un servidor u otro
entorno de producción.
Prerequisitos:
- Java 1.6 instalado (java -version)
Lo primero es descargar Hadoop desde su web: http://hadoop.apache.org.
En este momento la última versión estable es la 1.0.4, aquí tenéis el enlace a las releases:
http://hadoop.apache.org/releases.html
De toda la lista que aparece, descargo hadoop-1.0.4.tar.gz, este paquete contiene
tanto los fuentes como los binarios.
Hay que elegir una ruta para la instalación, en este caso va a ser /usr/local/hadoop.
Como mi usuario no está en modo administrador, no puedo crear las carpetas necesarias a través del finder, por eso abro un terminal y paso a modo
administrador:
sudo su -
este comando pedirá la contraseña de tu usuario (en mi caso, elena)
Nos posicionamos en el directorio donde queremos crear el directorio, y lo creamos:
cd /usr/local
mkdir hadoop
Y ahora le damos a la carpeta hadoop permisos al usuario (en mi caso elena):
chown elena hadoop
Salimos del modo Administrador y volvemos como usuario normal (elena) a través del comando
exit
Ahora ya podemos hacer modificaciones en el directorio a través del Finder.
Copiamos el fichero descargado hadoop-1.0.4.tar.gz en la carpeta
hadoop recién creada.
Otra vez a través de línea de comandos entramos en la carpeta hadoop y descomprimimos el fichero (también se puede hacer a través del Finder haciendo doble click sobre el fichero):
cd /usr/local/hadoop
tar xvfz hadoop-1.0.4.tar.gz
Ahora vamos a proceder a las diferentes configuraciones para hacer funcionar Hadoop, va a haber que modificar los ficheros:
Así que de nuevo a través del Finder accedemos a la carpeta /usr/local/hadoop/hadoo-1.0.4/conf, y antes de empezar a modificar estos 4 ficheros, creamos una copia de seguridad por precaución, llamándolos, por ejmplo: core-site.xml.orig, hdfs-site.xml.orig, mapred-site.xml.orig y hadoo-env.sh.orig
- core-site.xml
- hdfs-site.xml
- mapred-site.xml
- hadoop-env.sh
Así que de nuevo a través del Finder accedemos a la carpeta /usr/local/hadoop/hadoo-1.0.4/conf, y antes de empezar a modificar estos 4 ficheros, creamos una copia de seguridad por precaución, llamándolos, por ejmplo: core-site.xml.orig, hdfs-site.xml.orig, mapred-site.xml.orig y hadoo-env.sh.orig
A continuación detallamos el contenido de dichos ficheros. Para cada propiedad de Hadoop, comentaré qué describe el valor asociado.
core-site.xml
<configuration>
<property>
<!-- Indicamos la URL donde se va a lanzar el servicio hdfs (namenode) -->
<name>fs.default.name</name>
<value>hdfs://localhost:8020</value>
</property>
</configuration>
<property>
<!-- Indicamos la URL donde se va a lanzar el servicio hdfs (namenode) -->
<name>fs.default.name</name>
<value>hdfs://localhost:8020</value>
</property>
</configuration>
hdfs-site.xml
<configuration>
<property>
<!-- Como se trata de un clúster pseudodistribuído el factor de replicación de hdfs es 1 (por defecto si no se indica sería 3) -->
<name>dfs.replication</name>
<value>1</value>
</property>
<property>
<!-- Deshabilitamos la seguridad en hdfs -->
<name>dfs.permissions</name>
<value>false</value>
</property>
<property>
<!-- Indicamos el directorio donde se almacenarán los metadatos de hdfs (namenode). En esta configuración hemos localizado todos los datos que se generan en hadoop bajo una misma carpeta /data -->
<name>dfs.name.dir</name>
<value>/usr/local/hadoop/hadoop-1.0.4/data/dfs/nn</value>
</property>
<property>
<!-- Indicamos el directorio bajo el cual se almacenarán los bloques de datos hdfs (datanode) -->
<name>dfs.data.dir</name>
<value>/usr/local/hadoop/hadoop-1.0.4/data/dfs/dn</value>
</property>
<property>
<!-- Este parámetro permite salir más rápido del safemode. Indica el número de segundos que espera el namenode cuando haya detectado la localización de los bloques de los datanodes -->
<name>dfs.safemode.extension</name>
<value>0</value>
</property>
<property>
<!-- Configuramos el tamaño de bloque en hdfs (estándar 128MB), como no pretendo hacer pruebas con demasiados datos, lo he configurado a 16MB -->
<name>dfs.block.size</name>
<value>16777216</value>
</property>
</configuration>
mapred-site.xml
<configuration>
<property>
<!-- Indicamos la URL donde se va a lanzar el demonio del jobtracker -->
<name>mapred.job.tracker</name>
<value>localhost:8021</value>
</property>
<property>
<!-- Configura el tamaño del HEAP de las tareas map o reduce. Por defecto es 200, pero reducimos a 100 por limitación de RAM en mi portátil -->
<name>mapred.child.java.opts</name>
<value>-Xmx100m</value>
</property>
<property>
<!-- Directorio donde se almacenan datos temporales de los job mapreduce -->
<name>mapred.local.dir</name>
<value>/usr/local/hadoop/hadoop-1.0.4/data/mapred/local</value>
</property>
<property>
<!-- Define el número mínimo de tareas map a ejecutar para cualquier job -->
<name>mapred.map.tasks</name>
<value>1</value>
</property>
<property>
<!-- Define el número máximo de tareas map que se pueden ejecutar al mismo tiempo -->
<name>mapred.tasktracker.map.tasks.maximum</name>
<value>2</value>
</property>
<property>
<!-- Define el número máximo de tareas reduce que se pueden ejecutar al mismo tiempo. Como suele haber menos reduce que map, lo bajo a 1 (por defecto es 2) -->
<name>mapred.tasktracker.reduce.tasks.maximum</name>
<value>1</value>
</property>
<property>
<!-- Número de jobs ejecutados que permanecen en la memoria del jobtracker. Mejor un número pequeño para no despilfarrar memoria -->
<name>mapred.job.tracker.retiredjobs.cache.size</name>
<value>15</value>
</property>
<property>
<!-- Tamaño en MegaBytes del buffer en las tareas map o reduce donde se almacenan los datos intermedios -->
<name>io.sort.mb</name>
<value>25</value>
</property>
<property>
<!-- Número de veces que se replican los ficheros mapreduce en el distributed cache -->
<name>mapred.submit.replication</name>
<value>1</value>
</property>
</configuration>
<property>
<!-- Indicamos la URL donde se va a lanzar el demonio del jobtracker -->
<name>mapred.job.tracker</name>
<value>localhost:8021</value>
</property>
<property>
<!-- Configura el tamaño del HEAP de las tareas map o reduce. Por defecto es 200, pero reducimos a 100 por limitación de RAM en mi portátil -->
<name>mapred.child.java.opts</name>
<value>-Xmx100m</value>
</property>
<property>
<!-- Directorio donde se almacenan datos temporales de los job mapreduce -->
<name>mapred.local.dir</name>
<value>/usr/local/hadoop/hadoop-1.0.4/data/mapred/local</value>
</property>
<property>
<!-- Define el número mínimo de tareas map a ejecutar para cualquier job -->
<name>mapred.map.tasks</name>
<value>1</value>
</property>
<property>
<!-- Define el número máximo de tareas map que se pueden ejecutar al mismo tiempo -->
<name>mapred.tasktracker.map.tasks.maximum</name>
<value>2</value>
</property>
<property>
<!-- Define el número máximo de tareas reduce que se pueden ejecutar al mismo tiempo. Como suele haber menos reduce que map, lo bajo a 1 (por defecto es 2) -->
<name>mapred.tasktracker.reduce.tasks.maximum</name>
<value>1</value>
</property>
<property>
<!-- Número de jobs ejecutados que permanecen en la memoria del jobtracker. Mejor un número pequeño para no despilfarrar memoria -->
<name>mapred.job.tracker.retiredjobs.cache.size</name>
<value>15</value>
</property>
<property>
<!-- Tamaño en MegaBytes del buffer en las tareas map o reduce donde se almacenan los datos intermedios -->
<name>io.sort.mb</name>
<value>25</value>
</property>
<property>
<!-- Número de veces que se replican los ficheros mapreduce en el distributed cache -->
<name>mapred.submit.replication</name>
<value>1</value>
</property>
</configuration>
hadoop-env.sh
Descomentamos las líneas JAVA_HOME y
HADOOP_HEAPSIZE y deberán quedar de la forma siguiente:
export
JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Home
export HADOOP_HEAPSIZE=128
Una vez modificados los ficheros, pasamos a formatear el HDFS:
Creamos un directorio para guardar los logs en la carpeta raíz de hadoop, luego nos posicionamos en la carpeta bin y ejecutamos el comando format:
cd /usr/local/hadoop/hadoop-1.0.4/
mkdir -p logs data/dfs/nn
data/dfs/dn data/mapred/localcd /usr/local/hadoop/hadoop-1.0.4/bin
./hadoop namenode -format
Este es el resultado que debemos obtener:
elena:bin elena$ ./hadoop namenode
-format
13/02/24 13:08:21 INFO
namenode.NameNode: STARTUP_MSG:
/************************************************************
STARTUP_MSG: Starting NameNode
STARTUP_MSG: host =
elena.local/192.168.1.129
STARTUP_MSG: args = [-format]
STARTUP_MSG: version = 1.0.4
STARTUP_MSG: build =
https://svn.apache.org/repos/asf/hadoop/common/branches/branch-1.0 -r
1393290; compiled by 'hortonfo' on Wed Oct 3 05:13:58 UTC 2012
************************************************************/
Re-format filesystem in
/usr/local/hadoop/hadoop-1.0.4/data/dfs/nn ? (Y or N) Y
13/02/24 13:08:28 INFO util.GSet: VM
type = 64-bit
13/02/24 13:08:28 INFO util.GSet: 2%
max memory = 2.51875 MB
13/02/24 13:08:28 INFO util.GSet:
capacity = 2^18 = 262144 entries
13/02/24 13:08:28 INFO util.GSet:
recommended=262144, actual=262144
13/02/24 13:08:29 INFO
namenode.FSNamesystem: fsOwner=elena
13/02/24 13:08:29 INFO
namenode.FSNamesystem: supergroup=supergroup
13/02/24 13:08:29 INFO
namenode.FSNamesystem: isPermissionEnabled=false
13/02/24 13:08:29 INFO
namenode.FSNamesystem: dfs.block.invalidate.limit=100
13/02/24 13:08:29 INFO
namenode.FSNamesystem: isAccessTokenEnabled=false
accessKeyUpdateInterval=0 min(s), accessTokenLifetime=0 min(s)
13/02/24 13:08:29 INFO
namenode.NameNode: Caching file names occuring more than 10 times
13/02/24 13:08:29 INFO common.Storage:
Image file of size 111 saved in 0 seconds.
13/02/24 13:08:29 INFO common.Storage:
Storage directory /usr/local/hadoop/hadoop-1.0.4/data/dfs/nn has been
successfully formatted.
13/02/24 13:08:29 INFO
namenode.NameNode: SHUTDOWN_MSG:
/************************************************************
SHUTDOWN_MSG: Shutting down NameNode at
elena.local/192.168.1.129
************************************************************/
En la carpeta bin, vamos a editar el fichero start-dfs.sh así que también creamos una copia de seguridad:
cp start-dfs.sh start-dfs.sh.orig
Lo que hay que modificar, es quitar las letras "s" finales de donde pone hadoop-daemons.sh al final del fichero.
El fichero origen contiene:
El fichero origen contiene:
# note: datanodes will log connection
errors until namenode starts
"$bin"/hadoop-daemon.sh
--config $HADOOP_CONF_DIR start namenode $nameStartOpt
"$bin"/hadoop-daemons.sh
--config $HADOOP_CONF_DIR start datanode $dataStartOpt
"$bin"/hadoop-daemons.sh
--config $HADOOP_CONF_DIR --hosts masters start secondarynamenode
Y lo modificamos para que sea (es para ejecutar directamente los comandos de arranque Hadoop sin establecer una conexión ssh):
# note: datanodes will log connection
errors until namenode starts
"$bin"/hadoop-daemon.sh
--config $HADOOP_CONF_DIR start namenode $nameStartOpt
"$bin"/hadoop-daemon.sh
--config $HADOOP_CONF_DIR start datanode $dataStartOpt
"$bin"/hadoop-daemon.sh
--config $HADOOP_CONF_DIR --hosts masters start secondarynamenode
Sucede lo mismo en los ficheros start-mapred.sh, stop-dfs.sh y stop-mapred.sh, así que creamos las copias de seguridad y los editamos:
start-mapred.sh
cp start-mapred.sh start-mapred.sh.orig
start-mapred.sh
cp start-mapred.sh start-mapred.sh.orig
Datos antes:
# start jobtracker first to minimize connection errors at startup
"$bin"/hadoops-daemon.sh --config $HADOOP_CONF_DIR start jobtracker
"$bin"/hadoops-daemons.sh --config $HADOOP_CONF_DIR start tasktracker
Datos después:
# start jobtracker first to minimize connection errors at startup
"$bin"/hadoop-daemon.sh --config $HADOOP_CONF_DIR start jobtracker
"$bin"/hadoop-daemon.sh --config $HADOOP_CONF_DIR start tasktracker
stop-dfs.sh
cp stop-dfs.sh stop-dfs.sh.orig
Datos antes:
"$bin"/hadoop-daemon.sh --config $HADOOP_CONF_DIR stop namenode
"$bin"/hadoop-daemons.sh --config $HADOOP_CONF_DIR stop datanode
"$bin"/hadoop-daemons.sh --config $HADOOP_CONF_DIR --hosts masters stop secondarynamenode
Datos después:
"$bin"/hadoop-daemon.sh --config $HADOOP_CONF_DIR stop namenode
"$bin"/hadoop-daemon.sh --config $HADOOP_CONF_DIR stop datanode
"$bin"/hadoop-daemon.sh --config $HADOOP_CONF_DIR --hosts masters stop secondarynamenode
stop-mapred.sh
cp stop-mapred.sh stop-mapred.sh.orig
Datos antes:
"$bin"/hadoop-daemon.sh --config $HADOOP_CONF_DIR stop jobtracker
"$bin"/hadoop-daemons.sh --config $HADOOP_CONF_DIR stop tasktracker
Datos después:
"$bin"/hadoop-daemon.sh --config $HADOOP_CONF_DIR stop jobtracker
"$bin"/hadoop-daemon.sh --config $HADOOP_CONF_DIR stop tasktracker
Una vez hechas todas las configuraciones vamos a ver si todo funciona correctamente.
Nos posicionamos en la carpeta raíz del hadoop:
cd /usr/local/hadoop/hadoop-1.0.4/
Y arrancamos todo con el comando:
bin/start-all.sh
Este comando arranca los 3 demonios de HDFS y los 2 de MapReduce.
Para comprobar que todo ha funcionado correctamente,
podemos ver los ficheros de logs de cada demonio en la carpeta
logs.
También podemos usar un navegador web
y mirar las web UI de:
- MapReduce en http://localhost:50030/jobtracker.jsp
A tener en cuenta que en los 2 casos tenemos que ver 1 nodo
activo
Para detener todo el cluster, se hace con el comando
bin/stop-all.sh
Hay que tener en cuenta que no hemos puesto el comando hadoop en el PATH del sistema, así que para ejecutarlo hay que posicionarse en la carpeta bin y ponerlo de la forma:
./hadoop fs
bin/stop-all.sh
Hay que tener en cuenta que no hemos puesto el comando hadoop en el PATH del sistema, así que para ejecutarlo hay que posicionarse en la carpeta bin y ponerlo de la forma:
./hadoop fs