SafeChildren Banner

Havoc Oracle Solaris Experts

viernes, 31 de julio de 2009

Instalar subversion para compilar Hadoop en Solaris 10

Introducción
En esta nueva entrega, vamos a ver cómo podemos crear un entorno para trabajar con el código fuente de Hadoop, para ello, instalaremos subversion en una zona que aislaremos del resto con el fin de no interferir en las configuraciones de nuestro cluster de hadoop. Puede que te resulte interesante leer el post de como configurar wget, ant y subversion con proxy

Creación de una Zona para la compilación
Vamos a crear una zona como hemos visto en mi anterior post de Gestión básica de Zonas, con una modificación. Los paquetes que vamos a instalar los obtendremos en formato binario desde Sun Freeware y éstos se instalan en /usr/local por lo tanto, vamos a hacer que nuestra zona no comparta el directorio /usr ya que sino, lo montará como sólo lectura y no podremos instalarlos, para ello, eliminaremos la propiedad inherit-pkg-dir con valor /usr
# zonecfg -z hadoop-svn
hadoop-svn: No se ha configurado esa zona
Use 'create' para comenzar a configurar una zona nueva.
zonecfg:hadoop-svn> create
zonecfg:hadoop-svn> remove inherit-pkg-dir dir=/usr
zonecfg:hadoop-svn> set scheduling-class=FSS
zonecfg:hadoop-svn> set autoboot=false
zonecfg:hadoop-svn> set zonepath=/opt/zones/hadoop-svn
zonecfg:hadoop-svn> add net
zonecfg:hadoop-svn: net> set physical=e1000g0
zonecfg:hadoop-svn: net> set address=10.1.1.7/24
zonecfg:hadoop-svn: net> set defrouter=10.1.1.254
zonecfg:hadoop-svn: net> end
zonecfg:hadoop-svn> verify
zonecfg:hadoop-svn> commit
zonecfg:hadoop-svn> exit

# zoneadm -z hadoop-svn install
....
# zoneadm -z hadoop-svn boot
Una vez creada y configurada la zona podemos comenzar con la instalación de los paquetes, para ello, los descargaremos desde SunFreeware

Descargamos los paquetes

$ wget ftp://ftp.sunfreeware.com/pub/freeware/intel/10/libgcc-3.4.6-sol10-x86-local.gz
$ wget ftp://ftp.sunfreeware.com/pub/freeware/intel/10/libgcc-3.4.6-sol10-x86-local.gz
$ wget ftp://ftp.sunfreeware.com/pub/freeware/intel/10/zlib-1.2.3-sol10-x86-local.gz
$ wget ftp://ftp.sunfreeware.com/pub/freeware/intel/10/openldap-2.4.16-sol10-x86-local.gz
$ wget ftp://ftp.sunfreeware.com/pub/freeware/intel/10/libtool-1.5.24-sol10-x86-local.gz
$ wget ftp://ftp.sunfreeware.com/pub/freeware/intel/10/openssl-0.9.8k-sol10-x86-local.gz
$ wget ftp://ftp.sunfreeware.com/pub/freeware/intel/10/sasl-2.1.21-sol10-x86-local.gz
$ wget ftp://ftp.sunfreeware.com/pub/freeware/intel/10/db-4.7.25.NC-sol10-x86-local.gz
$ wget ftp://ftp.sunfreeware.com/pub/freeware/intel/10/libintl-3.4.0-sol10-x86-local.gz
$ wget ftp://ftp.sunfreeware.com/pub/freeware/intel/10/libiconv-1.11-sol10-x86-local.gz
$ wget ftp://ftp.sunfreeware.com/pub/freeware/intel/10/libxml2-2.6.31-sol10-x86-local.gz
$ wget ftp://ftp.sunfreeware.com/pub/freeware/intel/10/expat-2.0.1-sol10-x86-local.gz
$ wget ftp://ftp.sunfreeware.com/pub/freeware/intel/10/swig-1.3.36-sol10-x86-local.gz
$ wget ftp://ftp.sunfreeware.com/pub/freeware/intel/10/apache-2.0.59-sol10-x86-local.gz
$ wget ftp://ftp.sunfreeware.com/pub/freeware/intel/10/apache-2.2.11-sol10-x86-local.gz
$ wget ftp://ftp.sunfreeware.com/pub/freeware/intel/10/neon-0.28.3-sol10-x86-local.gz
$ wget ftp://ftp.sunfreeware.com/pub/freeware/intel/10/subversion-1.6.2-sol10-x86-local.gz
Descomprimimos los paquetes
$ gzip -d *.gz
Instalamos los paquetes
# pkgadd -d libgcc-3.4.6-sol10-x86-local
# pkgadd -d zlib-1.2.3-sol10-x86-local
# pkgadd -d openldap-2.4.16-sol10-x86-local
# pkgadd -d libtool-1.5.24-sol10-x86-local
# pkgadd -d openssl-0.9.8k-sol10-x86-local
# pkgadd -d sasl-2.1.21-sol10-x86-local
# pkgadd -d db-4.7.25.NC-sol10-x86-local
# pkgadd -d libintl-3.4.0-sol10-x86-local
# pkgadd -d libiconv-1.11-sol10-x86-local
# pkgadd -d libxml2-2.6.31-sol10-x86-local
# pkgadd -d expat-2.0.1-sol10-x86-local
# pkgadd -d swig-1.3.36-sol10-x86-local
# pkgadd -d apache-2.2.11-sol10-x86-local
# pkgadd -d neon-0.28.3-sol10-x86-local
# pkgadd -d subversion-1.6.2-sol10-x86-local
Comprobar la Instalación
Debemos incluir el directorio /usr/local/bin en nuestro path, para ello, podemos modificar el profile de la siguiente forma

$ cat >~/.profile<
##########################################################
# Developer Profile
##########################################################

# Common Home
ANT_HOME=/opt/ant
JAVA_HOME=/usr/java
HADOOP_HOME=/opt/hadoop
PATH=$ANT_HOME/bin:$PATH:$HADOOP_HOME/bin:/usr/sfw/bin:/usr/local/bin:/usr/ccs/bin:/usr/ucb

export PATH HADOOP_HOME JAVA_HOME ANT_HOME

# Simple Banner
banner Hadoop_Dev

MAIL=/usr/mail/${LOGNAME:?}

EOF
A continuación, vamos a comprobar que todas las dependencias de svn están correctamente, para ello ejecutaremos el siguiente comando
$ ldd $(which svn)
libsvn_client-1.so.0 => /usr/local/lib/libsvn_client-1.so.0
libsvn_wc-1.so.0 => /usr/local/lib/libsvn_wc-1.so.0
libsvn_ra-1.so.0 => /usr/local/lib/libsvn_ra-1.so.0
libsvn_diff-1.so.0 => /usr/local/lib/libsvn_diff-1.so.0
libsvn_ra_local-1.so.0 => /usr/local/lib/libsvn_ra_local-1.so.0
libsvn_repos-1.so.0 => /usr/local/lib/libsvn_repos-1.so.0
libsvn_fs-1.so.0 => /usr/local/lib/libsvn_fs-1.so.0
libsvn_fs_fs-1.so.0 => /usr/local/lib/libsvn_fs_fs-1.so.0
libsvn_fs_util-1.so.0 => /usr/local/lib/libsvn_fs_util-1.so.0
libsvn_ra_svn-1.so.0 => /usr/local/lib/libsvn_ra_svn-1.so.0
libsvn_ra_neon-1.so.0 => /usr/local/lib/libsvn_ra_neon-1.so.0
libsvn_ra_serf-1.so.0 => /usr/local/lib/libsvn_ra_serf-1.so.0
libserf-0.so.0 => /usr/local/lib/libserf-0.so.0
libm.so.2 => /usr/lib/libm.so.2
libsvn_delta-1.so.0 => /usr/local/lib/libsvn_delta-1.so.0
libsvn_subr-1.so.0 => /usr/local/lib/libsvn_subr-1.so.0
libaprutil-1.so.0 => /usr/local/apache2/lib/libaprutil-1.so.0
libldap-2.4.so.2 => /usr/local/lib/libldap-2.4.so.2
libsasl2.so.2 => /usr/local/lib/libsasl2.so.2
libgss.so.1 => /usr/lib/libgss.so.1
liblber-2.4.so.2 => /usr/local/lib/liblber-2.4.so.2
libresolv.so.2 => /usr/lib/libresolv.so.2
libgen.so.1 => /usr/lib/libgen.so.1
libapr-1.so.0 => /usr/local/apache2/lib/libapr-1.so.0
libuuid.so.1 => /usr/lib/libuuid.so.1
libsendfile.so.1 => /usr/lib/libsendfile.so.1
librt.so.1 => /usr/lib/librt.so.1
libpthread.so.1 => /usr/lib/libpthread.so.1
libneon.so.27 => /usr/local/lib/libneon.so.27
libz.so => /usr/local/lib/libz.so
libssl.so.0.9.8 => /usr/local/ssl/lib/libssl.so.0.9.8
libcrypto.so.0.9.8 => /usr/local/ssl/lib/libcrypto.so.0.9.8
libnsl.so.1 => /usr/lib/libnsl.so.1
libdl.so.1 => /usr/lib/libdl.so.1
libexpat.so.1 => /usr/local/lib/libexpat.so.1
libsocket.so.1 => /usr/lib/libsocket.so.1
libintl.so.8 => /usr/local/lib/libintl.so.8
libiconv.so.2 => /usr/local/lib/libiconv.so.2
libsec.so.1 => /usr/lib/libsec.so.1
libc.so.1 => /usr/lib/libc.so.1
libgcc_s.so.1 => /usr/local/lib/libgcc_s.so.1
libcmd.so.1 => /lib/libcmd.so.1
libaio.so.1 => /lib/libaio.so.1
libmd.so.1 => /lib/libmd.so.1
libmp.so.2 => /lib/libmp.so.2
libscf.so.1 => /lib/libscf.so.1
libavl.so.1 => /lib/libavl.so.1
libdoor.so.1 => /lib/libdoor.so.1
libuutil.so.1 => /lib/libuutil.so.1
Si por algún motivo nos faltase alguna, nos mostraría un mensaje (archivo no encontrado). A continuación se muestra un ejemplo de whoami sin una de su dependencia.
# ldd /usr/local/bin/whoami
libintl.so.8 => (archivo no encontrado)
libc.so.1 => /usr/lib/libc.so.1
libm.so.2 => /lib/libm.so.2
/platform/SUNW,Sun-Fire-280R/lib/libc_psr.so.1

Requisitos Especiales
Para una correcta compilación de hadoop sobre Solaris, tenemos que tener en cuenta algunos requisitos como son el hecho de que hadoop asume que whoami se encuentra en el path, como he comentado en el post anterior, además también asume que md5sum existe y está accesible, por lo tanto, vamos a hacer algunos cambios en nuestra instalación para que todo funcione correctamente.

1.- Instalaremos el paquete md5 desde SunFreeware
$ wget ftp://ftp.sunfreeware.com/pub/freeware/sparc/10/md5-6142000-sol10-intel-local.gz
$ gzip -d md5-6142000-sol10-intel-local.gz
$ su -
password
# pkgadd -d md5-6142000-sol10-intel-local.gz
2.- Crearemos un link desde md5 a md5sum ya que el paquete no lo crea
# cd /usr/local/bin
# ln md5 md5sum
3.- Introduciremos el directorio /usr/ucb en el path del usuario si no lo tenemos hecho ya

4.- Instalaremos la versión 1.7 de Apache ant
# cd /opt
# /usr/sfw/bin/wget http://apache.inetbridge.net/ant/binaries/apache-ant-1.7.1-bin.tar.gz
# /usr/sfw/bin/gtar zxvpf apache-ant-1.7.1-bin.tar.gz
# mv apache-ant-1.7.1 ant
# rm apache-ant-1.7.1-bin.tar.gz

Pondremos las variables de entorno ANT_HOME e introduciremos $ANT_HOME/bin en el path para que lo encuentre (esto está puesto en el profile de ejemplo) y con esto, ya tenemos el entorno preparado para poder hacer un checkout del proyecto Hadoop


CheckOut del Proyecto
Vamos a crear un directorio hadoop-source en el cual haremos el checkout de hadoop, para ello, realizaremos los siguientes pasos
$ mkdir ~/hadoop-source
$ cd ~/hadoop-source
$ svn checkout http://svn.apache.org/repos/asf/hadoop/common/trunk/ hadoop-common-trunk
Con esto ya podemos comenzar a probar el código fuente de hadoop, hacer parches, etc.

Conclusiones
Hemos visto cómo instalar subversion desde SunFreeware utilizando los paquetes en formato binario, además, hemos modificado el profile para incluir el famoso whoami en el path para que hadoop lo encuentre. Además, hemos incluido md5sum ya que también es necesario para la compilación de hadoop

Espero no haberos aburrido con este lago post y en los próximos veremos cómo trabajar con subversion para hacer parches y subirlos al source de hadoop

Referencias

jueves, 30 de julio de 2009

Configurar wget, subversion y ant en Solaris para que use un proxy HTTP

Introducción
Muchas veces nos encontramos con que nuestra salida a Internet se realiza a través de un proxy, y los comandos como wget, curl, no son capaces de salir correctamente. Con este pequeño tip espero resolver esos dolores de cabeza

Establecer variable http_proxy
A diferencia de FreeBSD que es HTTP_PROXY en Solaris para que wget salga a través de proxy (en mi caso squid) es necesario establecerla como http_proxy (en minúsculas), por ejemplo, si nuestro proxy fuese proxy-01.test.com y su puerto 3128
$ export http_proxy="http://proxy-01.test.com:3128/
Como muchas veces comparto el profile entre FreeBSD y Solaris, lo que al final hago es simplemente duplicar la entrada, una en minúsculas y otra en MAYÚSCULAS, .... es más rápido.

Sin embargo ant no hace uso de esta variable, ya que es una aplicación java y por lo tanto, es necesario utilizar las propiedades de http.proxyHost y http.proxyPort como opciones para ante en la variable de entorno ANT_OPTS. Si continuamos con el ejemplo anterior, para ant será de la siguiente forma
$ export ANT_OPTS="-Dhttp.proxyHost=proxy-01.test.com -Dhttp.proxyPort=3128"
Al igual que sucede con http_proxy, podemos incluir esta opción en el profile del usuario

Configuración subversion
Para subversion, deberemos editar el archivo servers que se encuentra en $HOME/.subversiony descomentar las entradas http-proxy-host y http-proxy-port de la sección global, continuando con el ejemplo
$ vi ~/.subversion/servers
[global]
http-proxy-host = proxy-01.test.com
http-proxy-port = 3128

:wq

Referencias

miércoles, 29 de julio de 2009

Problema de Seguridad HDFS y Solaris 10 con whoami

Introducción
Como ya he comentado en los anteriores posts Gestión de permisos en HDFS y El misterio de DrWho en Solaris 10 así que no voy a darle más vueltas y vamos a verlo con un ejemplo

El Problema
Básicamente el problema se encuentra en cómo se obtiene el usuario que está ejecutando el proceso. En la mayoría de las situaciones whoami está en el path, sin embargo, si no lo encuentra se asigna el usuario DrWho y iSuper a true, por lo tanto, ya no se evalúan los permisos en el sistema HDFS.

He creado un pequeño programa que evalúa las dos versiones hadoop-0.20-core y la que he creado yo hadoop-0.20.1-dev-core que tiene los parches para evitarlo.


A continuación os pongo el comentario que he hecho en el bug de Hadoop traducido al castellano para ver cómo explotar (y corregir) el fallo actual.

Pasos para reproducir el error

1.- Crear un nuevo directorio en el sistema HDFS y asignar el usuario y grupo como hadoop con permisos 700 para que sólo hadoop pueda escribir en él
$ uname -a
SunOS sol10-enigma 5.10 Generic_139556-08 i86pc i386 i86pc
$ hadoop fs -mkdir testdir
$ hadoop fs -chown -R hadoop:hadoop testdir
$ hadoop fs -chmod 700 testdir
$ hadoop fs -lsr
drwx------ - hadoop hadoop 0 2009-07-29 18:43 /user/hadoop/testdir

2.- Desde otro Sun ejecutando Solaris lanzamos la aplicación TestHadoop. Este Solaris no tiene whoami en el path
$ uname -a
SunOS hedwig 5.10 Generic_127127-11 sun4u sparc SUNW,Sun-Fire-V490
$ id
uid=2011(postgres) gid=90(postgres)
$ /usr/xpg4/bin/id -Gn
postgres dba
$ /usr/xpg4/bin/id -un
postgres
$ which whoami
no whoami in /opt/apache-ant-1.7.1/bin /u01/app/postgres/8.4/db/bin/64 /u01/app/postgres/8.4/db/bin /usr/bin /usr/sfw/bin /usr/local/bin
3.- Ejecutamos la aplicación de Test
$ cd TestHadoop/
$ ant
Buildfile: build.xml

init:
[mkdir] Created dir: /export/home/postgres/TestHadoop/build
[mkdir] Created dir: /export/home/postgres/TestHadoop/javadoc
[mkdir] Created dir: /export/home/postgres/TestHadoop/build.test

compile:
[javac] Compiling 1 source file to /export/home/postgres/TestHadoop/build
[javac] /export/home/postgres/TestHadoop/src/com/sfchildren/sbcore/backup/Main.java:89: warning: [deprecation] USER_NAME_COMMAND in org.apache.hadoop.util.Shell has been deprecated
[javac] String[] result = executeShellCommand( new String[]{Shell.USER_NAME_COMMAND});
[javac] ^
[javac] 1 warning

dist:
[mkdir] Created dir: /export/home/postgres/TestHadoop/dist
[jar] Building jar: /export/home/postgres/TestHadoop/dist/hadoop-example.jar

run:
[echo]
[echo] Test Hadoop Shell.USER_NAME without "whois" at path
[echo]
[echo] 1.- Test with original Hadoop-0.20.0-core.jar
[echo] 2.- Test with *NEW* Hadoop-0.20.1-core-dev.jar
[echo]
[echo] TestCase
[echo] - Create 3 directories "uno" "dos" "tres" at "/user/hadoop/testdir"
[echo] the "/user/hadoop/testdir" has the been created as bellow
[echo]
[echo] $ hadoop fs -mkdir testdir
[echo] $ hadoop fs -chown -R hadoop:hadoop testdir
[echo] $ hadoop fs -chmod 700 testdir
[echo] $ hadoop fs -lsr
[echo] drwx------ - hadoop hadoop 0 2009-07-29 18:24 /user/hadoop/testdir
[echo]
[echo] - Create 1 file onto directory
[echo]
[echo]
[echo]
[echo]
[echo]
[echo] Running with hadoop-0.20.0-core.jar
[echo]
[echo]
[java] Get UserName from System.getProperty: postgres
[java] Get UserName from Shell.USER_NAME_COMMAND Fail, Default User DrWho assigned
[java] 29-jul-2009 19:16:59 com.sfchildren.sbcore.backup.Main createTmpFile
[java] INFO: File testfile Created with Size: 772889 bytes Time: 1 seconds
[java] 29-jul-2009 19:17:04 com.sfchildren.sbcore.backup.Main createTmpFile
[java] INFO: File testfile Created with Size: 3592563 bytes Time: 4 seconds
[java] 29-jul-2009 19:17:20 com.sfchildren.sbcore.backup.Main createTmpFile
[java] INFO: File testfile Created with Size: 12417028 bytes Time: 16 seconds
[echo]
[echo]
[echo] Running With New Hadoop-0.20.1-dev-core
[echo]
[echo]
[java] Get UserName from System.getProperty: postgres
[java] Get UserName from Shell.USER_NAME_COMMAND Fail, Default User DrWho assigned
[java] Get UserName from Shell.getUSER_NAME_COMMAND() postgres
[java] Exception org.apache.hadoop.security.AccessControlException: Permission denied: user=postgres, access=EXECUTE, inode="testdir":hadoop:hadoop:rwx------

BUILD SUCCESSFUL
Total time: 27 seconds
Como se puede observar, cuando la aplicación se ejecuta con hadoop-0.20-core.jar el usuario del sistema (postgres) se ignora, ya que se produce una excepción y se asigna DrWho y puede crear los directorios y archivos sin problemas. Sin embargo, cuando se ejecuta con la versión modificada hadoop-0.20.1-dev-core.jar si que se identifica el usuario correctamente como postgres y se produce una excepción de acceso denegado

4.- Comprobar cómo ha creado los archivos y directorios con DrWho
$ hadoop fs -lsr
drwx------ - hadoop hadoop 0 2009-07-29 18:50 /user/hadoop/testdir
drwxr-xr-x - DrWho hadoop 0 2009-07-29 18:50 /user/hadoop/testdir/dos
-rw-r--r-- 3 DrWho hadoop 3592563 2009-07-29 18:50 /user/hadoop/testdir/dos/testfile
drwxr-xr-x - DrWho hadoop 0 2009-07-29 18:50 /user/hadoop/testdir/tres
-rw-r--r-- 3 DrWho hadoop 12417028 2009-07-29 18:50 /user/hadoop/testdir/tres/testfile
drwxr-xr-x - DrWho hadoop 0 2009-07-29 18:50 /user/hadoop/testdir/uno
-rw-r--r-- 3 DrWho hadoop 772889 2009-07-29 18:50 /user/hadoop/testdir/uno/testfile
5.- La configuración del sistema HDFS incluye un parámetro para que el SuperGroup sea hadoop de la siguiente forma
<property>
<name>dfs.permissions.supergroup</name>
<value>hadoop</value>
<final>true</final>
</property>
Sin embargo, el usuario que ha lanzado la aplicación de test es postgres con grupos postgres y dba en ningún caso hadoop

Falsear el comando "whoami"
El otro problema es falsear el comando whoami para hacer que hadoop crea que somos otro usuario, para ello, crearemos nuestro whoami y lo insertaremos en el path en primera posición

1.- En el cluster de Hadoop, limpiamos y volvemos a crear el directorio testdir
$ hadoop fs -rmr testdir
Deleted hdfs://namenode.hadoop.test.com:54310/user/hadoop/testdir
$ hadoop fs -mkdir testdir
$ hadoop fs -chown -R hadoop:hadoop testdir
$ hadoop fs -chmod 700 testdir
$ hadoop fs -lsr
drwx------ - hadoop hadoop 0 2009-07-29 19:02 /user/hadoop/testdir
2.- En la segunda máquina, vamos a crear un fake de whoami
$ uname -a
SunOS hedwig 5.10 Generic_127127-11 sun4u sparc SUNW,Sun-Fire-V490
$ which whoami
no whoami in /opt/apache-ant-1.7.1/bin /u01/app/postgres/8.4/db/bin/64 /u01/app/postgres/8.4/db/bin /usr/bin /usr/sfw/bin /usr/local/bin
$ echo "echo hadoop" > ~/whoami
$ chmod +x ~/whoami
$ export PATH=~:$PATH
$ which whoami
/export/home/postgres/whoami
$ whoami
hadoop
$ id
uid=2011(postgres) gid=90(postgres)
3.- Ejecutamos la aplicación de prueba
$ cd TestHadoop/
$ ant
Buildfile: build.xml

init:

compile:

dist:

run:
[echo]
[echo] Test Hadoop Shell.USER_NAME without "whois" at path
[echo]
[echo] 1.- Test with original Hadoop-0.20.0-core.jar
[echo] 2.- Test with *NEW* Hadoop-0.20.1-core-dev.jar
[echo]
[echo] TestCase
[echo] - Create 3 directories "uno" "dos" "tres" at "/user/hadoop/testdir"
[echo] the "/user/hadoop/testdir" has the been created as bellow
[echo]
[echo] $ hadoop fs -mkdir testdir
[echo] $ hadoop fs -chown -R hadoop:hadoop testdir
[echo] $ hadoop fs -chmod 700 testdir
[echo] $ hadoop fs -lsr
[echo] drwx------ - hadoop hadoop 0 2009-07-29 18:24 /user/hadoop/testdir
[echo]
[echo] - Create 1 file onto directory
[echo]
[echo]
[echo]
[echo]
[echo]
[echo] Running with hadoop-0.20.0-core.jar
[echo]
[echo]
[java] Get UserName from System.getProperty: postgres
[java] Get UserName from Shell.USER_NAME_COMMAND hadoop
[java] 29-jul-2009 19:32:45 com.sfchildren.sbcore.backup.Main createTmpFile
[java] INFO: File testfile Created with Size: 4421872 bytes Time: 4 seconds
[java] 29-jul-2009 19:32:53 com.sfchildren.sbcore.backup.Main createTmpFile
[java] INFO: File testfile Created with Size: 7235384 bytes Time: 8 seconds
[java] 29-jul-2009 19:33:02 com.sfchildren.sbcore.backup.Main createTmpFile
[java] INFO: File testfile Created with Size: 5693610 bytes Time: 8 seconds
[echo]
[echo]
[echo] Running With New Hadoop-0.20.1-dev-core
[echo]
[echo]
[java] Get UserName from System.getProperty: postgres
[java] Get UserName from Shell.USER_NAME_COMMAND hadoop
[java] Get UserName from Shell.getUSER_NAME_COMMAND() postgres
[java] Exception org.apache.hadoop.security.AccessControlException: Permission denied: user=postgres, access=EXECUTE, inode="testdir":hadoop:hadoop:rwx------

BUILD SUCCESSFUL
Total time: 24 seconds
Como podéis ver, para hadoop el usuario que ha ejecutado el comando es hadoop si utilizamos la versión hadoop-0.20-core.jar, sin embargo, si utilizamos la versión el sistema hadoop-0.20.1-dev-core.jar reconoce correctamente el usuario.

4.- Comprobamos que ha creado en el sistema de ficheros
$ hadoop fs -lsr
drwx------ - hadoop hadoop 0 2009-07-29 19:06 /user/hadoop/testdir
drwxr-xr-x - hadoop hadoop 0 2009-07-29 19:06 /user/hadoop/testdir/dos
-rw-r--r-- 3 hadoop hadoop 7235384 2009-07-29 19:06 /user/hadoop/testdir/dos/testfile
drwxr-xr-x - hadoop hadoop 0 2009-07-29 19:06 /user/hadoop/testdir/tres
-rw-r--r-- 3 hadoop hadoop 5693610 2009-07-29 19:06 /user/hadoop/testdir/tres/testfile
drwxr-xr-x - hadoop hadoop 0 2009-07-29 19:06 /user/hadoop/testdir/uno
-rw-r--r-- 3 hadoop hadoop 4421872 2009-07-29 19:06 /user/hadoop/testdir/uno/testfile
Conclusiones
Queda claro que con el simple hecho de incluir whoami en el path no estamos exentos de que nos puedan sabotear la seguridad impuesta en nuestro sistema HDFS, aunque, mejor es incluir el comando whoami que nada, por lo menos hasta que se resuelva la forma de obtener el usuario que ejecuta el proceso.

Espero no haberos aburrido mucho, con este largo post

Referencias
Nota: para aplicar el parche al archivo Shell.java, haremos
$ patch Shell.java <>
Parece un diff normal.
terminado

martes, 28 de julio de 2009

El misterio de DrWho en Solaris 10

Introducción
Como ya comentaba en mi post anterior he descubierto un problema en la implementación de Hadoop para Solaris 10 que hacía que no se obtuviese correctamente el usuario del sistema operativo

He creado un bug en Hadoop 507 y espero tener un parche disponible para solucionar el problema.


ACTUALIZACIÓN:
Todo este tema de whoami en Solaris tiene más problemas de Seguridad que de configuración, es cierto que con un sencillo cambio en el PATH todo está solucionado, sin embargo creo que es un gran fallo de diseño (en cuanto a seguridad se refiere) el hecho de que se llame a "whoami" sin path absoluto. He creado una entrada donde explico con detalle el problema y los cambios que he propuesto a Hadoop para solucionarlo.


Referencias

lunes, 27 de julio de 2009

Introducción a los permisos en HDFS - Problema con DrWho en Solaris 10

Introducción
En la primera parte de la introducción a los permisos en HDFS concluí que era más fácil utilizar IPFilter. La verdad es que esta conclusión la saqué después de mucho tiempo con la configuración a vueltas y un pequeño código que creaba unos archivos y luego los borraba.

El problema de DrWho
Después de un buen rato investigando el código de Hadoop, he encontrado el problema :D y creo que lo he solucionado.

El problema era muy sencillo, cuando ejecutaba un código muy simple que creaba n archivos desde Solaris, siempre me ponía como usuario "DrWho" y como group "" así que por muchos permisos que yo asignaba el código se los saltaba ya que DrWho es supergroup y por lo tanto no evalua los permisos.

Bien, el problema viene por cómo se mira quién es el usuario que está definido en la clase Shell.USER_NAME_COMMAND ($HADOOP_HOME/src/core/org/apache/hadoop/security/) que hace la llamada a "whoami", este comando no existe en Solaris así, sino "who am i", sin embargo, este comando no puede ser llamado si no estás atacado a la consola, así que estoy evaluando las siguientes opciones
  • Modicar el path para incluir los binarios compatibles con BSD que se encuentran en /usr/ucb donde está whoami (Es necesario tener instalado el paquete SUNWscpu)
  • Instalar whoami desde Sunfreeware.
  • Crear un WhoAmI propio utilizando el comando id de Solaris. Esta solución que es la más complicada, es como no la que he seleccionado, ya que creo es más interesante.
Solución al problema
# echo "/usr/xpg4/bin/id -un" > /usr/bin/whoami
# chmod +x /usr/bin/whoami
Con este sencillo cambio, el sistema ya reconoce quien soy y por lo tanto evalúa los permisos correctamente. Por defecto los comando compatibles con BSD se encuentran en /usr/xpg4/, podíamos haber hecho un simple link para solucionar el problema, pero creo que es más correcto hacer que Hadoop se encargue de saber a que id llamar en función del OS.

A continuación os muestro una ejecución sin el parche y otra con el parche
[java] hdfs://namenode.hadoop.test.com:54310/
[java] hdfs://namenode.hadoop.test.com:54311/
[java] Get UserName: hadoop
[java] Creating PATH 1248715418585
[java] Creating FILE 1248715418622
[java] Creating PATH 1248715421131
[java] 27-jul-2009 19:23:41 com.sfchildren.sbcore.backup.Main createTmpFile
[java] INFO: File testfile Created with Size: 1717833
[java] Creating FILE 1248715421148
[java] Creating PATH 1248715432033
[java] 27-jul-2009 19:23:52 com.sfchildren.sbcore.backup.Main createTmpFile
[java] INFO: File testfile Created with Size: 8968960
[java] Creating FILE 1248715432055
....

El log del NameNode
$ tail -f $HADOOP_HOME/log/hadoop--namenode*
2009-07-27 19:19:00,082 INFO org.apache.hadoop.hdfs.server.namenode.FSNamesystem.audit: ugi=DrWho,postgres,dba ip=/10.80.1.82 cmd=create src=/user/DrWho/testdir/tres/testfile dst=null perm=DrWho:supergroup:rw-r--r--
Y la estructura HDFS que tengo sólo permite la escritura al usuario hadoop de la siguiente forma
$ hadoop fs -lsr /user/DrWho
drwxr-xr-x - hadoop hadoop 0 2009-07-27 19:22 /user/DrWho/testdir
Sin embargo, después de ejecutar el comando (sin el parche) no sólo no falla, sino que se salta la seguridad por completo, aquí está el resultado
$ hadoop fs -lsr /user/DrWho
drwxr-xr-x - hadoop hadoop 0 2009-07-27 19:25 /user/DrWho/testdir
drwxr-xr-x - DrWho hadoop 0 2009-07-27 19:25 /user/DrWho/testdir/cuatro
-rw-r--r-- 3 DrWho hadoop 0 2009-07-27 19:25 /user/DrWho/testdir/cuatro/testfile
drwxr-xr-x - DrWho hadoop 0 2009-07-27 19:24 /user/DrWho/testdir/dos
-rw-r--r-- 3 DrWho hadoop 7731334 2009-07-27 19:24 /user/DrWho/testdir/dos/testfile
drwxr-xr-x - DrWho hadoop 0 2009-07-27 19:25 /user/DrWho/testdir/tres
-rw-r--r-- 3 DrWho hadoop 9384206 2009-07-27 19:25 /user/DrWho/testdir/tres/testfile
drwxr-xr-x - DrWho hadoop 0 2009-07-27 19:24 /user/DrWho/testdir/uno
-rw-r--r-- 3 DrWho hadoop 5752383 2009-07-27 19:24 /user/DrWho/testdir/uno/testfile


Sin embargo, si activo el parche el resultado es muy diferente
[java] hdfs://namenode.hadoop.test.com:54310/
[java] hdfs://namenode.hadoop.test.com:54311/
[java] Get UserName: hadoop
[java] Result 0 Value: postgres
[java] Creating PATH 1248715876078
[java] Creating FILE 1248715876149
[java] 27-jul-2009 19:31:16 com.sfchildren.sbcore.backup.Main main
[java] GRAVE: null
[java] org.apache.hadoop.security.AccessControlException: org.apache.hadoop.security.AccessControlException: Permission denied: user=postgres, access=WRITE, inode="testfile":DrWho:hadoop:rw-r--r--
[java] at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
[java] at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
[java] at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
[java] at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
[java] at org.apache.hadoop.ipc.RemoteException.instantiateException(RemoteException.java:96)
[java] at org.apache.hadoop.ipc.RemoteException.unwrapRemoteException(RemoteException.java:58)
[java] at org.apache.hadoop.hdfs.DFSClient$DFSOutputStream.(DFSClient.java:2647)
[java] at org.apache.hadoop.hdfs.DFSClient.create(DFSClient.java:463)
[java] at org.apache.hadoop.hdfs.DistributedFileSystem.create(DistributedFileSystem.java:195)
[java] at org.apache.hadoop.fs.FileSystem.create(FileSystem.java:479)
[java] at org.apache.hadoop.fs.FileSystem.create(FileSystem.java:460)
[java] at org.apache.hadoop.fs.FileSystem.create(FileSystem.java:367)
[java] at org.apache.hadoop.fs.FileSystem.create(FileSystem.java:359)
[java] at com.sfchildren.sbcore.backup.Main.createTmpFile(Main.java:171)
[java] at com.sfchildren.sbcore.backup.Main.main(Main.java:100)
[java] Caused by: org.apache.hadoop.ipc.RemoteException: org.apache.hadoop.security.AccessControlException: Permission denied: user=postgres, access=WRITE, inode="testfile":DrWho:hadoop:rw-r--r--
[java] at org.apache.hadoop.hdfs.server.namenode.PermissionChecker.check(PermissionChecker.java:176)
[java] at org.apache.hadoop.hdfs.server.namenode.PermissionChecker.checkPermission(PermissionChecker.java:111)
[java] at org.apache.hadoop.hdfs.server.namenode.FSNamesystem.checkPermission(FSNamesystem.java:4486)
[java] at org.apache.hadoop.hdfs.server.namenode.FSNamesystem.checkPathAccess(FSNamesystem.java:4446)
[java] at org.apache.hadoop.hdfs.server.namenode.FSNamesystem.startFileInternal(FSNamesystem.java:1011)
[java] at org.apache.hadoop.hdfs.server.namenode.FSNamesystem.startFile(FSNamesystem.java:968)
[java] at org.apache.hadoop.hdfs.server.namenode.NameNode.create(NameNode.java:377)
[java] at sun.reflect.GeneratedMethodAccessor7.invoke(Unknown Source)
[java] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
[java] at java.lang.reflect.Method.invoke(Method.java:597)
[java] at org.apache.hadoop.ipc.RPC$Server.call(RPC.java:508)
[java] at org.apache.hadoop.ipc.Server$Handler$1.run(Server.java:959)
[java] at org.apache.hadoop.ipc.Server$Handler$1.run(Server.java:955)
[java] at java.security.AccessController.doPrivileged(Native Method)
[java] at javax.security.auth.Subject.doAs(Subject.java:396)
[java] at org.apache.hadoop.ipc.Server$Handler.run(Server.java:953)
[java]
[java] at org.apache.hadoop.ipc.Client.call(Client.java:739)
[java] at org.apache.hadoop.ipc.RPC$Invoker.invoke(RPC.java:220)
[java] at $Proxy0.create(Unknown Source)
[java] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[java] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
[java] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
[java] at java.lang.reflect.Method.invoke(Method.java:597)
[java] at org.apache.hadoop.io.retry.RetryInvocationHandler.invokeMethod(RetryInvocationHandler.java:82)
[java] at org.apache.hadoop.io.retry.RetryInvocationHandler.invoke(RetryInvocationHandler.java:59)
[java] at $Proxy0.create(Unknown Source)
[java] at org.apache.hadoop.hdfs.DFSClient$DFSOutputStream.(DFSClient.java:2644)
[java] ... 8 more

Conclusión
Voy a abrir un bug en Hadoop para informar de los problemas que tiene el usar "whoami" en Solaris, para que cuando la propiedad os.name de Java sea SunOS entonces que llame a /usr/xpg4/id -un en vez de whoami
if ( System.getProperty("os.name").equals("SunOS") )
shellCommand = "/usr/xpg4/id -un";
else
shellCommand = "/usr/bin/id -un";
Todavía tengo que ver todos los casos en los que se produce y crear un report para crear el bug en Hadoop, de todas formas, espero haber ayudado con el misterio de DrWho.

Introducción a los permisos en HDFS

Introducción
El sistema HDFS implementa un sistema de permisos muy similar a POSIX. Cada uno de los archivos tiene un propietario(user) y un grupo (group). Hasta aquí es similar a la implementación de POSIX, sin embargo HDFS no almacena el user_id y group_id sino que guarda un String con sus valores además el usuario root será aquel que lanze el proceso de Hadoop, es decir, que cualquiera con acceso local a la máquina puede ser root para Hadoop.

Esto supone que la configuración de la seguridad sea muy importante, como ya comenté en el post Instalación de Hadoop, una de las recomendaciones es que no se permita hacer login en el cluster a los usuarios.

Por ello, vamos a establecer unos niveles de seguridad mayores que nos permitan mantener en buenas condiciones nuestra instalación para poder llevarla a producción de una forma óptima.

Limitar el Acceso a nuestro NameNode
Hadoop nos permite incluir una lista de equipos permitidos (y equipos excluidos) los cuales pueden acceder a nuestro NameNode, las propiedades de configuración son las siguientes:
  • dfs.hosts, full path al archivo que contiene los hosts permitidos. Si está vacía (por defecto) todos los hosts pueden acceder
  • dfs.hosts.exclude, full path al archivo que contiene los hosts denegados. Si está vacía (por defecto) no hay ninguno denegado
  • hadoop.security.authorization, habilita el control de acceso al sistema de hadoop (es necesario editar el archivo $HADOOP_HOME/conf/hadoop-policy.xml)

Configuración de IPFilter para limitar el acceso al NameNode
Después de muchas horas con la configuración de Hadoop a vueltas, no he sido capaz de hacer funcionar de una forma sencilla el sistema de autorizaciones. Creo que existe algún tipo de incopatibilidades entre Solaris y la implementación aunque no lo veo muy claro.

Por lo tanto, he buscado la solución más sencilla que consite en activar el firewall IPFilter e incluir los DataNodes y NameNodes en un pool permitiendo su acceso y denegando al resto. Sé que es una solución muy drástica, sin embargo creo que es mucho más efectiva ya que no implica problemas con la resolución de userid o groupid, así que vamos allá.

Activación de IPFilter
Lo primero que debemos hacer es activar IPFilter para ello, ejecutaremos el siguiente comando
# ipf -E
Creamos el pool de nuestro cluster de Hadoop
La configuración de IPFilter nos permite crear un pool de direcciones y referirnos a ellos como pool/_id_ de esta forma es más sencillo gestionar un cluster. También es cierto que con nuestra configuración podemos incluir todas las reglas sin pool ya que son sólo 3 datanode y 1 namenode
# vi /etc/ipf/ipf.conf

# permitimos el acceso a nuestro NameNode
pass in quick from pool/20 to any
pass out quick from any to pool/20

# denegamos el acceso al NameNode
block in quick from any to any port=54310
block in quick from any to any port=54311

:wq!
Y creamos el Pool
# vi /etc/ipf/ippool.conf

table role = ipf type = tree number = 20
{ 10.1.1.3/32, 10.1.1.4/32, 10.1.1.5/32, 10.1.1.6/32 };

:wq
Ya está, cargamos los pool y las reglas y ya está
# ipf -E
# ipf -Fa
# ippool -F
0 objects flushed
# ippool -f /etc/ipf/ippool.conf
# ipf -f /etc/ipf/ipf.conf
He utilizado los comando ipf -Fa para hacer un flush de las reglas al igual que un ippool -F de esta forma todos los filtros están desde cero.

Conclusiones
La conclusión que obtenido es que la implementación de ACL actual en Hadoop no está tan pulida como otras, además de que la documentación es ambigua y difusa. Todo esto me ha hecho perder mucho tiempo en investigación sobre la definición de los parámetros. Sin embargo, IPFilter es un firewall muy maduro que aporta muchas soluciones (no tantas como pf de OpenBSD) para limitar el acceso al NameNode.

Espero que la configuración os sirva de startup ya que como siempre, cada Solaris es un Mundo.


Refrencias

jueves, 23 de julio de 2009

Gestión básica de Zonas en Solaris 10 aplicado a Hadoop

Introducción

Vamos a introducir algunos comandos básicos de administración de zonas que nos ayudarán a mantener nuestra instalación de Hadoop en óptimas condiciones. Este post lo escribo no para ser un referente en la administración de las zonas de Solaris, más bien, debido a que un amigo me ha pedido algunas nociones básicas para la gestión, así que ahí va.

Para la gestión de las zonas en Solaris contamos con los siguientes comandos:
  • zonecfg nos permite configurar los parámetros de la zona (Nombre, IP, Packages, Resources, ...)
  • zoneadm nos permite administrar la zona (Iniciar, Detener, Reiniciar)
  • zlogin nos permite conectarnos a la sesión de una zona
  • zonename nos permite saber el nombre de la zona en la que nos encontramos
Una zona es una instancia nueva de Solaris ejecutándose de forma aislada del kernel principal. Esto expresado de una forma más simple, significa que si una zona produce un kernel panic las demás no se verán afectadas además, se pueden establecer niveles de uso de recursos por lo tanto, una zona no podrá nunca sobrepasar los límites asignados.

Si ha esto le sumamos que las partes constantes del O.S. se encuentran compartidas (/dev, /lib) podemos ver cómo la utilización de Solaris Zones puede darnos una gran ventaja en las arquitecturas Web.

Puedes ver una imagen de la arquitectura obtenida desde http://www.solarisinternals.com/wiki/index.php/Zones_Best_Practices donde explican con detalle el funcionamiento y estructura de Solaris Zones

Solaris siempre tendrá una zona especial llamada Global correspondiente a la instalación del sistema operativo, es decir, la principal y sobre la cual deberemos realizar las tareas de administración de las Zonas Hijas (non-global zone).

Cada zona necesita una ubicación local donde almacenar aquellas partes que no se encuentren compartidas (Shared) y este path debe pertenecer a root y sólo él debe poder escribir. Esto que parece algo tonto es de vital importancia, como hemos comentado al principio, las zonas son aisladas unas de otras, a excepción de la zona Global que gestiona todas las demás, por lo tanto, si "alguien" tomase el control de la zona global, tendrá control sobre las non-global zones.

Por lo tanto, podremos ver el estado de todas las non-global desde la zona global para ello Solaris ha incorporado una opción -Z que hace referencia a todas las zonas en los comandos ps y prstat

Este tema, aunque la gente parece no tener en cuenta es de vital importancia y creo que si merece un post sobre cómo Gestionar la Seguridad en Zonas de Solaris 10 para Hadoop (os lo prometo)

Creación de una Zona
Vamos a crear una zona que nos servirá como template para la creación de datanodes de forma automatizada, para ello desde la zona global haremos lo siguiente
# mkdir -p /opt/zones
# chmod 700 /opt/zones
# zonecfg -z node-template
node-template: No se ha configurado esa zona
Use 'create' para comenzar a configurar una zona nueva.
zonecfg:node-template> create
zonecfg:node-template> set zonepath=/opt/zones/node-template
zonecfg:node-template> set autoboot=false
zonecfg:node-template> add net
zonecfg:node-template:net> set physical=e1000g0
zonecfg:node-template:net> set address=10.1.1.7/24
zonecfg:node-template:net> set defrouter=10.1.1.254
zonecfg:node-template:net> end
zonecfg:node-template> verify
zonecfg:node-template> commit
zonecfg:node-template> exit
Fácil no? Yo he establecido el valor de la propiedad autoboot a false ya que mi intención es mantener esta zona apagada como un template para desplegar datanodes, sin embargo, si quieres que Solaris inicie la zona automáticamente sólo tienes que poner el valor a true


Configuración de una Zona Existente

# zonecfg -z node-template
zonecfg:node-template> info
zonename: node-template
zonepath: /opt/zones/node-template
brand: native
autoboot: false
bootargs:
pool:
limitpriv:
scheduling-class:
ip-type: shared
inherit-pkg-dir:
dir: /lib
inherit-pkg-dir:
dir: /platform
inherit-pkg-dir:
dir: /sbin
inherit-pkg-dir:
dir: /usr
net:
address: 10.1.1.7/24
physical: e1000g0
defrouter: 10.1.1.254
zonecfg:node-template> exit
Y si queremos borrar una propiedad?
zonecfg:node-template> remove net
zonecfg:node-template> info
zonename: node-template
zonepath: /opt/zones/node-template
brand: native
autoboot: false
bootargs:
pool:
limitpriv:
scheduling-class:
ip-type: shared
inherit-pkg-dir:
dir: /lib
inherit-pkg-dir:
dir: /platform
inherit-pkg-dir:
dir: /sbin
inherit-pkg-dir:
dir: /usr

Instalación de una Zona
Una vez ya hemos configurado la zona, podemos comenzar la instalación con el siguiente comando
# zoneadm -z node-template install
Preparing to install zone .
Creating list of files to copy from the global zone.
Copying <8137> files to the zone.
Initializing zone product registry.
Determining zone package initialization order.
Preparing to initialize <1194> packages on the zone.
Initialized <1194> packages on zone.
Zone is initialized.
Ya hemos instalado la zona, podemos comprobar su estado utilizando el comando zoneadm list
# zoneadm list -cv
ID NAME STATUS PATH BRAND IP
0 global running / native shared
1 node2 running /opt/zones/node2 native shared
2 node3 running /opt/zones/node3 native shared
3 node1 running /opt/zones/node1 native shared
- node-template installed /opt/zones/node-template native shared
Todavía nos queda un último paso que es configurar el sistema, para ello, deberemos conectarnos a la consola de la zona utilizando la opción -C

Nota: zlogin -C utiliza como secuencia de escape ~. sin embargo, es posible cambiarla por la que queramos utilizando -e

Nos conectamos a la consola y finalizamos la instalación de Solaris como siempre (he puesto como caracter de escape #. en vez de
~.)
# zoneadm -z node-template boot
# zlogin -C -e\# node-template
[Conectado a la consola de la zona 'node-template']
Una vez concluida la identificación del sistema nuestra zona ya está preparada

boot/reboot/halt de una Zona
Para las tareas de administración de la zona utilizaremos el comando zoneadm, a continuación podemos ver la opciones que tiene
# zoneadm
sintaxis: zoneadm help
zoneadm [-z ] [-u ] list
zoneadm {-z |-u }

Subórdenes:

help
boot [-- boot_arguments]
halt
ready
reboot [-- boot_arguments]
list [-cipv]
verify
install [-x nodataset] [brand-specific args]
uninstall [-F]
clone [-m method] [-s ] zonename
move zonepath
detach [-n]
attach [-F] [-n ] [-b patchid]* [-u]
mark incomplete
Para ver las zonas disponibles y sus estados utilizaremos
# zoneadm list -cv
Si queremos bootar una zona ejecutaremos el siguiente comando
# zoneadm -z _nombre_zona_ boot
Si queremos parar una zona ejecutaremos el siguiente comando
# zoneadm -z _nombre_zona halt
Si queremos rebootar una zona ejecutaremos el siguiente comando
# zoneadm -z _nombre_zona reboot
Si queremos que una zona deje de estar disponible para su gestión, pero no borrarla
# zoneadm -z _nombre_zona detach
Si queremos que una zona vuelva a estar disponible para su gestión
# zoneadm -z _nombre_zona attach
Clonación de una Zona
Para poder clonar una zona, ésta debe estar halted y attached para ello, procederemos a clonar nuestra node-template a una nueva zona node4. Cuando clonamos una zona ésta (la clonada) se clona en estado unconfigured y por lo tanto es necesario conectarse a la consola para concluir la instalación. En cierta medida, la única diferencia entre crear una zona desde cero y una clonación es el origen de los paquetes (básicamente)

Obtenemos la configuración de la zona node-template (source)
# zonecfg -z node-template > node-template.cfg
A continuación editamos el archivo de configuración y cambiamos los parámetros
zonename, zonepath y net, p
or ejemplo, con los siguientes valores
zonename: node4
zonepath: /opt/zones/node4
brand: native
autoboot: false
bootargs:
pool:
limitpriv:
scheduling-class:
ip-type: shared
inherit-pkg-dir:
dir: /lib
inherit-pkg-dir:
dir: /platform
inherit-pkg-dir:
dir: /sbin
inherit-pkg-dir:
dir: /usr
net:
address: 10.1.1.8/24
physical: e1000g0
defrouter: 10.1.1.254
Crearemos la nueva zona con la configuración que hemos modificado
# zonecfg -z node4 -f node-template.cfg
Detenemos la zona de la cual vamos a clonar
# zoneadm -z node-template halt
Iniciaremos el proceso de Clonación

# zoneadm -z node4 clone node-template
Una vez concluido el proceso de clonación, podemos conectarnos a la consola de la nueva zona node4 y finalizar el proceso de identificación del sistema como hemos visto en el paso de Instalación

Espero que aunque sé que es muy breve, os sirva para recordar y perder el miedo a las zonas.

Más información sobre Administración de Solaris Zones

martes, 21 de julio de 2009

HDFS Primeros Pasos - Solaris 10

Introducción
Durante los post anteriores, hemos Instalado y Configurado Hadoop en un cluster de tres nodos. Ahora bien, todavía no hemos empezado a exprimir Hadoop, ....

Primeros Pasos
La iteración con el cluster se realiza utilizando el comando $HADOOP_HOME/bin/hadoop si
tecleamos el comando sin parámetros, nos muestra una ayuda de los comandos principales disponibles como se muestra a continuación
$ hadoop
Usage: hadoop [--config confdir] COMMAND
where COMMAND is one of:
namenode -format format the DFS filesystem
secondarynamenode run the DFS secondary namenode
namenode run the DFS namenode
datanode run a DFS datanode
dfsadmin run a DFS admin client
mradmin run a Map-Reduce admin client
fsck run a DFS filesystem checking utility
fs run a generic filesystem user client
balancer run a cluster balancing utility
jobtracker run the MapReduce job Tracker node
pipes run a Pipes job
tasktracker run a MapReduce task Tracker node
job manipulate MapReduce jobs
queue get information regarding JobQueues
version print the version
jar run a jar file
distcp copy file or directories recursively
archive -archiveName NAME * create a hadoop archive
daemonlog get/set the log level for each daemon
or
CLASSNAME run the class named CLASSNAME
Most commands print help when invoked w/o parameters.
En esta primera entrega, vamos a ver los principales comandos de FileSystem que se encuentran divididos en tres subcategorías: fs, fsck y dfsadmin
  • fs, nos permite interactuar con el sistema de fichero. Implementa las principales utilidades de UNIX como "ls, cat, rm, mkdir, mv"
  • fsck, nos permite verificar el sistema de ficheros
  • dfsadmin, nos permite obtener información de los clientes y del sistema de ficheros
Vamos a empezar con un pequeño ejemplo, será nuestro HolaMundo de HDFS, para ello, vamos a crear un directorio "helloworld" y vamos a copiar en el nuestro "HolaMundo!"

$ cat >helloworld<
> HolaMundo
> EOF
$ hadoop fs -mkdir helloworld
$ hadoop fs -put helloworld helloworld/holamundo.dfs
$ hadoop fs -ls helloworld
Found 1 items
-rw-r--r-- 3 DrWho supergroup 10 2009-07-20 18:43 /user/DrWho/helloworld/holamundo.dfs
$ hadoop fs -cat helloworld/holamundo.dfs
HolaMundo
Sencillo no? El único comando que merece explicación es -put que nos permite poner un archivo/directorio local en el sistema de ficheros remoto.

Puedes encontrar más detalle en esta dirección

Verificar el estado de nuestro HDFS
Los fallos suceden. Esta es una premisa que debes tener muy en cuenta ya que la probabilidad de tener fallos en los nodos cuando estamos hablando de muchos, muchos nodos, es más probable que la que no falle ninguno. Esto hace que sea necesario comprobar la estructura del sistema HDFS, para ello, utilizaremos el siguiente comando:
$ hadoop fsck /
......Status: HEALTHY
Total size: 116417442 B
Total dirs: 10
Total files: 6
Total blocks (validated): 6 (avg. block size 19402907 B)
Minimally replicated blocks: 6 (100.0 %)
Over-replicated blocks: 0 (0.0 %)
Under-replicated blocks: 0 (0.0 %)
Mis-replicated blocks: 0 (0.0 %)
Default replication factor: 3
Average block replication: 2.8333333
Corrupt blocks: 0
Missing replicas: 0 (0.0 %)
Number of data-nodes: 4
Number of racks: 1


The filesystem under path '/' is HEALTHY

Nota: En HDFS el pathSepartor es "/" siempre

Administrar el Cluster HDFS
Dentro de las tareas de administración podemos destacar Ver el estado de los nodos, Espacio Libre, Volver a leer la configuración, Liberar espacio, todas estas opciones (y más) se encuentran en dfsadmin, vamos a ver algunos ejemplos

Para ver las opciones que tenemos dentro de dfsadmin introduciremos el siguiente comando (sin argumentos)
$ hadoop dfsadmin
Usage: java DFSAdmin
[-report]
[-safemode enter | leave | get | wait]
[-saveNamespace]
[-refreshNodes]
[-finalizeUpgrade]
[-upgradeProgress status | details | force]
[-metasave filename]
[-refreshServiceAcl]
[-setQuota ...]
[-clrQuota ...]
[-setSpaceQuota ...]
[-clrSpaceQuota ...]
[-help [cmd]]

Generic options supported are
-conf specify an application configuration file
-D use value for given property
-fs specify a namenode
-jt specify a job tracker
-files specify comma separated files to be copied to the map reduce cluster
-libjars specify comma separated jar files to include in the classpath.
-archives specify comma separated archives to be unarchived on the compute machines.

The general command line syntax is
bin/hadoop command [genericOptions] [commandOptions]

De todas las opciones disponibles, en esta primera parte, vamos a centrarnos en -report y -refreshNodes

Utilizaremos -report para ver el estado de los Nodos, es decir, espacio libre, nodos activos e inactivos, etc.
$ hadoop dfsadmin -report
Configured Capacity: 24784855040 (23.08 GB)
Present Capacity: 10768458752 (10.03 GB)
DFS Remaining: 10532012032 (9.81 GB)
DFS Used: 236446720 (225.49 MB)
DFS Used%: 2.2%
Under replicated blocks: 57
Blocks with corrupt replicas: 0
Missing blocks: 0

-------------------------------------------------
Datanodes available: 2 (2 total, 0 dead)

Name: 10.1.1.3:50010
Decommission Status : Normal
Configured Capacity: 12392427520 (11.54 GB)
DFS Used: 118223872 (112.75 MB)
Non DFS Used: 7008197632 (6.53 GB)
DFS Remaining: 5266006016(4.9 GB)
DFS Used%: 0.95%
DFS Remaining%: 42.49%
Last contact: Wed Jul 22 11:25:05 CEST 2009


Name: 10.1.1.5:50010
Decommission Status : Normal
Configured Capacity: 12392427520 (11.54 GB)
DFS Used: 118222848 (112.75 MB)
Non DFS Used: 7008198656 (6.53 GB)
DFS Remaining: 5266006016(4.9 GB)
DFS Used%: 0.95%
DFS Remaining%: 42.49%
Last contact: Wed Jul 22 11:25:06 CEST 2009
En la primera sección del report, podemos observar información sobre Capacidad, Espacio Libre, Espacio Usado sin embargo, una parte importante es Under replicated blocks que nos informa de aquellos chunks que no se encuentran replicados según su configuración, es decir. Si hemos establecido el valor de dfs.replication a 3 nos informa cuántos bloques no tienen ese valor en el cluster y por lo tanto, se encuentran por debajo del umbral de replicación

Para volver a leer la configuración de Hadoop utilizaremos -refreshNodes. Esta opción será interesante cuando actualicemos el número de nodos (añadir, eliminar) y la explicaremos con más detalle en Administración de Hadoop
$ hadoop dfsadmin -refreshNodes
Por último, vamos a introducir un comando (que explicaremos con más detalle en Administración de Hadoop) encargado de balancear los chunks entre los diferentes DataNodes

$ hadoop balancer
Time Stamp Iteration# Bytes Already Moved Bytes Left To Move Bytes Being Moved
09/07/22 11:32:17 INFO net.NetworkTopology: Adding a new node: /default-rack/10.1.1.3:50010
09/07/22 11:32:17 INFO net.NetworkTopology: Adding a new node: /default-rack/10.1.1.5:50010
09/07/22 11:32:17 INFO balancer.Balancer: 0 over utilized nodes:
09/07/22 11:32:17 INFO balancer.Balancer: 0 under utilized nodes:
The cluster is balanced. Exiting...
09/07/22 11:32:17 WARN conf.Configuration: mapred-default.xml:a attempt to override final parameter: mapred.job.tracker; Ignoring.
Balancing took 2.341 seconds


Un poco de resumen


Hemos visto muy por encima las diferentes secciones que Hadoop nos proporciona para Administrar HDFS. Entraremos en más detalle en el post dedicado a Administración de Hadoop sobre Solaris 10 hasta entonces espero que hagáis vuestras pruebas ....

lunes, 20 de julio de 2009

Instalación Hadoop sobre Solaris - Configurar SMF para DataNode y TaskTracker

Introducción
En post anteriores hemos concluido la primera parte de la Instalación y Configuración de Hadoop sobre Solaris 10, sin embargo, vamos a incluir alguna mejora en la configuración para evitar caídas de los DataNode

Configurar DataNode para arranque automático utilizando SMF
La configuración y estado de los servicio en Solaris 10 trajo una nueva característica llamada SMF, básicamente sustituye la antigua funcionalidad de los /etc/rc?.d por un framework más avanzado. Pues bien, vamos a utilizarlo para configurar el inicio de nuestros DataNodes de forma que se inicien solos.

Creación del descriptor SMF
Para ello, crearemos la siguiente estrucutra de directorios en los datanodes
# mkdir -p /var/svc/manifest/application/hadoop
# cd /var/svc/manifest/application/hadoop
# vi datanode.xml

He introducimos lo siguiente:

<service_bundle type="'manifest'" name="'HADOOP:DataNode'">
<service name="application/hadoop/datanode" type="service" version="1">
<create_default_instance enabled="'false'">
<single_instance>

<dependency name="multi-user-server" grouping="optional_all" type="service" restart_on="none">
<service_fmri value="'svc:/milestone/multi-user-server'">
</service_fmri>

<exec_method type="method" name="start" exec="/lib/svc/method/hadoop/datanode %m" timeout_seconds="60">
<method_context>
<method_credential user="'hadoop'">
</method_credential>
</method_context>

<exec_method type="method" name="restart" exec="/lib/svc/method/hadoop/datanode %m" timeout_seconds="60">
<method_context>
<method_credential user="'hadoop'">
</method_credential>
</method_context>

<exec_method type="method" name="stop" exec="/lib/svc/method/hadoop/datanode %m" timeout_seconds="60">
<method_context>
<method_credential user="'hadoop'">
</method_credential>
</method_context>

<property_group name="'startd'" type="'framework'">
<propval name="'duration'" type="'astring'" value="'contract'">
</propval>

<template>
<common_name>
<loctext lang="'C'">
HADOOP DataNode Service
</loctext>
</common_name>
<documentation>
<doc_link name="'hadoop_datanode_overview'" uri="'http://http://sparcki.blogspot.com/2009/07/apache-hadoop-que-es-y-para-que-sirve.html'/">
<doc_link name="'hadoop_datanode_install'" uri="'http://http://hadoop.apache.org/'">
</doc_link>
</doc_link>
</documentation>

Validamos e Importamos la definición

# svccfg
svc:> validate /var/svc/manifest/application/hadoop/datanode.xml
svc:> import /var/svc/manifest/application/hadoop/datanode.xml
svc:> quit


A continuación, crearemos el method que será llamado por el framework SMF

# mkdir -p /lib/svc/method/hadoop
# cd /lib/svc/method/hadoop
# vi datanode

He introducimos lo siguiente

#!/sbin/sh
# Start/stop Hadoop DataNode
#
.. /lib/svc/share/smf_include.sh
HADOOP_HOME=/opt/hadoop
HADOOP_DAEMON=hadoop-daemon.sh
CFG=$HADOOP_HOME/bin/$HADOOP_DAEMON
TYPE=datanode

case "$1" in
'start')
$CFG start $TYPE
sleep 2
;;
'restart')
$CFG stop $TYPE
sleep 2
$CFG start $TYPE
;;
'stop')
$CFG stop $TYPE
;;
*)
echo "Usage: $0 { start | stop | restart }"
exit 1
;;
esac
exit $SMF_EXIT_OK

Corregimos los permisos y propietario
# chown -R root:sys /var/svc/manifest/application/hadoop
# chown -R root:bin /lib/svc/method/hadoop/
# chmod 555 /lib/svc/method/hadoop/datanode

Ya podemos activar el servicio
# svcadm enable -t svc:/application/hadoop/datanode
# svcs -a|grep hadoop
online 17:39:20 svc:/application/hadoop/datanode:default

Ya está! Si ahora hacemos un kill -9 de nuestro PID, veremos como el framework SMF vuelve a iniciar el demonio

Os dejo a vuestra imaginación cómo hacer un servicio para el TaskTracker y de esta forma tener los datanodes con arranque automático.


Os he dejado los archivos de configuración completos para que los podais descargar en las siguientes direcciones:

jueves, 16 de julio de 2009

Instalación de Hadoop sobre Solaris 10 - Configuración

Introducción
Ya hemos visto en el post anterior como Instalar Hadoop sobre Solaris 10, sin embargo, no hemos hecho más que empezar. En esta nueva entrega configuraremos Hadoop y Solaris para tener un Cluster funcional con soporte para HDFS.

Debemos tener en cuenta que la seguridad de HDFS no es más elevada que la que nos pueda proporcionar NFS, por lo tanto, es altamente recomendable que las máquinas que componen el cluster de Hadoop sólo se dediquen a esto y que los usuarios no puedan hacer login en las mismas.

Por ejemplo, podemos estructurar nuestra red utilizando el siguiente esquema:

Nota: La configuración del esquema es conceptual ya que las reglas del firewall deben ser más extensas, sin embargo, quería mostrar el concepto de bloquear todo el acceso al cluster de Hadoop desde cualquier workstation exceptuando una encargada de su gestión.

Desactivación de servicios no necesarios en Solaris 10
Aunque este paso no es estrictamente necesario, es muy recomendable ya que queremos realizar una instalación lo más óptima posible con el fin de poder utilizar Hadoop en producción.
# svcadm disable svc:/application/graphical-login/cde-login:default
# svcadm disable svc:/network/smtp:sendmail

Configuración de Hadoop - HDFS

Vamos a comenzar configurando el sistema HDFS, para ello, debemos tener en cuenta que en esta arquitectura el namenode es nuestro punto único de fallo (SPOF) y por lo tanto los metadatos y log de transacciones son nuestro mayor tesoro, son como los Redolog y ArchiveLog de Oracle, por ello, vamos a utilizar la arquitectura OFA pero un poco adaptada.

En Oracle utilizaríamos una SAN para almacenar los datos, sin embargo, una de las principales caracteristicas de HDFS es que utiliza una arquitectura shared_nothing, es decir, cada nodo almacena su información independientemente de los demás. Esta arquitectura nos permite que el fallo de una datanode no afecte a los demás.

Voy a tratar de explicarlo con un ejemplo. Pensemos en HSFS como un RAID 5, donde cada disco del RAID es un datanode y por lo tanto ante la pérdida de un disco, los demás reconstruyen el contenido. Bien, HDFS copia cada bloque de datos n veces, siendo 3 por defecto, por lo tanto, es aquí donde encontramos la redundancia. Creo que el funcionamiento de HDFS y su tuning me llevará todo un post que lo verás dentro de poco, hasta entonces puedes encontrar más información en Apache HDFS.

Como ya he comentado nuestro namenode es nuestro SPOF por lo tanto, debemos tener la mayor redundancia posible en este host, es decir, RAID 1 o RAID 1+0 para el almacenamiento de los metadatos y transaction logs que serán las partes necesarias para poder reconstruir el sistema de ficheros ante una caída.

Nota: En mi instalación de ejemplo no existe RAID, ni HDD separados, aunque sea para pruebas no es muy recomendable esta configuración.

Por lo tanto, vamos a utilizar el path /u02/metadata/${user.name} para el almacenamiento de los metadatos, /u02/editlog/${user.name} para transaction log (EditLog) y /u02/data/${user.name} para los bloques de datos, de esta forma, podemos tener varias instalaciones de Hadoop ejecutándose con diferentes nombres, con un único path de almacenamiento ya que Hadoop convertirá ${user.name} al nombre de usuario que está ejecutando Hadoop.

# mkdir -p /u02/metadata/hadoop
# mkdir -p /u02/editlog/hadoop
# mkdir -p /u02/data/hadoop
# mkdir -p /u02/pid/hadoop
# chown -R hadoop:hadoop /u02/
# chmod 700 /u02

Nota: Como siempre, deberemos crear la estructura de directorios en todos los nodos del cluster.


Ya estamos listos para comenzar con la configuración de Hadoop, nos conectaremos a la máquina que va hacer de namenode y establecemos la configuración que luego replicaremos en todos los nodos. La configuración mínima que debemos establecer es:
  • JAVA_HOME path de java, en nuestro caso, /usr/java
  • HADOOP_HEAPSIZE tamaño máximo en Mb de JavaHeap, en nuestro caso, 500
  • HADOOP_OPTS opciones de tuning para la máquina virtual, en nuestro caso, -server
  • HADOOP_MASTER configuración de la cual se sincronizarán los clientes, en nuestro caso, master:$HADOOP_HOME/src/hadoop
  • HADOOP_PID_DIR ubicación de los pid, en Solaris es, /var/run
Así que nos conectamos al NameNode y configuramos el sistema de la siguiente forma
# zonename
global
# su - hadoop
$ cd $HADOOP_HOME
$ vi conf/hadoop-env.sh
export JAVA_HOME=/usr/java
export HADOOP_HEAPSIZE=500
export HADOOP_OPTS=-server
export HADOOP_PID_DIR=/u02/pid/hadoop

# Command specific options appended to HADOOP_OPTS when specified
export HADOOP_NAMENODE_OPTS="-Dcom.sun.management.jmxremote $HADOOP_NAMENODE_OPTS"
export HADOOP_SECONDARYNAMENODE_OPTS="-Dcom.sun.management.jmxremote $HADOOP_SECONDARYNAMENODE_OPTS"
export HADOOP_DATANODE_OPTS="-Dcom.sun.management.jmxremote $HADOOP_DATANODE_OPTS"
export HADOOP_BALANCER_OPTS="-Dcom.sun.management.jmxremote $HADOOP_BALANCER_OPTS"
export HADOOP_JOBTRACKER_OPTS="-Dcom.sun.management.jmxremote $HADOOP_JOBTRACKER_OPTS"
En el archivo $HADOOP_HOME/conf/core-site.xml

<property>
<name>fs.default.name</name>
<value>hdfs://namenode.hadoop.test.com:54310/</value>
<final>true</final>
</property>

<property>
<name>mapred.job.tracker</name>
<value>hdfs://namenode.hadoop.test.com:54311/</value>
<final>true</final>
</property>
Nota: El valor debe ser hdfs://___nombre_dns__que__queramos__/

Ahora vamos a editar el archivo de configuración de HDFS que se encuentra en $HADOOP_HOME/conf/hdfs-site.xml sin embargo hay que tener en cuenta unas cosas. En nuestra configuración queremos hacer distinción de metadata, editlog y data, por ello vamos a definir las propiedades dfs.name.dir (MetaDatos), dfs.name.edits.dir (EditLog) y dfs.data.dir, si no queremos separarlo podemos dejarlo con sus configuraciones por defecto, para ello sólo debemos establacer el la propiedad hadoop.tmp.dir. Puedes ver la configuración por defecto que se aplicará a HDFS en $HADOOP_HOME/src/hdfs/hdfs-default.xml

  • dfs.name.dir ubicación de los metadatos, en nuestro caso, /u02/metadata/${user.name}
  • dfs.name.edits.dir ubicación de los editlog, en nuestro caso, /u02/editlog/${user.name}
  • dfs.data.dir ubicación de los bloques de datos, en nuestro caso, /u02/data/${user.name}
  • dfs.replication número de réplicas, en nuestro caso, 8
El formato del archivo es xml utilizando los tags property, name y value para asignarlos. Existe una etiqueta llamada final que si está establecida a true el valor de la propiedad no puede ser modificado en ejecución. A continuación se muestra el archivo $HADOOP_HOME/conf/hdfs-site.xml

<property>
<name>dfs.name.dir</name>
<value>/u02/metadata/${user.name}</value>
<final>true</final>
</property><property>
<name>dfs.name.edits.dir</name>
<value>/u02/editlog/${user.name}</value>
<final>true</final>
</property>
<property>
<name>dfs.data.dir</name>
<value>/u02/data/${user.name}</value>
<final>true</final>
</property>
<property>
<name>dfs.replication</name>
<value>8</value>
</property>
Asignaremos ahora los master y slaves, como hemos comentado con anterioridad, HDFS necesita de un NameNode y JobTracker como mínimo y de mútiples datanodes. Así que en el fichero masters pondremos el NameNode y TrackerNode y en el fichero slaves todos los datanode que queramos, en nuestro caso node1 y node2.

Nota: Esto no lo tengo todavía muy claro, ya que no encuentro ninguna información sobre "TrackerNode" así que he asumido que irá en Masters, ya que son los dos únicos que hacen de Master

$ echo "namenode" > $HADOOP_HOME/conf/masters
$ echo "node1" > $HADOOP_HOME/conf/slaves
$ echo "node2" >> $HADOOP_HOME/conf/slaves
Ya hemos configurado el nodo principal, ahora tenemos que replicar la configuración a los nodos secundarios node1 y node2

$ pwd
/opt/hadoop/conf
$ scp hadoop-env.sh core-site.xml hdfs-site.xml masters hadoop@node1:$PWD
hadoop-env.sh 100% |**********************************************************************************************************| 2222 00:00
core-site.xml 100% |**********************************************************************************************************| 433 00:00
hdfs-site.xml 100% |**********************************************************************************************************| 599 00:00
masters 100% |**********************************************************************************************************| 9 00:00

$ scp hadoop-env.sh core-site.xml hdfs-site.xml masters hadoop@node2:$PWD
hadoop-env.sh 100% |**********************************************************************************************************| 2222 00:00
core-site.xml 100% |**********************************************************************************************************| 433 00:00
hdfs-site.xml 100% |**********************************************************************************************************| 599 00:00
masters 100% |**********************************************************************************************************| 9 00:00

Y eliminamos el contenido del archivo slaves en los nodos node1 y node2 ya que no tienen ninguno.

$ ssh node1
$ echo "" > $HADOOP_HOME/conf/slaves

$ ssh node2
$ echo "" > $HADOOP_HOME/conf/slaves

Con esto, hemos acabado la configuración de Hadoop!! Ahora, el siguiente paso es formatear la nueva unidad HDFS para que podamos empezar a trabajar con ella.

$ bin/hadoop namenode -format
09/07/17 10:37:00 INFO namenode.NameNode: STARTUP_MSG:
/************************************************************
STARTUP_MSG: Starting NameNode
STARTUP_MSG: host = sol10-enigma/10.1.1.4
STARTUP_MSG: args = [-format]
STARTUP_MSG: version = 0.20.0
STARTUP_MSG: build = https://svn.apache.org/repos/asf/hadoop/core/branches/branch-0.20 -r 763504; compiled by 'ndaley' on Thu Apr 9 05:18:40 UTC 2009
************************************************************/
Re-format filesystem in /u02/metadata/hadoop ? (Y or N) Y
09/07/17 10:37:03 INFO namenode.FSNamesystem: fsOwner=DrWho,hadoop
09/07/17 10:37:03 INFO namenode.FSNamesystem: supergroup=supergroup
09/07/17 10:37:03 INFO namenode.FSNamesystem: isPermissionEnabled=true
09/07/17 10:37:03 INFO common.Storage: Image file of size 95 saved in 0 seconds.
09/07/17 10:37:03 INFO common.Storage: Storage directory /u02/metadata/hadoop has been successfully formatted.
09/07/17 10:37:03 INFO common.Storage: Storage directory /u02/editlog/hadoop has been successfully formatted.
09/07/17 10:37:03 INFO namenode.NameNode: SHUTDOWN_MSG:
/************************************************************
SHUTDOWN_MSG: Shutting down NameNode at sol10-enigma/10.1.1.4
************************************************************/

Una vez formateado en nuevo sistema de ficheros, ya podemos iniciar Hadoop, para ello, debemos iniciar HDFS y MAP

$ $HADOOP_HOME/bin/start-dfs.sh
starting namenode, logging to /opt/hadoop/bin/../logs/hadoop--namenode-sol10-enigma.out
node1: starting datanode, logging to /opt/hadoop/bin/../logs/hadoop-hadoop-datanode-node1.out
node2: starting datanode, logging to /opt/hadoop/bin/../logs/hadoop-hadoop-datanode-node2.out
namenode: starting secondarynamenode, logging to /opt/hadoop/bin/../logs/hadoop-hadoop-secondarynamenode-sol10-enigma.out

$ $HADOOP_HOME/bin/start-mapred.sh
starting jobtracker, logging to /opt/hadoop/bin/../logs/hadoop--jobtracker-sol10-enigma.out
node1: starting tasktracker, logging to /opt/hadoop/bin/../logs/hadoop-hadoop-tasktracker-node1.out
node2: starting tasktracker, logging to /opt/hadoop/bin/../logs/hadoop-hadoop-tasktracker-node2.out

Si todo ha ido bien, podemos ver que el sistema está funcionando utilizando el comando jps del JDK que nos proporciona el pid y ClassName

$ /usr/java/bin/jps
8619 Jps
8473 JobTracker
2998 SecondaryNameNode
2826 NameNode


Un poco de resumen

Hemos visto como configurar el sistema de ficheros HDFS utilizando diferentes path para los metadatos, editlog y data, de esta forma, podemos separar en diferentes unidades físicas cada una de las partes, añadiendo tolerancia a fallos incorporando algún sistema de RAID en metadata y editlog.

En el próximo post empezaremos con nuestro HelloWorld dentro de HDFS y los comandos más básicos, espero no haberos aburrido mucho :)