jueves, 23 de mayo de 2013

WordCount: testing Hadoop

En la anterior entrada hablé de Ambari, la plataforma para el control de clusters Hadoop y servicios asociados. Hoy vamos a poner a prueba el funcionamiento de cluster. Para ello lanzaremos nuestro primer programa paralelo. Para lo ocasión usaremos uno de ejemplo de los que podréis encontrar en la Wiki de Hadoop y cuya función es contar las palabras que aparecen en uno (o varios) archivos de texto.

Antes de ello, repasemos algunos conceptos asociados a Hadoop. Como ya vimos anteriormente, su objetivo es proveer un entorno para el trabajo paralelo bajo el paradigma MapReduce, trabajos que se distribuyen para su procesamiento en un cluster. HDFS es el sistema de ficheros en dicho cluster que soporta esta operativa. Este sistema de ficheros permite, usando el disco local de cada máquina, generar un espacio unificado que desde el punto de vista lógico se comporta y gestiona como si de un solo disco se tratase. En realidad por debajo HDFS lo que hace es replicar la información en los diferentes nodos del cluster asegurando en todo momento la coherencia de datos y la tolerancia a fallos por caídas puntuales de nodos.

Lo primero que necesitaremos en un fichero de entrada con palabras que contar. Como es un test tampoco importa mucho cómo sea ese fichero. Por ejemplo, he generado uno de nombre input1.txt concatenando varios ficheros de logs del sistema. El fichero ocupa 542MB y tiene mas de 6 millones de líneas:


Como puede verse en la imagen anterior, primero deberemos copiar el fichero al espacio de disco HDFS del cluster. Eso se consigue haciendo uso de los comandos Hadoop asociados al tratamiento del almacenamiento (dfs), en concreto tendremos que crear un nuevo directorio que contenga el fichero de entrada y copiarlo en dicha localización dentro del espacio HDFS.

Pero antes de lanzar nuestro programa tendremos que crearlo. Hadoop está desarrollado con tecnología Java por lo que ofrece todo un conjunto completo de librerías bajo este lenguaje para desarrollar los aplicativos paralelos. En nuestro caso el código que especifica cómo debe ser tratada la entrada, wordcount, debe definir las acciones tanto para el mapeo (Map) como la reducción (Reduce). Siguiendo el ejemplo de la wiki comentado anteriormente, el código quedaría de la siguiente forma:

Es bastante intuitivo interpretar lo definido anteriormente. Se puede apreciar que están definidas claramente tres secciones:
  1. La función Map: en la que a cada palabra se le asigna el valor 1 (one)
  2. La función Reduce: en la que se agrega dicho valor por cada palabra mapeada
  3. La función main: principal, que es la que controla la creación de la tarea (Job), establece los parámetros iniciales de lanzamiento y controla su estado.
Definido el fichero de entrada y el programa paralelo solo resta ejecutarlo en nuestro cluster:

Como acabamos de comprobar, nuestro job paralelo se ha ejecutado en el cluster Hadoop satisfactoriamente, obteniendo una respuesta a nuestra necesidad: contar el numero de veces que cada palabra aparecía en el fichero de entrada. Pero recordemos que disponemos de la plataforma Ambari, nuestro controlador del cluster Hadoop. Si revisamos en su interfaz web podremos ver detalles interesantes como, por ejemplo, la información asociada al job:


De forma rápida tenemos acceso a información detallada sobre el trabajo en ejecución. Y si pulsamos sobre el job en concreto obtendremos un detalle aun mayor de cómo y cuando se han ido ejecutando las diferentes fases del trabajo:


Visualmente obtenemos información tan interesante como:
  • El estado de ejecución: exitoso (SUCCESS) o erróneo (FAILED)
  • La duración total del trabajo, casi 212 segundos
  • 5 de los 6 nodos disponibles han estado implicados en el trabajo
  • Detalles sobre el estado de ejecución de la tarea en el tiempo, como cuantos nodos han participado en las diferentes fases Map y Reduce.
Si comparamos esta tarea con realizar el cálculo haciendo uso de un script tradicional (secuencial) observamos el siguiente resultado:


En este caso, la ejecución completa del trabajo ha tardado 4 minutos y 35 segundos, es decir, 275 segundos. Comparativamente se ha obtenido una reducción del 30% en tiempo de ejecución gracias al uso del cluster.

Y esto es solo un ejemplo. Con tareas mejor diseñadas las reducciones podrían ser mas significativas. Y no olvidemos que el cluster, y su filosofía de trabajo paralelizada, nos permiten abordar problemas de cálculo con volúmenes de entrada muy grandes. En este ejemplo hemos usando un fichero con unas 6 millones de lineas. Pero imaginad que tuviera, por ejemplo, 10 o 100 veces más. El problema seguiría siendo resoluble en nuestro cluster Hadoop y sin embargo, por limitaciones de memoria, una sola máquina de forma secuencial dificilmente podría abordarlo.

domingo, 19 de mayo de 2013

Ambari: Plataforma para el procesamiento paralelo

Hoy quiero hablar de Ambari, un proyecto bajo el auspicio de la Fundación Apache y que cuenta con el apoyo de la gente de Hortonworks. El objetivo de Ambari es proveer de un framework amigable para el uso de Hadoop y sus aplicaciones complementarias (HDFS, MapReduce, Hive, HCatalog, HBase, etc) en una solución integrada y facilmente escalable. Si tu pregunta es ¿qué es Hadoop?, pues Hadoop es una solución de software libre para el tratamiento de lo que ahora está tan de moda: el Bigdata.

Bigdata es (según la Wikipedia), en el sector de tecnologías de la información y la comunicación, una referencia a los sistemas que manipulan grandes conjuntos de datos. A grandes rasgos se trata de analizar ingentes cantidades de datos con el objetivo de obtener información relevante de ellos. Pero procesar grandes volúmenes de información no es una tarea fácil. Muchas veces el conjunto de datos a analizar es tan grande que excede las capacidades de espacio, en disco y memoria, de los sistemas convencionales y el tiempo que requeriría su análisis secuencial sería considerable. ¿Cómo resolver el problema? Divide y vencerás.

En 2004 los gurus de Google publicaron una documentación relativa al paradigma MapReduce el cual toma un problema complejo y lo divide en varios trozos procesables de forma paralela. Cada uno de estos trozos son enviados un servidor, o nodo del cluster, que trabaja con ellos en dos fases claramente diferenciadas:
  • Map: Fase de mapeo en la que se toma el conjunto de datos de entrada y se mapea esa entrada de una determinada forma
  • Reduce: Fase en la que se toman los valores mapeados previamente y se aplica un determinado procesamiento para reducirlos y obtener la información de interés
Tomando el ejemplo descrito en el documento de Google, imaginad que quereis contar el número de veces que aparecen las palabras en un determinado documento. Expresado en pseudo-código el ejemplo tendría mas o menos de la siguiente forma:


En la primera fase (Map) se mapearia cada palabra al valor 1. En la segunda fase (Reduce) por cada palabra se agregarán sucesivamente los valores a un contador. Como resultado tendremos el conteo requerido. Algunos pensareis --- ¡qué tontería! podría haberlo calculado facilmente con un pequeño script secuencial. De acuerdo, si el documento es pequeño es una opción valida para resolver el problema. Imaginad ahora que en lugar de un documento quieres contar las ocurrencias en un libro, o en la colección de libros de una gran biblioteca. El problema se complica y la solución no es alcanzable si no cambiamos el paradigma de programación y paralelizamos el problema. Eso es lo que hace Hadoop:


Hadoop, y el conjunto de programas anexos, nos ayudan a trabajar de forma paralela. Haciendo uso de HDFS, un sistema de ficheros distribuido que permite alojar grandes cantidades de datos bajo hardware económico. La idea es conseguir potencia a base de unir nodos, equipos de prestaciones normales y económicos. Si un nodo se estropea es facilmente reemplazable por otro. Si necesitamos mas potencia solo necesitaremos añadir nodos al cluster creciendo de forma prácticamente lineal las capacidades disponibles. Interesante, ¿no?

Pero Hadoop y sus aplicaciones anexas no son demasiado user friendly. Si a eso unimos que para el trabajo necesitaremos desplegar los aplicativos en multiples nodos, controlar su estado, etc, la tarea se vuelve mas y mas compleja. No nos olvidemos que nuestro objetivo es procesar la información para obtener datos relevantes no el cluster en si mismo (el cluster es solo la herramienta). Para eso está Ambari: simplifica el despliegue de estos aplicativos, monitoriza su estado y proporciona herramientas para controlar el correcto funcionamiento tanto del cluster como de los trabajos desplegados, todo desde un entorno web muy agradable.

Para instalar Ambari lo mejor es seguir la guía (versión 1.2.2 en el momento de realizar este artículo) que los desarrolladores proporcionan en su web. Yo voy a comentar cómo he desplegado mi cluster Hadoop de pruebas y haré foco de atención en puntos importantes que hay que tener en cuenta para montar correctamente el cluster. Empecemos.

Ambari se despliega sobre REHL5/6, CentOS 5/6 y SLES 11. Importante es que solo admite versión x86_64 (64bits) como sistema operativo. Hace unos meses quise desplegar Ambari sobre equipos antiguos (HP Proliant G3) y me llevé un chasco al verificar con los desarrolladores del producto que al ser plataforma de 32bits no podía hacerlo.  Como lo mio es una prueba de concepto lo he desplegado sobre máquinas virtuales alojadas en mi PC: procesador Intel i7-2600K 3.4GHz (4 cores con HyperThreading) y 16GB de RAM. Pero podría hacerse igualmente sobre máquinas físicas o incluso sobre plataformas en la nube como AWS de Amazon.

Como sistema operativo base para los nodos del cluster he usado CentOS 6.4 minimal. Mi consejo es que, useis la distro que useis (dentro de las permitidas) instaleis una version mínima para reducir los requisitos de paquetes instalados. No os preocupeis porque Ambari, cuando lo necesite, instalará los paquetes que sean necesarios. Configuré 6 nodos con las siguientes características:
  • master-node: El nodo maestro. Donde instalaré el servidor de Ambari y las aplicaciones principales. 4GB de RAM y 2 cores. 7GB para disco de sistema (/) y 20GB para disco de cluster (/cluster)
  • backup-node: El nodo secundario. Donde se instalarán las aplicaciones maestras secundarias. 4GB de RAM y 1 core. 5GB para disco de sistema (/) y 20GB para disco de cluster (/cluster)
  • node02: Nodo cliente. 2GB de RAM y 1 core. 5GB para disco de sistema (/) y 20GB para disco de cluster (/cluster)
  • node03: Nodo cliente. 2GB de RAM y 1 core. 5GB para disco de sistema (/) y 20GB para disco de cluster (/cluster)
  • node04: Nodo cliente. 2GB de RAM y 1 core. 5GB para disco de sistema (/) y 20GB para disco de cluster (/cluster)
  • node05: Nodo cliente. 2GB de RAM y 1 core. 5GB para disco de sistema (/) y 20GB para disco de cluster (/cluster)
Mi consejo es que instaleis primero un CentOS base, casi sin nada, y una vez listo, haciendo uso de la utilidad de clonación de MV de VMWare, crear el resto. El resultado final en la consola de VMWare es el siguiente:



Paso previo a instalar y MUY IMPORTANTE es que los nodos deben verse entre sí. Para ello la resolución de nombres debe funcionar correctamente. Si no tienes un DNS donde dar de alta a los nodos del cluster una solución eficaz es meter la resolución de nombres en cada fichero '/etc/hosts' y asegurar que el hostname de cada nodo corresponde exactamente con dicha resolución:


Si lo anterior no está puesto correctamente fallará la fase de detección de nodos del cluster. Bien, ya tenemos todo listo para empezar. Lanzamos desde la interfaz web de administración de Ambari la configuración del nuevo cluster: establecer nombre, incluir los nombres de los nodos que lo forman (los nombres añadidos en el fichero de hosts). Listo, ahora deberemos seleccionar los aplicativos que queremos desplegar en nuestro cluster Hadoop:


El único que es obligatorio es el sistema de ficheros de cluster HDFS. Mi recomendación es que los añadas todos (no ocupan demasiado espacio y siempre puedes detenerlos después si no vas a hacer uso de ellos). Una vez elegidos los servicios a incluir, deberemos distribuirlos entre los nodos del cluster:


Yo he distribuido los servicios mas o menos para que todos los principales estén en el nodo maestro y backup. Seguramente haya una mejor distribución pero como mi objetivo sobre todo es evaluarlo no me preocupé demasiado en cómo distribuirlos. Ambari si precisa que algún servicio esté en varios nodos ya se preocupa de que así sea. Una vez distribuidos, proseguimos con la instalación.

Esta parte es delicada ya que, según como hayamos distribuido los servicios, Ambari tendrá que instalar unos u otros paquetes en los diferentes nodos del cluster. ¿Cómo hace este trabajo? La forma de interactuar de Ambari con los nodos del cluster usa dos caminos: SSH (si has seguido la guía de instalación oficial habrás tenido que configurar para que nodo maestro pueda acceder mediante este protocolo de forma directa, sin tener que proporcionar password alguna) y ambari-agent. En todos los nodos que formen parte del cluster se instalará el cliente de Ambari (via SSH) y, una vez provisionado, este será el método de comunicación. El cliente no es mas que una customizada adaptación de puppet. El nodo maestro, haciendo uso de los manifiestos (manifest), traslada configuraciones de un nodo del cluster a otro asegurando la coherencia en todo momento.

Como decía, esta parte es delicada ya que puede requerir instalar muchos paquetes en los diferentes nodos. A mi me dio error y revisando los nodos me percaté que no es que hubiera fallado la instalación, es que en varios nodos aun se estaban instalando muchos paquetes habiéndose llegado a una situación de timeout por el trabajo que ello requiere. ambari-agent recibe el manifiesto desde el nodo maestro, empieza a instalar paquetes (que requieren hacer uso de Internet via yum en muchas ocasiones). Mi consejo es que mireis en cada nodo y aseguraos que no hay procesos pendientes. Es facil detectarlo mirando la lista de procesos. Vereis que ambari-agent está ejecutando procesos relacionados con la instalación de paquetes:


Cuando veáis que la actividad en los nodos ha cesado, pulsar el botón de reintento. Debe aparecer una ventana similar a esta mostrando el progreso de instalación de los servicios en los nodos:


Y finalmente, si todo va bien, llegaremos a un estado donde todos los servicios se han desplegado correctamente en los diferentes nodos del cluster:


Entramos ahora en la ventana de dashboard de Ambari:


Esta ventana nos muestra una imagen general de cómo se encuentra nuestro cluster: los servicios activos y gráficas de las principales métricas asociadas al estado de computación: carga, uso de CPU, memoria, etc. Si pulsamos sobre cualquier gráfica, nos abre una ventana que nos permite ver interactivamente el detalle de la misma:


Como puede apreciarse, se ofrecen formas simples, interactivas e intuitivas para conocer el estado de salud de nuestro cluster, monitorizando los diferentes servicios, y ofreciendo información precisa gracias a los agentes de control integrados en el cluster como Ganglia y Nagios. Todo ello de forma cómoda: si necesitas mas potencia basta con añadir nuevos nodos al cluster. Ambari gestionará la provisión automática para integrar los nuevos nodos dentro de los procesos de control y gestión del cluster:






En la pestaña de Jobs podremos revisar el estado de ejecución de los diferentes procesos lanzados en la plataforma:


Como hemos visto, Ambari puede facilitarnos la gestión de nuestro cluster Hadoop. Ahora que tenemos una plataforma adecuada para desplegar nuestros jobs paralelos es el momento de empezar a usarla para procesar esa información que nos ayude a obtener datos significativos y, en definitiva, nos permita tomar mejores decisiones para el desarrollo de nuestra empresa a futuro.

PD: Lectura recomendada: MapReduce Design Patterns (O'Reilly)