¿Por qué utilizar tecnologías como Hadoop o Spark?
Para no mí no es fácil responder a esta pregunta, ya que realmente estoy empezando ahora a conocer todas estas tecnologías. Voy a intentar hacer una aproximación a mi interpretación, aunque quizás dentro de un tiempo, cuando conozca mejor todo esto, sea capaz de hacer una lectura quizás bastante diferente. Voy a ello.
Si tenemos un problema de cálculo asociado a datos, podemos resolverlo con un ordenador. Eso está claro. Si nuestro problema crece, ya sea en la complejidad del cálculo y/o en el volumen de datos, el tiempo de resolución también aumentará, así que llegará un momento, en el que simplemente sustituiremos dicho ordenador por otro más grande, y resuelto. Esta forma de proceder es muy sencilla, más hardware y listo. Sin embargo, ¿qué podemos hacer si llegamos a un punto de inflexión en el que no podemos acceder a un ordenador lo suficientemente grande (porque no existe, o porque su coste es excesivo)? Aquí es donde las tecnologías como Hadoop y Spark nos pueden ayudar.
Hadoop nos va a ofrecer tener un sistema de ficheros distribuido. De este modo, podemos montar una red de 100 ordenadores con almacenamiento local SSD, y configurar hadoop para que tenga un coeficiente de réplica para que cada dato esté copiado/sincronizado en al menos 10 ordenadores.
Esto lo que nos va a permitir es paralelizar, dividir nuestro trabajo en tareas, cada una de las cuales se pueda realizar en un ordenador de nuestro Cluster. Pero lo más importante, es que nos va a permitir que se realice en un ordenador que ya tenga una copia de los datos en local, lo cual va a acelerar mucho más todo el proceso, ya que los ordenadores no tendrán que ir a buscar el dato y traerlo a través de la red, porque ya lo tienen, y en disco rápido.
Claro, con Hadoop, el problema es que la programación (por lo que me han contado, que yo no lo he vivido en mis propias carnes) es un poco infierno, pegándose con código Java para hacer Map Reduce, etc. Aquí es donde llega Spark, que aunque su lenguaje más natural sería Scala, también permite programar en R y en Python, lo que nos da la potencia de Hadoop y la facilidad y potencia de programación de Python y R, para paralelizar código, y para programar con rapidez tanto algoritmos de Ciencia de Datos como incluso realizar las propias visualizaciones desde un simple Jupyter Notebook con un Kernel de PySpark o de sparkr. Y esto mola. Mola y mucho. Es potente, y además fácil.
Pero ¿Qué son todas estas cosas: Hadoop, Hive, Spark,...?
Si, esto también es un poco lío al principio. Muchas palabras nuevas. Vamos a intentar hacer un breve resumen, quizás no muy fiel, pero que transmita un poco el concepto.
- Hadoop ofrece un sistema de archivos distribuido entre varios Nodos. Divide los ficheros en bloques grandes (por defecto 128MB) que se almacenan duplicados según el coeficiente de réplica que tengamos configurado (por defecto 3, por lo tanto, al menos 3 Nodos tendrán una copia local de cada bloque de datos).
- MapReduce funciona sobre Hadoop/HDFS y nos va a permitir ejecutar grandes conjuntos de datos en paralelo, sobre los Nodos que tengan localmente los datos que necesita de HDFS.
- YARN gestiona los recursos de nuestro Cluster, como RAM y CPU.
- Hive proporciona una capa de abstracción en formato SQL para poder acceder a los datos de HDFS como si fuera una base de datos relacional. Sus consultas SQL son transformadas a Jobs de Map Reduce para su ejecución en paralelo, permitiendo trabajar con grandes volúmenes de información.
Y dicho esto, vamos al lío.
Descripción del escenario de partida
Tenemos las Raspberry con Raspbian recién instalado utilizando PINN, SSH está habilitado, la password por defecto ha sido cambiada, Auto-Login ha sido deshabilitado, la memoria para la GPU ha sido configurada a 32MB, el idioma del teclado ha sido configurado, la configuración de red (dirección IP, DNS y Gateway) del interfaz eth0 ha sido configurada, se tiene acceso a Internet, el hostname ha sido configurado (ej: node01, node02, etc), java ya está instalado (ej: java versión 1.8.0_65), vim ya está instalado (sudo apt-get install vim).
Lo primero que vamos a hacer es crear un usuario hduser para Hadoop, MapReduce y YARN en todas las Raspberry. Utilizaremos el mismo usuario para las tres cosas.
Para ello nos conectaremos a la Raspberry. Crearemos un grupo denominado hadoop, crearemos un usuario denominado hduser estableciéndole como grupo primario hadoop (el que acabamos de crear), y concederemos privilegios de sudo al usuario hduser (a través de la pertenencia al grupo sudo). Esto lo realizaremos con los siguientes comandos:
sudo addgroup hadoop sudo adduser --ingroup hadoop hduser sudo adduser hduser sudo |
A continuación se muestra la salida de ejecución.
Modificaremos el fichero /etc/hosts en todas las Raspberry para asegurarnos que resuelven correctamente los nombres de todos los nodos del Cluster. Para ello nos aseguraremos de que están presentes las siguientes entradas en /etc/hosts.
192.168.1.190 node01 192.168.1.191 node02 192.168.1.192 node03 |
También vamos a aumentar el tamaño del fichero de swap a 2GB en todas las Raspberry (la versión de Raspbian que tenemos, viene con 1GB de SWAP). Para ello ejecutaremos los siguientes comandos en cada una de las Raspberry.
sudo su -c 'echo "CONF_SWAPSIZE=2048" > /etc/dphys-swapfile' sudo dphys-swapfile setup sudo dphys-swapfile swapon |
Lo siguiente que vamos a hacer es generar una clave RSA sin contraseña para el acceso SSH en la primera de las Raspberry (node01), y la vamos a añadir como clave autorizada de confianza en la propia Raspberry para el usuario hduser. Esto nos permitirá poder conectarnos a través de SSH localmente a la propia Raspberry, sin tener que introducir credenciales, que es algo que necesitaremos en varias situaciones, por ejemplo, por los scripts start-dfs.sh y start-yarn.sh para arranchar Hadoop y YARN, pues en caso contrario se solicitará la contraseña del usuario hduser.
mkdir ~/.ssh ssh-keygen -t rsa -P "" cat ~/.ssh/id_rsa.pub > ~/.ssh/authorized_keys |
Copiaremos la información de las claves RSA, desde node01 al resto de nodos. Esto lo podremos hacer con un comando como el siguiente para cada nodo. Una vez realizado, podremos conectarnos por ssh entre los nodos, sin que se solicite contraseña, así como también realizar copia de ficheros con scp, ejecutar comandos remotos, etc.
scp /home/hduser/* node02:/home/hduser/.ssh |
Instalación de Hadoop en Single Node (incluye YARN y MapReduce)
Para comenzar, vamos a crear un Cluster de un único Nodo, por lo tanto, tendremos un NameNode y un DataNode, ambos roles sobre la misma Raspberry.
Nos conectaremos por SSH a nuestra raspberry con el usuario hduser. Descargaremos el binario de la versión de Hadoop que deseamos instalar, en nuestro caso Hadoop 2.7.6, lo descomprimiremos en /opt, lo renombraremos como /opt/hadoop, y cambiaremos su propietario. Esto lo realizaremos con los siguientes comandos:
cd /opt sudo wget http://apache.rediris.es/hadoop/common/hadoop-2.7.6/hadoop-2.7.6.tar.gz sudo tar -xvzf hadoop-2.7.6.tar.gz sudo mv hadoop-2.7.6 hadoop sudo chown -R hduser:hadoop hadoop |
Ahora vamos a establecer varias variables de entorno para el usuario hduser. Para ello, volveremos al directorio home del usuario hduser, y editaremos el fichero .bashrc añadiendo al final del mismo las siguientes líneas.
export JAVA_HOME=$(readlink -f /usr/bin/java | sed "s:bin/java::") export HADOOP_HOME=/opt/hadoop export HADOOP_CONF_DIR=$HADOOP_HOME/etc/hadoop export HADOOP_INSTALL=$HADOOP_HOME export YARN_HOME=$HADOOP_HOME export PATH=$PATH:$HADOOP_INSTALL/bin:$HADOOP_INSTALL/sbin export HADOOP_USER_CLASSPATH_FIRST=true |
A continuación vamos a modificar varios ficheros de configuración de hadoop. Estos ficheros se encuentran en la ruta /opt/hadoop/etc/hadoop.
En particular, los ficheros que vamos a modificar son los siguientes:
- /opt/hadoop/etc/hadoop/hadoop-env.sh
- /opt/hadoop/etc/hadoop/core-site.xml
- /opt/hadoop/etc/hadoop/hdfs-site.xml
- /opt/hadoop/etc/hadoop/yarn-site.xml
- /opt/hadoop/etc/hadoop/mapred-site.xml
- /opt/hadoop/etc/hadoop/slaves
- /opt/hadoop/etc/hadoop/masters
El primer fichero que vamos a modificar es hadoop-env.sh en el cual vamos a modificar sólo dos líneas, la export JAVA_HOME y la export HADOOP_HEAPSIZE (por defecto son 1000MB de heap por demonio, y lo bajaremos a 256MB, dada la reducida memoria de la Raspberry), dejándolas tal y como se ve en el siguiente ejemplo.
export JAVA_HOME=$(readlink -f /usr/bin/java | sed "s:bin/java::") export HADOOP_HEAPSIZE=256 |
Ahora modificaremos el fichero core-site.xml básicamente añadiendo contenido entre las etiquetas configuration (estarán vacías), dejándolo tal y como se ve en el siguiente ejemplo.
<configuration> <property> <name>hadoop.tmp.dir</name> <value>/hdfs/tmp</value> </property> <property> <name>fs.default.name</name> <value>hdfs://node01:54310</value> </property> </configuration> |
Seguidamente modificaremos el fichero hdfs-site.xml básicamente para añadir la configuración dfs.replication asignándola al valor 1 (más adelante, cuando tengamos varios nodos, la estableceremos a un valor superior), dejándolo tal y como se ve en el siguiente ejemplo (por defecto, nos encontraremos la etiqueta configuration vacía).
<configuration> <property> <name>dfs.replication</name> <value>1</value> </property> </configuration> |
Ahora modificaremos el fichero yarn-site.xml básicamente añadiendo contenido entre las etiquetas configuration (estarán vacías), dejándolo tal y como se ve en el siguiente ejemplo. Para más detalles ver https://hadoop.apache.org/docs/r2.7.6/hadoop-yarn/hadoop-yarn-common/yarn-default.xml
<configuration> <property> <name>yarn.resourcemanager.hostname</name> <value>node01</value> </property> <property> <name>yarn.nodemanager.resource.memory-mb</name> <value>4096</value> </property> <property> <name>yarn.nodemanager.resource.cpu-vcores</name> <value>4</value> </property> <property> <name>yarn.resourcemanager.bind-host</name> <value>0.0.0.0</value> </property> <property> <name>yarn.nodemanager.aux-services</name> <value>mapreduce_shuffle</value> </property> <property> <name>yarn.nodemanager.aux-services.mapreduce.shuffle.class</name> <value>org.apache.hadoop.mapred.ShuffleHandler</value> </property> </configuration> |
A continuación copiaremos el fichero plantilla de MapRecuce (cp mapred-site.xml.template mapred-site.xml), y seguidamente modificaremos el fichero mapred-site.xml básicamente añadiendo contenido entre las etiquetas configuration (estarán vacías), dejándolo tal y como se ve en el siguiente ejemplo. La primera propiedad indica que queremos utilizar YARN, y las siguientes son más específicas para Raspberry, con el objetivo de ajustar el uso de memoria.
<configuration> <property> <name>mapreduce.framework.name</name> <value>yarn</value> </property> <property> <name>mapreduce.map.memory.mb</name> <value>256</value> </property> <property> <name>mapreduce.map.java.opts</name> <value>-Xmx210m</value> </property> <property> <name>mapreduce.reduce.memory.mb</name> <value>256</value> </property> <property> <name>mapreduce.reduce.java.opts</name> <value>-Xmx210m</value> </property> <property> <name>yarn.app.mapreduce.am.resource.mb</name> <value>256</value> </property> </configuration> |
Editaremos el fichero slaves especificando en su interior el nombre de nuestra raspberry, tal y como se muestra en el siguiente ejemplo.
Editaremos el fichero masters especificando en su interior el nombre de nuestra raspberry, tal y como se muestra en el siguiente ejemplo.
Llegados a este punto, reiniciaremos nuestra raspberry (sudo reboot), tras lo cual nos volveremos a conectar por SSH utilizando el usuario hduser, crearemos el directorio para hdfs, y lo formatearemos. Esto lo haremos con los siguientes comandos.
sudo mkdir -p /hdfs/tmp sudo chown hduser:hadoop /hdfs/tmp sudo chmod 750 /hdfs/tmp hdfs namenode -format |
A continuación, arrancaremos manualmente Hadoop (hdfs) y YARN (resource scheduler).
start-dfs.sh start-yarn.sh |
Otra forma alternativa de arrancar HDFS y YARN sería:
hdfs namenode > name_node.log 2>&1 & hdfs datanode > data_node.log 2>&1 & yarn resourcemanager > resource_manager.txt 2>&1 & yarn nodemanager > node_manager.txt 2>&1 & |
La siguiente pantalla capturada muestra la salida de ejecución.
Con esto ya habríamos creado un Cluster de Hadoop con un único nodo. Ahora, vamos a probarlo.
Probando Hadoop en Single Node
Comprobaremos que los demonios de Hadoop y YARN están levantados, ejecutando el comando jps, tal y como se muestra en la siguiente pantalla capturada. Los números de la izquierda son el PID.
Una prueba típica es calcular el número pi con MapReduce, que podemos realizar ejecutando la siguiente línea de código.
hadoop jar /opt/hadoop/share/hadoop/mapreduce/hadoop-mapreduce-examples-2.7.6.jar pi 16 1000 |
La siguiente prueba que vamos a hacer es copiar un fichero al HDFS, y ejecutar un programa mapreduce para contar las palabras de dicho fichero. Descargaremos el fichero de salida, y lo revisaremos en nuestro portátil. Esto lo haremos con los siguientes comandos.
hdfs dfs -copyFromLocal /opt/hadoop/LICENSE.txt /license.txt hadoop jar /opt/hadoop/share/hadoop/mapreduce/hadoop-mapreduce-examples-2.7.6.jar wordcount /license.txt /license-out.txt hdfs dfs -copyToLocal /license-out.txt more ~/license-out.txt/part-r-00000 |
Seguidamente accederemos a la URL de Hadoop Web UI, para comprobar que está disponible, en http://192.168.1.190:50070
También accederemos a la URL de YARN Web UI, para comprobar que está disponible, en http://192.168.1.190:8088
Añadir Nodos al Cluster de Hadoop
Nos conectaremos por SSH a nuestra raspberry con el usuario hduser. Descargaremos el binario de la versión de Hadoop que deseamos instalar, en nuestro caso Hadoop 2.7.6, lo descomprimiremos en /opt, lo renombraremos como /opt/hadoop, y cambiaremos su propietario. Esto lo realizaremos con los siguientes comandos:
cd /opt sudo wget http://apache.rediris.es/hadoop/common/hadoop-2.7.6/hadoop-2.7.6.tar.gz sudo tar -xvzf hadoop-2.7.6.tar.gz sudo mv hadoop-2.7.6 hadoop sudo chown -R hduser:hadoop hadoop |
Ahora vamos a establecer varias variables de entorno para el usuario hduser. Para ello, volveremos al directorio home del usuario hduser, y editaremos el fichero .bashrc añadiendo al final del mismo las siguientes líneas.
export JAVA_HOME=$(readlink -f /usr/bin/java | sed "s:bin/java::") export HADOOP_HOME=/opt/hadoop export HADOOP_INSTALL=$HADOOP_HOME export YARN_HOME=$HADOOP_HOME export PATH=$PATH:$HADOOP_INSTALL/bin:$HADOOP_INSTALL/sbin export HADOOP_USER_CLASSPATH_FIRST=true |
Copiaremos desde node01 los ficheros de configuración que hemos personalizado, al resto de nodos del Cluster, para lo cual podemos ejecutar un conjunto de comandos como los siguientes para cada nodo.
scp core-site.xml node02:/opt/hadoop/etc/hadoop/core-site.xml scp hdfs-site.xml node02:/opt/hadoop/etc/hadoop/hdfs-site.xml scp yarn-site.xml node02:/opt/hadoop/etc/hadoop/yarn-site.xml scp mapred-site.xml node02:/opt/hadoop/etc/hadoop/mapred-site.xml scp slaves node02:/opt/hadoop/etc/hadoop/slaves scp masters node02:/opt/hadoop/etc/hadoop/masters |
Crearemos el directorio para hdfs en el resto de Raspberrys. Esto lo haremos con los siguientes comandos.
sudo mkdir -p /hdfs/tmp sudo chown hduser:hadoop /hdfs/tmp sudo chmod 750 /hdfs/tmp |
Conectados a node01 por SSH, reiniciaremos la Raspberry y borraremos el directorio de hdfs (luego lo vamos a formatear), para lo cual ejecutaremos los siguientes comandos.
sudo reboot sudo rm -rf /hdfs/tmp/* |
Editaremos el fichero de configuración hdfs-site.xml en cada uno de los nodos (vi /opt/hadoop/etc/hadoop/hdfs-site.xml) y lo modificaremos dejando el ratio de sincronización que deseamos. En el siguiente ejemplo se ha dejado en 2, para que cada dato se copia al menos a 2 nodos.
<configuration> <property> <name>dfs.replication</name> <value>2</value> </property> </configuration> |
Editaremos el fichero de configuración slaves en node01 (vi /opt/hadoop/etc/hadoop/slaves), e introduciremos el nombre de todos los nodos del Cluster. El siguiente ejemplo sería para un Cluster formado por sólo dos nodos.
Editaremos el fichero de configuración slaves en cada uno de los nodos excepto en node01 (vi /opt/hadoop/etc/hadoop/slaves), dejándolo configurado con el nombre del nodo local (node01 seguirá almacenando el nombre de todos los nodos). Por ejemplo, en node02 el valor será el siguiente.
Conectados a node01 por SSH, formatearemos hdfs, arrancaremos manualmente Hadoop (hdfs) y YARN (resource scheduler). Para ello ejecutaremos los siguientes comandos. Téngase en cuenta, que con ejecutarlos sólo una vez en node01, se arrancarán los servicios en todos los nodos del Cluster.
hdfs namenode -format start-dfs.sh start-yarn.sh |
Llegados a este punto, podríamos repetir las pruebas que realizamos anteriormente con el Cluster de un único nodo, y así comprobar el funcionamiento. Un detalle relevante, es que con el comando jps podremos ver como node02 sólo es un nodo de datos, teniendo menos servicios levantados que node01, que seguirá teniendo levantados los mismos servicios que cuando teníamos un Cluster Hadoop de un único nodo. A continuación se muestra la salida de ejecución del comando jps en node02.
Instalación de Hive 2.1.1
A continuación vamos a instalar Hive en su versión 2.1.1 sobre node01. Hive sólo necesita ser instalado en el nodo maestro (master node). Para simplificar la instalación, crearemos el metastore de Hive utilizando una base de datos Derby (es decir, ficheros en el filesystem local). Este es el método por defecto, aunque lo recomedable es utilizar una base de datos relacional como MySQL para evitar problemas de corrupción, permitir múltiples sesiones de Hive, etc. No obstante, para comenzar, y desde un punto de vista didáctico, con Derby sería suficiente.
El primer paso, será descargar y descomprimir hive, dejándolo con los permisos correctos, para que tenga acceso el usuario hduser.
cd /opt wget http://apache.rediris.es/hive/hive-2.1.1/apache-hive-2.1.1-bin.tar.gz sudo tar -xzvf apache-hive-2.1.1-bin.tar.gz sudo mv apache-hive-2.1.1-bin hive sudo chown -R hduser:hadoop /opt/hive |
Modificaremos el fichero .bashrc del usuario hduser en node01 (vi /home/hduser/.bashrc) para añadir hive al path, así como establecer la variable de entorno HIVE_HOME. En nuestro caso de ejemplo, añadiremos las siguientes dos líneas.
export HIVE_HOME=/opt/hive export PATH=$PATH:$HIVE_HOME/bin |
Realizado esto, conectados por SSH a node01, pararemos los servicios de YARN y Hadoop, reiniciaremos, y volveremos a arancar Hadoop y YARN. A continuación se muestran los comandos que utilizaríamos.
stop-yarn.sh stop-dfs.sh sudo reboot start-dfs.sh start-yarn.sh |
Ahora vamos a inicializar Hive. Veremos que esto crea un directorio metastore_db, donde se almacenará el metastore de Hive. Una vez inicializado, accederemos a la línea de comandos de hive, utilizando el comando hive. Estas tareas las realizaremos con los siguientes comandos.
cd ~ schematool -initSchema -dbType derby ls -l hive |
A continuación se muestra un ejemplo de salida de ejecución.
Instalación de Spark 2.1
El primer paso, será descargar y descomprimir spark, dejándolo con los permisos correctos, para que tenga acceso el usuario hduser. Esto lo haremos en todos los nodos. Los comandos a ejecutar serían similares a los siguientes.
cd /opt wget https://archive.apache.org/dist/spark/spark-2.1.0/spark-2.1.0-bin-hadoop2.7.tgz sudo tar -xzvf spark-2.1.0-bin-hadoop2.7.tgz sudo mv spark-2.1.0-bin-hadoop2.7 spark sudo chown -R hduser:hadoop /opt/spark |
Modificaremos el fichero .bashrc del usuario hduser en todas las Raspberry (vi /home/hduser/.bashrc) para añadir Spark al path, así como establecer las variables de entorno de Spark. En nuestro caso de ejemplo, añadiremos las siguientes dos líneas.
export SPARK_HOME=/opt/spark export SPARK_CONF_DIR=/opt/spark/conf export SPARK_MASTER_HOST=node01 export PATH=$PATH:$SPARK_HOME/bin:$SPARK_HOME/sbi |
Conectados por SSH a node01, pararemos los servicios de YARN y Hadoop, y crearemos el fichero de configuración de los Workers de Spark, desde la plantilla.
stop-yarn.sh stop-dfs.sh cd /opt/spark/conf cp slaves.template slaves |
Editaremos el fichero de configuración de los Workers de Spark (vi /opt/spark/conf/slaves), especificando los nombres de todos los nodos de nuestros Cluster. El siguiente ejemplo sería para un Cluster con dos nodos.
Crearemos en todas las Raspberry el fichero de configuración spark-defaults.conf como una copia del fichero que incluye spark como plantilla (spark-defaults.conf.template), y lo editaremos.
cp spark-defaults.conf.template spark-defaults.conf vi spark-defaults.conf |
Estableceremos los valores de spark.executor.memory y spark.driver.memory a 512 MB, para de este modo intentar ajustar la configuración de Spark al hardware limitado de nuestras Raspberry. Además, configuraremos Spark para que utilice una copia de las librerías de Spark (jars) directamente de HDFS, así evitar el retraso que implica tener que copiarlo del sistema de ficheros local de Master Node cada vez que ejecutar pyspark, spark-shell, spark-submit, spark-sql, etc. Es decir, en cierto modo, tenerlo cacheado.
Copiaremos manualmente los JARs, para lo cual ejecutaremos los siguientes comandos:
jar cv0f ~/spark-libs.jar -C /opt/spark/jars/ . hdfs dfs -mkdir /spark-libs hdfs dfs -put ~/spark-libs.jar /spark-libs/ |
Modificaremos el fichero de configuración spark-env.sh para establecer la memoria del worker y daemon conforme al limitado hardware de la Raspberry (SPARK_WORKER_MEMORY y SPARK_DAEMON_MEMORY).
Conectados por SSH a node01, arrancaremos los servicios de YARN, Hadoop, y Spark (tanto Maestro como Workers), y comprobaremos que los servicios están levantados.
start-dfs.sh start-yarn.sh start-master.sh start-slaves.sh jps |
A continuación se muestra cómo sería la salida de ejecución en node01.
Seguidamente ejecutaremos el commando jps en node02 para comprobar qué servicios tiene levantados. Como podemos ver, ahora también aparece levantado el servicio de Worker correspondiente a Spark.
Accederemos al Spark Master Web UI, disponible en el Puerto 8080 del nodo Master (en nuestro caso node01), para lo cual utilizaremos la URL http://192.168.1.190:8080/
Accederemos a la Shell de Spark ejecutando el comando spark-shell --master yarn. Esto tardará un rato.
Despedida y Cierre
Hasta aquí llega el presente artículo, en el cual hemos intentado ver la instalación y configuración básica de Hadoop, Hive, y Spark, utilizando como campo un conjunto de Raspberry. Aprovecho para compartir algunos enlaces de interés, para quien desee ampliar más información.
Si quieres seguir ampliando un Cluster de Raspberry puedes:
Poco más por hoy. Como siempre, confío que la lectura resulte de interés.