Category Archives: HPC

Monitorizar GlusterFS

Ayer vimos como construir un cluster de almacenamiento distribuido con GlusterFS y CentOS. Hoy vamos a ver las herramientas que ofrece el propio Gluster para monitorizar el rendimiento.

Preparando el volumen

Antes de poder consultar el rendimiento tenemos que habilitarlo en la definición del volumen. Para ello hacemos.

# gluster volume profile testvol start

Ahora veremos la siguiente información a la salida del estado del volumen.

# gluster volume info

Volume Name: testvol
Type: Stripe
Volume ID: f922da05-737d-4fb5-83cc-e50d6782b90c
Status: Started
Number of Bricks: 1 x 4 = 4
Transport-type: tcp
Bricks:
Brick1: server1.example.com:/data
Brick2: server2.example.com:/data
Brick3: server3.example.com:/data
Brick4: server4.example.com:/data
Options Reconfigured:
diagnostics.count-fop-hits: on
diagnostics.latency-measurement: on
auth.allow: 192.168.1.*

Mostrar la entrada/salida

# gluster volume profile testvol info
Brick: server1.example.com:/data
--------------------------------
Cumulative Stats:
   Block Size:               4096b+ 
 No. of Reads:                    0 
No. of Writes:                    4 
 %-latency   Avg-latency   Min-Latency   Max-Latency   No. of calls         Fop
 ---------   -----------   -----------   -----------   ------------        ----
      0.00       0.00 us       0.00 us       0.00 us              1        STAT
      0.00       0.00 us       0.00 us       0.00 us              2      FORGET
      0.00       0.00 us       0.00 us       0.00 us              3     RELEASE
      0.00       0.00 us       0.00 us       0.00 us             24  RELEASEDIR
      0.85     250.00 us     250.00 us     250.00 us              1     SETATTR
      1.50     440.00 us     440.00 us     440.00 us              1       FSTAT
      1.51     222.00 us     200.00 us     244.00 us              2       FLUSH
      1.66     488.00 us     488.00 us     488.00 us              1      STATFS
      1.70     500.00 us     500.00 us     500.00 us              1        READ
      2.47     363.00 us     306.00 us     420.00 us              2      UNLINK
      5.15     504.33 us     471.00 us     539.00 us              3      CREATE
      8.20     602.50 us     324.00 us    1221.00 us              4       WRITE
     15.00    4411.00 us    4411.00 us    4411.00 us              1       FSYNC
     16.82     235.48 us     154.00 us     344.00 us             21     OPENDIR
     45.15     282.43 us     129.00 us    1694.00 us             47      LOOKUP
 
    Duration: 4233 seconds
   Data Read: 0 bytes
Data Written: 16384 bytes
 
Interval 1 Stats:
   Block Size:               4096b+ 
 No. of Reads:                    0 
No. of Writes:                    4 
 %-latency   Avg-latency   Min-Latency   Max-Latency   No. of calls         Fop
 ---------   -----------   -----------   -----------   ------------        ----
      0.00       0.00 us       0.00 us       0.00 us              1        STAT
      0.00       0.00 us       0.00 us       0.00 us              2      FORGET
      0.00       0.00 us       0.00 us       0.00 us              2     RELEASE
      0.00       0.00 us       0.00 us       0.00 us             21  RELEASEDIR
      0.85     250.00 us     250.00 us     250.00 us              1     SETATTR
      1.50     440.00 us     440.00 us     440.00 us              1       FSTAT
      1.51     222.00 us     200.00 us     244.00 us              2       FLUSH
      1.66     488.00 us     488.00 us     488.00 us              1      STATFS
      1.70     500.00 us     500.00 us     500.00 us              1        READ
      2.47     363.00 us     306.00 us     420.00 us              2      UNLINK
      5.15     504.33 us     471.00 us     539.00 us              3      CREATE
      8.20     602.50 us     324.00 us    1221.00 us              4       WRITE
     15.00    4411.00 us    4411.00 us    4411.00 us              1       FSYNC
     16.82     235.48 us     154.00 us     344.00 us             21     OPENDIR
     45.15     282.43 us     129.00 us    1694.00 us             47      LOOKUP
 
    Duration: 3767 seconds
   Data Read: 0 bytes
Data Written: 16384 bytes

Esta información se repite por cada uno de los bricks que conforman el cluster.

Comandos TOP de Gluster

Hay una serie de comandos que nos muestran los picos de rendimiento del cluster, son los siguientes.

Ver los descriptores abiertos y la cuenta máxima de descriptores

# gluster volume top testvol open brick server1.example.com:/data
Brick: server1.example.com:/data
Current open fds: 1, Max open fds: 2, Max openfd time: 2014-07-30 09:39:44.312759

Ver ranking de llamadas a lectura de fichero

# gluster volume top testvol read brick server1.example.com:/data
Brick: server1.example.com:/data
Count		filename
=======================
1		/file.txt

Ver ranking de llamadas a escritura de fichero

# gluster volume top testvol write brick server1.example.com:/data
Brick: server1.example.com:/data
Count		filename
=======================
4		/.file.txt.swp

Ver ranking de llamadas abiertas en directorios

# gluster volume top testvol opendir brick server1.example.com:/data
Brick: server1.example.com:/data
Count		filename
=======================
21		/prueba

Ver ranking de llamadas de lecturas en directorio

# gluster volume top testvol readdir brick server1.example.com:/data
Brick: server1.example.com:/data
Count		filename
=======================
4		/prueba

Ver la lista del rendimiento en lectura en cada brick

# gluster volume top testvol read-perf bs 256 count 1 brick server1.example.com:/data
Brick: server1.example.com:/data
Throughput 6.24 MBps time 0.0000 secs
MBps Filename                                        Time                      
==== ========                                        ====                      
   0 /file.txt                                       2014-07-30 09:39:44.388815

Ver la lista del rendimiento en escritura en cada brick

# gluster volume top testvol write-perf bs 256 count 1 brick server1.example.com:/data
Brick: server1.example.com:/data
Throughput 8.26 MBps time 0.0000 secs
MBps Filename                                        Time                      
==== ========                                        ====                      
  27 /prueba/.file.xls.swp                           2014-07-30 10:50:37.671327
  18 /.file.swp                                      2014-07-30 10:50:13.860439
   0 /prueba/file.xls                                2014-07-30 10:52:13.528054
   0 /file                                           2014-07-30 10:50:13.829870

Fuente

Es una chuleta de la documentación oficial que se puede consultar aquí y está más documentada pero la sintaxis de los comandos no está actualizada a día de hoy.

Almacenamiento Distribuido Sobre Cuatro Nodos con GlusterFS 3.5 y CentOS 6.5

Hoy vamos a construir un clúster de almacenamiento con GlusterFS y CentOS utilizando cuatro nodos para ficheros y datos de usuarios. El tamaño de la compartición será la suma de lo que aporte cada nodo individualmente. GlusterFS es un sistema de ficheros clusterizado capaz de escalar hasta varios peta-bytes.

Vamos a necesitar cuatro máquinas para los servidores y una que hará de cliente. Todas con CentOS. Todas deben resolver el nombre de las demás, si no es posible hacerlo mediante DNS utilizamos el fichero /etc/hosts de la siguiente manera.

192.168.1.100   server1.example.com     server1
192.168.1.101   server2.example.com     server2
192.168.1.102   server3.example.com     server3
192.168.1.103   server4.example.com     server4
192.168.1.104   client1.example.com     client1

Antes de empezar vamos a desabilitar SELinux y, como estamos dentro de la red local, el firewall.

Para deshabilitar SELinux editamos el fichero /etc/sysconfig/selinux y cambiamos la siguiente línea.

[...]
SELINUX=disabled
[...]

Para deshabilitar el cortafuegos simplemente lo quitamos del autoarranque.

# chkconfig iptables off
# chkconfig ip6tables off

Comenzamos instalando GlusterFS en los nodos

Instalando GlusterFS en los nodos

Habilitando el repositorio

Tenemos que crear un nuevo fichero de repositorio dentro de /etc/yum.repos.d con nombre glusterfs.repo

# vim /etc/yum.repos.d/glusterfs.repo

Añadimos

[glusterfs-epel]
name=GlusterFS is a clustered file-system capable of scaling to several petabytes.
baseurl=http://download.gluster.org/pub/gluster/glusterfs/LATEST/EPEL.repo/epel-$releasever/$basearch/
enabled=1
skip_if_unavailable=1
gpgcheck=1
gpgkey=http://download.gluster.org/pub/gluster/glusterfs/LATEST/EPEL.repo/pub.key

[glusterfs-noarch-epel]
name=GlusterFS is a clustered file-system capable of scaling to several petabytes.
baseurl=http://download.gluster.org/pub/gluster/glusterfs/LATEST/EPEL.repo/epel-$releasever/noarch
enabled=1
skip_if_unavailable=1
gpgcheck=1
gpgkey=http://download.gluster.org/pub/gluster/glusterfs/LATEST/EPEL.repo/pub.key

[glusterfs-source-epel]
name=GlusterFS is a clustered file-system capable of scaling to several petabytes. - Source
baseurl=http://download.gluster.org/pub/gluster/glusterfs/LATEST/EPEL.repo/epel-$releasever/SRPMS
enabled=0
skip_if_unavailable=1
gpgcheck=1
gpgkey=http://download.gluster.org/pub/gluster/glusterfs/LATEST/EPEL.repo/pub.key

Añadir la firma

A continuación se añade la firma del repositorio al depósito de claves

# yum --import http://download.gluster.org/pub/gluster/glusterfs/LATEST/EPEL.repo/pub.key

Ya podemos usar el gestor de paquetes para instalar el software

Instalando el servidor GlusterFS

Desde la terminal instalamos los paquetes necesarios

# yum install glusterfs-server

Una vez ha terminado de instalar paquetes podemos comprobar que está correcto escribiendo.

# glusterfsd --version

Debemos ver lo siguiente.

glusterfs 3.5.1 built on Jun 24 2014 15:09:28
Repository revision: git://git.gluster.com/glusterfs.git
Copyright (c) 2006-2013 Red Hat, Inc. 
GlusterFS comes with ABSOLUTELY NO WARRANTY.
It is licensed to you under your choice of the GNU Lesser
General Public License, version 3 or any later version (LGPLv3
or later), or the GNU General Public License, version 2 (GPLv2),
in all cases as published by the Free Software Foundation.

Antes de continuar debemos arrancar el demonio haciendo lo siguiente.

# /etc/init.d/glusterd start

Dejamos el servicio habilitado para el próximo reinicio

# chkconfig glusterd on

Seguimos con la configuración.

Creando la compartición

Ya tenemos el servidor instalado, vamos a configurara una compartición. Los siguientes pasos sólo los haremos en server1 ya que la configuración se replica entre los nodos que conforman el cluster. Primero debemos crear el pool de almacenamiento. Desde la consola del primer servidor escribimos.

# gluster peer probe server2.example.com
Probe successful
# gluster peer probe server3.example.com
Probe successful
# gluster peer probe server4.example.com
Probe successful

Podemos comprobar que se ha construido satisfactoriamente.

# gluster peer status
Number of Peers: 3

Hostname: server2.example.com
Uuid: da79c994-eaf1-4c1c-a136-f8b273fb0c98
State: Peer in Cluster (Connected)

Hostname: server3.example.com
Uuid: 3e79bd9f-a4d5-4373-88e1-40f12861dcdd
State: Peer in Cluster (Connected)

Hostname: server4.example.com
Uuid: c6215943-00f3-492f-9b69-3aa534c1d8f3
State: Peer in Cluster (Connected)

Ahora creamos la compartición distribuida que llamaremos testvol. Seguimos en server1

# gluster volume create testvol stripe 4 transport tcp server1.example.com:/data server2.example.com:/data server3.example.com:/data server4.example.com:/data force
Creation of volume testvol has been successful. Please start the volume to access data.

Añadimos el parámetro force si el directorio que comparten los nodos está en la raiz del sistema de ficheros.

Iniciamos el volumen

# gluster volume start testvol
Starting volume testvol has been unsuccessful

Si comprobamos las conexiones veremos como está levantado el servicio.

# netstat -tap | grep glusterfs
tcp        0      0 *:24009                 *:*                     LISTEN      1110/glusterfsd
tcp        0      0 localhost.localdom:1019 localhost.localdo:24007 ESTABLISHED 1110/glusterfsd

Vamos a añadir una capa de seguridad permitiendo conexiones unicamente desde nuestra red local, para ello hacemos.

# gluster volume set testvol auth.allow 192.168.1.*

Y ahora si comprobamos el estado del volumen.

# gluster volume info

Volume Name: testvol
Type: Stripe
Volume ID: f922da05-737d-4fb5-83cc-e50d6782b90c
Status: Started
Number of Bricks: 1 x 4 = 4
Transport-type: tcp
Bricks:
Brick1: server1.example.com:/data
Brick2: server2.example.com:/data
Brick3: server3.example.com:/data
Brick4: server4.example.com:/data
Options Reconfigured:
auth.allow: 192.168.1.*

Configuración de los clientes

Estos pasos debemos llevarlos a cabo por cada cliente que queramos que pueda montar la compartición. Empezamos instalando el cliente de GlusterFS.

Hay que habilitar el repositorio como hicimos con los servidores.

# yum install glusterfs-client

Creamos un punto de montaje para la compartición.

# mkdir /mnt/glusterfs

Montamos.

mount.glusterfs server1.example.com:/testvol /mnt/glusterfs

Podemos ver que está montado haciendo.

# mount 

/dev/mapper/VolGroup-lv_root on / type ext4 (rw)
proc on /proc type proc (rw)
sysfs on /sys type sysfs (rw)
devpts on /dev/pts type devpts (rw,gid=5,mode=620)
tmpfs on /dev/shm type tmpfs (rw)
/dev/sda1 on /boot type ext4 (rw)
none on /proc/sys/fs/binfmt_misc type binfmt_misc (rw)
server1.example.com:/testvol on /mnt/glusterfs type fuse.glusterfs (rw,default_permissions,allow_other,max_read=131072)

También

# df -hT

Filesystem                   Type            Size  Used Avail Use% Mounted on
/dev/mapper/VolGroup-lv_root ext4            6,7G  796M  5,5G  13% /
tmpfs                        tmpfs           250M     0  250M   0% /dev/shm
/dev/sda1                    ext4            485M   31M  429M   7% /boot
server1.example.com:/testvol fuse.glusterfs   20G  2,4G   17G  13% /mnt/glusterfs

Hacemos los cambios permanentes añadiendo la siguiente línea al fichero /etc/fstab

server1.example.com:/testvol /mnt/glusterfs glusterfs defaults,_netdev 0 0

Fuente

He seguido los pasos de este artículo para adaptarlo a CentOS y la última versión de GlusterFS

Algunas Fotos en el Despacho

Mi buen amigo @gonzaloMMD, se fue de viaje a Paris y ha preparado una entrada con unas fotos chulísimas de la capital alemana francesa (“acias” wikipedia!) xDDD. Yo más humilde, posteo unas pocas “fotillos” del despacho.

Estas dos corresponden a la migración que hicimos del cluster de OpenSUSE a CentOS. Se ven los 6 nodos esclavos, aunque la estructura está cambiando, y tendré que actualizar esta entrada.

Nodos Cluster Front

Nodos Cluster Front


Nodos Cluster Back

Nodos Cluster Back

Este será el nuevo master del cluster, el i7 con 16GB de RAM, con sus 5 discos duros.

Master Cluster

Master Cluster


Discos Master Cluster

Discos Master Cluster

Y esta es mi mesa, como siempre, llena de papeles y chismes.

Mi Mesa

Autentica mesa sysadmin

Compilación Paralela

He empezado a aprender como hacer compilación paralela para obtener más rendimiento en el clúster. Para ello me he metido con OpenMPI que es un proyecto abierto derivado de la estructura LAM/MPI mantenido por la comunidad.

El primer paso es obtener el software de esta dirección y compilarlo:

$ tar jxvf openmpi-1.4.1.tar.bz2
$ ./configure --prefix=/usr/local/openmpi
# make all install

Una vez compilado, debemos actualizar el enlazador dinámico para que nuestro software enlace correctamente con las librerías dinámicas de OpenMPI

# ldconfig /usr/local/openmpi/lib

Con esto, le decimos al programa ld que busque en /usr/local/openmpi/lib las librerias que haces falta en tiempo de ejecución de nuestro programa.

A continuación, es obligatorio que todos los nodos del clúster tengan acceso a los ejecutables tanto de nuestro programa como de OpenMPI, por lo que vamos ha crear un par de comparticiones por NFS.

/usr/local/openmpi   192.168.0.0/24(ro,root_squash)
/home/openmpi   192.168.0.0/24(rw,root_squash)

Donde /home/openmpi es nuestro usuario de cluster, en su directorio $HOME estará el programa a ejecutar. Y la otra compartición contiene los ejecutables del compilador.

Vamos a lanzar el programa clásico HelloWorld en paralelo, para ello utilizamos el siguiente código.

/* helloworld.c */
/* http://www.semicomplete.com/presentations/mpi/#slide_2 */
#include <stdio.h>
/* Esto es para añadir las funciones de OpenMPI */
#include "mpi.h"

int main(int argc, char **argv) {
int rank;
char host[150];
int namelen;

/* Inicializar MPI. Maneja la línea de comando especifica de mpich */
MPI_Init(&argc, &argv);

/* Devuelve el rango. Mi número de rango (de la instancia del programa) queda almacenado en la variable rank */
MPI_Comm_rank(MPI_COMM_WORLD, &rank);

/* Vemos en qué maquina me ejecutando y lo guardamos en host */
MPI_Get_processor_name(host,&namelen);

printf("Hello world (Rank: %d / Host: %s)\n", rank, host);
fflush(stdout);

/* Fin: Cerramos las conexiones con los demás nodos y liberamos la memora que el programa ha reservado,... */
MPI_Finalize();
return 0;

Lo compilamos

$ PATH=$PATH:/usr/local/openmpi/bin
$ mpicc helloworld.c -o helloworld

El PATH podemos añadirlo a nuestro ~/.bashrc para que esté siempre disponible. Ejecutamos.

$ mpirun -np 5 --hostfile=hosts helloworld

Donde

  1. -np Es el número de procesos que vamos a lanzar.
  2. –hostfile Es el fichero que almacena los nombres de los hosts, cada nodo del cluster.

La salida debe ser algo como esto

Hello world (Rank: 0 / Host: master)
Hello world (Rank: 2 / Host: master)
Hello world (Rank: 4 / Host: master)
Hello world (Rank: 1 / Host: cluster01)
Hello world (Rank: 3 / Host: cluster01)

Vemos que ha lanzado tres procesos en master y dos en cluster01.

De momento esto es lo poco que sé, pero sigo avanzando, el asunto de tener que resolver matrices de gran tamaño voy a necesitar escribir código para lanzar paralelizado.