Hadoop y Spark

Hadoop

Apache Hadoop es un framework de software que soporta aplicaciones distribuidas. Permite a las aplicaciones trabajar con miles de nodos y petabytes de dtos.

Arquitectura Hadoop

El Hadoop Distributed File System (HDFS) es un sistema de archivos distribuido, escalable y portátil escrito en Java para el framework Hadoop. Cada nodo en una instancia Hadoop típicamente tiene un único nodo de datos; un clúster de datos forma el clúster HDFS.

Spark

Descripción Spark

Spark es un sistema de computación en clúster de propósito general. Puede implementar y ejecutar aplicaciones paralelas en clústeres que van desde un solo nodo hasta miles de nodos distribuidos. Spark fue diseñado originalmente para ejecutar aplicaciones Scala, pero también es compatible con Java, Python y R

Este cluster de Spark correrá bajo el protocolo Yarn de HADOOP. Los trabajos de Spark pueden ejecutarse en YARN en dos modos: modo de clúster y modo de cliente. Comprender la diferencia entre los dos modos es importante para elegir una configuración de asignación de memoria adecuada y para enviar trabajos como se espera.

Los trabajos de Spark constan de dos partes:

  • Ejecutores Spark. Ejecutan las tareas reales.
  • Controlador Spark. Organiza los ejecutores.

Modo Clúster Todo se ejecuta dentro del clúster. Puede iniciar un trabajo desde cualquier equipo y el trabajo continuará ejecutándose incluso si se cierra el equipo desde donde se lanzo el trabajo. En este modo el controlador Spark se encapsula dentro del YARN Application Master.

Modo Cliente El controlador se ejecuta en el equipo cliente, si el equipo cliente se apaga el trabajo falla. El modo cliente es adecuado para trabajos interactivos pero para trabajos de larga ejecución, el modo el clúster es más apropiado.

Funcionamiento Las aplicaciones Spark se ejecutan como conjuntos independientes de procesos en un clúster, coordinados por el objeto SparkContext (Progama controlador).

Siendo más específico, SparkContext para ejecutarse en el clúster puede conectarse a varios tipos de administradores de clúster (el propio Spark , Mesos o Yarn, siendo este último el de nuestra instalación), que asigna recursos entre las aplicaciones. Una vez conectado, Spark adquiere ejecutores en nodos de clúster, que son procesos que ejecutan cálculos y almacenan datos para su aplicación. A continuación, envía su código de aplicación (definido por los archivos JAR o Python pasados a SparkContext) a los ejecutores. Finalmente, SparkContext envía tareas a los ejecutores para ejecutar.

Funcionamiento-spark.png

Instalación Hadoop

Para la instalación de Hadoop hemos seguido el siguiente tutorial: https://www.linode.com/docs/databases/hadoop/how-to-install-and-set-up-hadoop-cluster/

Equipos para la instalación TEST Spark -> 45.79.207.240 (Maestro y Esclavo) cool-ad14 -> 172.104.214.142 (Esclavo)

Paso 1 Creación de /etc/hosts. Debemos añadir a cada /etc/hosts todos las máquinas que participan en el clúster

45.79.207.240 spark
172.104.214.142 node-ad14

Paso 2 Creación del usuario hadoop y clave pública. Debemos crear un usuario con el nombre hadoop en cada máquina.

   User: hadoop
   Pass: passwd

Solo nos faltará crear una clave pública en el maestro y compartilo con el propio maestro y los esclavos.

   Máquina Spark / Usuario hadoop
   ssk-keygen -b 4096
   ssh-copy-id -i $HOME/.ssh/id_rsa.pub hadoop@spark
   ssh-copy-id -i $HOME/.ssh/id_rsa.pub hadoop@node-ad14

Paso 3 En el Master. Dentro de la carpeta /home/hadoop con el usuario hadoop nos descargamos el fichero.tar.gz que contiene hadoop.

https://hadoop.apache.org/
https://archive.apache.org/dist/hadoop/common/hadoop-3.1.2/hadoop-3.1.2.tar.gz
   Descomprimimos   / tar -xvzf hadoop-3.1.2.tar.gz
   Cambio de nombre / mv hadoop-3.2.1 hadoop


Paso 4 Variables de entorno. En el fichero /home/hadoop/.profile añadimos la siguiente línea. Si el fichero no existe hemos de crearlo:

PATH=/home/hadoop/hadoop/bin:/home/hadoop/hadoop/sbin:$PATH

Paso 5 Configuración de JAVA. Si no tenemos java instalado debemos instalarlo

yum install jdk-1.8.0-devel

Una vez instalado debemos conocer la ubicación de la carpeta jre, para saberlo utilizamos el siguiente comando:

   update-alternatives --display java

Una vez obtenemos la ruta de java, hacemos un export de la variable JAVA_HOME en hadoop-env.sh

/home/hadoop/hadoop/etc/hadoop/hadoop-env.sh

export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64/jre


Paso 6 Archivos de configuración. Establecemos el master. /home/hadoop/hadoop/etc/hadoop/core-site.xml

<configuration>
       <property>
           <name>fs.default.name</name>
           <value>hdfs://node-master:9000</value>
       </property>
</configuration>


Establecemos los path para hdfs. /home/hadoop/hadoop/etc/hadoop/hdfs-site.xml

<configuration>
   <property>
           <name>dfs.namenode.name.dir</name>
           <value>/home/hadoop/data/nameNode</value>
   </property>
   <property>
           <name>dfs.datanode.data.dir</name>
           <value>/home/hadoop/data/dataNode</value>
   </property>
   <property>
           <name>dfs.replication</name>
           <value>1</value>
   </property>
</configuration>

La última propiedad dfs.replication, indica cuántas veces se replican los datos en el clúster. Por ejemplo podríamos configurar con 2 para que todos los datos se duplicasen en ambos nodos, NO INGRESAR UN VALOR MÁS ALTO QUE EL NÚMERO DE NODOS ESCLAVOS.


Establecemos Yarn como el framework por defecto para las operaciones de Mapreduce. /home/hadoop/hadoop/etc/hadoop/mapred-site.xml

<configuration>
   <property>
           <name>mapreduce.framework.name</name>
           <value>yarn</value>
   </property>
</configuration>


Configuración Yarn ~/hadoop/etc/hadoop/yarn-site.xml

<configuration>
   <property>
           <name>yarn.acl.enable</name>
           <value>0</value>
   </property>
   <property>
           <name>yarn.resourcemanager.hostname</name>
           <value>node-master</value>
   </property>
   <property>
           <name>yarn.nodemanager.aux-services</name>
           <value>mapreduce_shuffle</value>
   </property>
</configuration>


Configuración de esclavos. En la documentación que hemos leído se utiliza un fichero llamado slaves, pero actualmente se está utilizando un fichero que se llama workers.

Dentro del fichero /home/hadoop/hadoop/etc/hadoop/workers
localhost
node-ad14


Configuración de la asignación memoria. La asignación de memoria puede ser complicada en nodos de RAM baja porque los valores predeterminados no son adecuados para nodos con menos de 8GB de RAM. Vamos a destacar como funciona la asignación de memoria para los trabajos de MapReduce y veremos una configuración para nodos de 2GB de RAM.


Propiedades de la asignación de memoria. Un operación con Yarn tiene dos tipos de procesos:

  • Application Master(AM) Responsable de monitorizar la aplicación y coordinar los ejecutores distribuidos por el clúster.
  • Ejecutores propios para realizar los actuales trabajos.

Ambos tipos de procesos se ejecutan en los nodos esclavos. Cada nodo esclavo ejecuta un demonio NodeManager que es responsable de la creación del contenedor en el nodo. Todo el clúster es administrado por un ResourceManager que programa la asignación de contenedores en todos los nodos esclavos, según los requisitos de capacidad y el cargo actual.

Tenemos cuatro tipos de asignación deben configurarse para el clúster funcione correctamente.

Cuánta memoria se puede asignar para los contenedores YARN en un solo nodo. Este límite debe ser más alto que todos los demás, de lo contrario la asignación de contenedores será rechazada y las aplicaciones fallan. Sin embargo no debe ser la cantidad total de RAM en el Nodo.

yarn.nodemanager.resource.memory-mb

Cuánta memoria puede consumir un contenedor y la asignación de memoria mínima permitida. Un contenedor nunca será más grande que el máximo, o la asignación fallará y siempre se asignará como un múltiplo de la cantidad mínima de RAM.

yarn.scheduler.maximum-allocation-mb
yarn.scheduler.minimum-allocation-mb


Cuánta memoria se le asignará al AplicationMaster. Este es un valor constante que debe ser inferior al de tamaño máximo del contenedor.

yarn.app.mapreduce.am.resource.mb


Cuańta memoria se le asignará a cada mapa.

mapreduce.map.memory.mb
mapreduce.reduce.memory.mb

   

Ejemplo de configuración de 2GB de RAM por NODO.

yarn.nodemanager.resource.memory-mb    1536
yarn.scheduler.maximum-allocation-mb    1536
yarn.scheduler.minimum-allocation-mb    128
yarn.app.mapreduce.am.resource.mb    512
mapreduce.map.memory.mb            256
mapreduce.reduce.memory.mb        256

~/hadoop/etc/hadoop/yarn-site.xml

<property>
       <name>yarn.nodemanager.resource.memory-mb</name>
       <value>1536</value>
</property>
<property>
       <name>yarn.scheduler.maximum-allocation-mb</name>
       <value>1536</value>
</property>
<property>
       <name>yarn.scheduler.minimum-allocation-mb</name>
       <value>128</value>
</property>
<property>
       <name>yarn.nodemanager.vmem-check-enabled</name>
       <value>false</value>
</property>

~/hadoop/etc/hadoop/mapred-site.xml

<property>
       <name>yarn.app.mapreduce.am.resource.mb</name>
       <value>512</value>
</property>
<property>
       <name>mapreduce.map.memory.mb</name>
       <value>256</value>
</property>
<property>
       <name>mapreduce.reduce.memory.mb</name>
       <value>256</value>
</property>

Paso 7

Replicación de los binarios de hadoop y los archivos de configuración. Pasamos los binarios y las configuración que hicimos anteriormente en el maestro hacia los esclavos asignados.

Paso 8 Formatear HDFS. HDFS necesita ser formateado como cualquier clásico sistema de ficheros. En no nodo maestro ejecutar el siguiente comando:

   /home/hadoop/hadoop/bin/hdfs namenode -format

Una vez termina hadoop está listo para iniciarse.

Paso 9 y último Antes de levantar Hadoop vamos a securizar los puertos de escucha controlando las conexiones desde el iptables tanto del nodo-maestro como de los nodos-esclavos.

Lista de puertos a controlar en el< nodo maestro

9000 - 9684 -9866 - 9867 - 9868 - 9870
8040 - 8042 - 8088 - 8030 - 8031 - 8033 
40773 - 36550 - 27017

Preparamos el firewall y levantamos.

Arranque de Hadoop

Esta sección explicará cómo iniciar HDFS en NameNode y DataNodes, y controlará que todo funcione correctamente e interactúe con los datos HDFS.

Inicio y parada de HDFS En el nodo maestro lanzamos con el usuario hadoop:

/home/hadoop/hadoop/sbin/start-dfs.sh

Una vez finalizado la ejecución comprobamos los procesos java con el comando jps, tanto en el nodo maestro como en los esclavos, nos tiene que aparecer algo así:

NODO MAESTRO

21922 Jps
21603 NameNode
21787 SecondaryNameNode

NODO ESCLAVO

19728 DataNode
19819 Jps

Si queremos ver un reporte de los nodos conectados y del clúster utilizamos el comando

/home/hadoop/hadoop/bin/hdfs dfsadmin -report

Para parar el funcionamiento de hadoop:

/home/hadoop/hadoop/sbin/stop-dfs.sh

Inicio y parada de Yarn En el nodo maestro lanzamos con el usuario hadoop:

/home/hadoop/hadoop/sbin/start-yarn.sh


Para comprobar que los nodos están trabajando con yarn

/home/hadoop/hadoop/bin/yarn node -list

Plataforma web de yarn http://spark:8080

Instalación de Spark

Para la instalació de Apache Spark, simplemente necesitamos realizar la descarga de los ficheros de binarios y descomprimirlos, y clonar el repositorio para el conector con Cassandra.

Nos descargamos el tar de ficheros binarios de Apache Spark del siguiente enlace: http://apache.rediris.es/spark/spark-<version>/spark-<version>-bin-hadoop2.7.tgz P.e:

  1. cd /install
  2. wget http://apache.rediris.es/spark/spark-2.3.0/spark-2.3.0-bin-hadoop2.7.tgz

Ya solo debemos descomprimir el archivo en /usr/local (o en otra ruta si fuera mas pertinente):

  1. cd /usr/local
  2. tar -zxf /install/spark-2.3.0-bin-hadoop2.7.tgz

Hacemos un clone del repositorio de git del conector de Cassandra:

  1. git clone https://github.com/datastax/spark-cassandra-connector

Integración de Spark con Hadoop

Para la comunicación con el administrador de recursos YARN, Spark debe conocer la configuración de Hadoop. Esto se hace a través de la variable de entorno HADOOP_CONF_DIR

Editamos /home/hadoop/.profile

export HADOOP_CONF_DIR=/home/hadoop/hadoop/etc/hadoop
export SPARK_HOME=/usr/local/spark
export LD_LIBRARY_PATH=/home/hadoop/hadoop/lib/native:$LD_LIBRARY_PATH

Reiniciamos la sesión.

Renombramos el archivo spark-defaults.conf.template ha spark-defaults.conf Este archivo se encuentra en la ubicación de Spark, normalmente en:

/usr/local/spark

ASIGNACIÓN DE MEMORIA EN SPARK Como le hemos pasado la ruta de la configuración de Hadoop, Spark cogerá la configuración de memoria para contenedores y a se la aplicará, aún así hemos de configurar algunas asignaciones de memoria en spark y otras cosas, hago un breve resumen más abajo con las variables necesarias.

Editamos spark-defaults.conf, le añadimos la siguiente líneas al final del archivo:

  1. Para qué spark sepa que ha de funcionar con Yarn.
spark.master yarn
  1. Cantidad predeterminada de memoria asignada a Spark.driver en el clúster.
spark.driver.memory     512m
spark.yarn.am.memory    512m
spark.executor.memory   896m
  1. Monitorización
spark.eventLog.enabled false
spark.eventLog.dir hdfs://spark:9000/spark-logs
spark.history.provider            org.apache.spark.deploy.history.FsHistoryProvider
spark.history.fs.logDirectory     hdfs://spark:9000/spark-logs
spark.history.fs.update.interval  10s
spark.history.ui.port             18080

Comandos Docker

Docker

 
  1. Obtener información
  • docker info
  • docker network info
  • docker volume info
  1. Ver número de procesos levantados (contenedores levantados). Muy útil para encontrar de manera rápida el identificador del contenedor
  • docker ps
  1. Entra en un terminal del contenedor
  • docker exec it Id_container sh
  1. Entra en el log del contendor
  • docker attach Id_container
  1. Ver archivos de configuración
  • docker inspect Id_container
  1. Para borrar
  • docker system prune -a
  • docker image prune
  • docker container prune
  • docker volume prune
  • docker network prune
  1. Para listar
  • docker system ls
  • docker image ls
  • docker volume ls
  • docker network ls
  • docker container ls
  1. Descargar y levantar una imagen
  • docker run -d –name graphite –restart=always -p 8080:80 -p 2003-2004:2003-2004 -p 2023-2024:2023-2024 -p 8125:8125/udp -p 8126:8126 graphiteapp/graphite-statsd
  1. Parada y arrancada de un contenedor
  • docker stop name or id // docker start name or id
  1. Levantar una imagen descargada
  • docker build -t hopsoft/docker-graphite-statsd ./docker-graphite-statsd/
  1. Levantar imagen con compose
  • Debe lanzarse en el directorio donde se encuentre el archivo docker-compose.yml
    • docker-compose up
  1. Logs de los containers
  • docker logs name_container

Virtualización OpenVZ

El OpenVZ es un proyecto de virtualización basado en containers. OpenVz crea containers (también llamados Ves o VPSs) que son entidades independientes y que pueden poseer su propia IP , recursos, usuarios, etc… es decir es en si mismo un sistema independiente. El proyecto es la base de la versión comercial Parallels Virtuozo. Para más info: wiki.openvz.org

Instalación CentOs

La instalación del Openvz se puede realizar mediante repositorio:
cd /etc/yum.repos.d wget http.//download.openvz.org/openvz.repo rpm –import http://download.openvz.org/RPM-GPG-Key-OpenVZ

Una instalado el repositorio ya se puede instalar mediante yum el kernel necesario para ejecutar el openvz

  • yum install ovzkernel

Configuración

Configurar parametros del sistema operativo: (editar fichero sysctl.conf)
# On Hardware Node we generally need packet
forwarding enabled and proxy arp disabled
net.ipv4.ip_forward = 1
net.ipv6.conf.default.forwarding = 1
net.ipv6.conf.all.forwarding = 1
net.ipv4.conf.default.proxy_arp = 0
# Enables source route verification net.ipv4.conf.all.rp_filter = 1
# Enables the magic-sysrq key kernel.sysrq = 1
# We do not want all our interfaces to send redirects net.ipv4.conf.default.send_redirects = 1 net.ipv4.conf.all.send_redirects = 0

Y por último desactivar el selinux, en el fichero /etc/sysconfig/selinux realizar el siguiente cambio
SELINUX=disabled Reiniciar la máquina y cargar la opción con el ovzkernel.

Creación máquinas

Para la gestión de los containers es necesaria la instalación del vzctl
yum install vzctl vzquota

Arrancar el servicio
/sbin/service vz start

Antes de la creación de cualquier container tenemos que bajarnos los templates o crear uno especifico, para comenzar nos bajaremos un template ya creado.. Podemos bajar templates ya creados desde la siguiente dirección: [1]

Una vez ya tengamos los templates crearemos el container usando nuestro template:
vzctl create 1001 –ostemplate nombre_template

configurar los parametros del container
vzctl set –ipadd ipaddr –nameserver nameserverIP –hostname hostname –save

En este punto ya deberíamos ser capaces de arrancar la máquina
vzctl start vpsid

Para consultar los recursos que esta consumiendo
vzcalc -v vpsid

Para indicar que el container se inicie en el arranque:
vzctl set vpsid –onboot yes –save

Podemos realizar cambios del resto de parametros de la configuración de igual manera:
vzctl set vpsid –vmguarpages $((256 * 256)) –save

Toda la configuración se almacena en /etc/vz/conf/container_id.conf , así que ante grandes cambios se puede modificar directamente el fichero de configuración y el comando vzcfgvalidate para validar si el fichero de configuración es correcto.

Uso de Containers

Si en un momento dado necesitamos entrar en la máquina, lo haremos de la siguiente manera:
vzctl enter vpid

De esta forma entraremos directamente en la máquina como usuario root y sin que nos pida el password, realizaremos el trabajo que tengamos que hacer dentro de la máquina y saldremos de esta con un simple exit. Si lo que queremos es resetear el password, igual que con los cambios de configuración usaremos el vzctl
vzctl set vpsid –userpasswd user:passwd

Por último, si no queremos entrar,si no que simplemente queremos ejecutar un comando dentro de la maquina:
vzctl exec vpsid apt-get upgrade

Borrado de Containers

La última gestión que podemos realizar sobre el container es la eliminación del container, cuando se realiza no pide confirmación y elimina el container y todo el contenido, así que mejor pensárselo dos veces antes de dar al enter. Para eliminar un container lo que tenemos que hacer es llamar a vzctl con el parámetro destroy y el id del container.
vzctl destroy veid