domingo, 24 de agosto de 2014

Gluster: explotando su cache

Ya que los últimos días estuve trabajando bastante con gluster y su cache, me pareció interesante plasmarlo acá (para cuando me vuelva a olvidar cómo se hace ja!). La idea es mostrarles cómo se configura la cache en los volúmenes de gluster y qué funcionamiento tiene.

En este escenario vamos a estar trabajando con Gluster 3.5.2 (not production ready yet, but good enough :P) sobre CentOS 6.5.

Creando un volumen con  replica 2

Para empezar necesitamos crear un volumen. En este caso creamos un volumen con réplica 2 de la siguiente manera:

[root@gluster-test-1 ~]# gluster vol create volumen_prueba replica 2 gluster-test-1:/ladrillos/l1/l gluster-test-2:/ladrillos/l1/l
volume create: volumen_prueba: success: please start the volume to access data
[root@gluster-test-1 ~]# gluster vol start volumen_prueba
volume start: volumen_prueba: success
[root@gluster-test-1 ~]# 

Una vez creado e iniciado vemos su estado e información

[root@gluster-test-1 ~]# gluster vol status volumen_prueba
Status of volume: volumen_prueba
Gluster process                                         Port    Online  Pid
------------------------------------------------------------------------------
Brick gluster-test-1:/ladrillos/l1/l                    49159   Y       11717
Brick gluster-test-2:/ladrillos/l1/l                    49159   Y       12102
NFS Server on localhost                                 N/A     N       N/A
Self-heal Daemon on localhost                           N/A     Y       11731
NFS Server on gluster-test-3                            N/A     N       N/A
Self-heal Daemon on gluster-test-3                      N/A     Y       11929
NFS Server on gluster-test-2                            N/A     N       N/A
Self-heal Daemon on gluster-test-2                      N/A     Y       12120
 
Task Status of Volume volumen_prueba
------------------------------------------------------------------------------
There are no active volume tasks
 
[root@gluster-test-1 ~]# gluster vol info volumen_prueba
                                                                                                                                                                  
Volume Name: volumen_prueba                                                                                                                                       
Type: Replicate                                                                                                                                                   
Volume ID: 1197881d-ce2a-4f64-af17-53e5529b691c                                                                                                                   
Status: Started                                                                                                                                                   
Number of Bricks: 1 x 2 = 2                                                                                                                                       
Transport-type: tcp                                                                                                                                               
Bricks:                                                                                                                                                           
Brick1: gluster-test-1:/ladrillos/l1/l                                                                                                                            
Brick2: gluster-test-2:/ladrillos/l1/l                                                                                                                            
[root@gluster-test-1 ~]#   

Ahora que vemos que todo se encuentra bien montamos el volumen desde la máquina cliente:

[root@gluster-client-1 ~]# mount.glusterfs gluster-test-1:/volumen_prueba /mnt/gluster_vol                                                                       
[root@gluster-client-1 ~]# 

Dado que el montaje fue exitoso vemos los logs en /var/log/gluster/mnt-gluster_vol.log y encontramos la definición del volumen (todos estos translators y demás valores se cargan por defecto):

Final graph:
+------------------------------------------------------------------------------+
  1: volume volumen_prueba-client-0
  2:     type protocol/client
  3:     option remote-host gluster-test-1
  4:     option remote-subvolume /ladrillos/l1/l
  5:     option transport-type socket
  6:     option send-gids true
  7: end-volume
  8: 
  9: volume volumen_prueba-client-1
 10:     type protocol/client
 11:     option remote-host gluster-test-2
 12:     option remote-subvolume /ladrillos/l1/l
 13:     option transport-type socket
 14:     option send-gids true
 15: end-volume
 16: 
 17: volume volumen_prueba-replicate-0
 18:     type cluster/replicate
 19:     subvolumes volumen_prueba-client-0 volumen_prueba-client-1
 20: end-volume
 21: 
 22: volume volumen_prueba-dht
 23:     type cluster/distribute
 24:     subvolumes volumen_prueba-replicate-0
 25: end-volume
 26: 
 27: volume volumen_prueba-write-behind
 28:     type performance/write-behind
 29:     subvolumes volumen_prueba-dht
 30: end-volume
 31: 
 32: volume volumen_prueba-read-ahead
 33:     type performance/read-ahead
 34:     subvolumes volumen_prueba-write-behind
 35: end-volume
 36: 
 37: volume volumen_prueba-io-cache
 38:     type performance/io-cache
 39:     subvolumes volumen_prueba-read-ahead
 40: end-volume
 41: 
 42: volume volumen_prueba-quick-read
 43:     type performance/quick-read
 44:     subvolumes volumen_prueba-io-cache
 45: end-volume
 46: 
 47: volume volumen_prueba-open-behind
 48:     type performance/open-behind
 49:     subvolumes volumen_prueba-quick-read
 50: end-volume
 51: 
 52: volume volumen_prueba-md-cache
 53:     type performance/md-cache
 54:     subvolumes volumen_prueba-open-behind
 55: end-volume
 56: 
 57: volume volumen_prueba
 58:     type debug/io-stats
 59:     option latency-measurement off
 60:     option count-fop-hits off
 61:     subvolumes volumen_prueba-md-cache
 62: end-volume
 63: 
+------------------------------------------------------------------------------+

Las líneas 37 a 40 hacen referencia a la configuración del performance/IO-cache translator, el cuál se encarga de definir la configuración del cache del volumen.  Como vemos no hay demasiado configurado dado que aún se encuentra todo por defecto. Según la documentación oficial el tamaño default del cache es de 32Mbytes y un tiempo de expiración de 1 segundo. 

Algunos de los parámetros que podremos controlar desde aquí son:

  • cache-size: espacio asignado a cache
  • cache-timeout: tiempo de expiración de los objetos en cache
  • priority: permite asignar prioridades a distintos tipos de archivos para el uso de cache
  • cache-max-file-size: tamaño máximo de archivo que se puede almacenar en cache
  • cache-min-file-size: tamaño mínimo de archivo que se puede almacenar en cache

Probando los default settings:

Ahora que montamos el archivo vamos a probar la configuración por defecto con que se arman los volúmenes en gluster.

Primero escribimos un archivo de 25Mbytes en el directorio montado:

[root@gluster-client-1 ~]# dd if=/dev/zero of=/mnt/gluster_vol/25MB bs=1M count=25
25+0 records in
25+0 records out
26214400 bytes (26 MB) copied, 0,0286961 s, 914 MB/s
[root@gluster-client-1 ~]# ll -h /mnt/gluster_vol/
total 25M
-rw-r--r--. 1 root root 25M ago 24 20:54 25MB
[root@gluster-client-1 ~]# 

Ahora lo leeremos con intervalos de 10 segundos limpiando los bufferes del sistema entre cada operación:

[root@gluster-client-1 ~]# for i in 1 2 3 4 5; do echo 3 > /proc/sys/vm/drop_caches; dd of=/dev/null if=/mnt/gluster_vol/25MB bs=1M; date; sleep 10;done
25+0 records in
25+0 records out
26214400 bytes (26 MB) copied, 0,271792 s, 96,5 MB/s
dom ago 24 21:20:12 ART 2014
25+0 records in
25+0 records out
26214400 bytes (26 MB) copied, 0,0568677 s, 461 MB/s
dom ago 24 21:20:22 ART 2014
25+0 records in
25+0 records out
26214400 bytes (26 MB) copied, 0,0402717 s, 651 MB/s
dom ago 24 21:20:32 ART 2014
25+0 records in
25+0 records out
26214400 bytes (26 MB) copied, 0,0392092 s, 669 MB/s
dom ago 24 21:20:43 ART 2014
25+0 records in
25+0 records out
26214400 bytes (26 MB) copied, 0,0420014 s, 624 MB/s
dom ago 24 21:20:53 ART 2014
[root@gluster-client-1 ~]# 

Interesante! La primer lectura demora 0.27 segundos, mientras que las 4 siguientes demoran entre 0.03 y 0.05! Claramente se trata de la intervención de la cache. Podría parecer confuso por los 10 segundos que esperamos entre lectura y lectura, pero la documentación define cache-timeout como un tiempo de expiración que fuerza una de re-validación, así que este es un comportamiento esperable. Probablemente estos 10 segundos de espera hubiesen sido demasiado en un entorno de mayor uso del cache.
 
Ahora corremos la misma prueba pero removiendo el tiempo de espera de 10 segundos:

[root@gluster-client-1 ~]# for i in 1 2 3 4 5; do echo 3 > /proc/sys/vm/drop_caches; dd of=/dev/null if=/mnt/gluster_vol/25MB bs=1M; date; done
25+0 records in
25+0 records out
26214400 bytes (26 MB) copied, 0,0485229 s, 540 MB/s
dom ago 24 21:25:18 ART 2014
25+0 records in
25+0 records out
26214400 bytes (26 MB) copied, 0,0471389 s, 556 MB/s
dom ago 24 21:25:18 ART 2014
25+0 records in
25+0 records out
26214400 bytes (26 MB) copied, 0,0360902 s, 726 MB/s
dom ago 24 21:25:18 ART 2014
25+0 records in
25+0 records out
26214400 bytes (26 MB) copied, 0,0359891 s, 728 MB/s
dom ago 24 21:25:18 ART 2014
25+0 records in
25+0 records out
26214400 bytes (26 MB) copied, 0,0355376 s, 738 MB/s
dom ago 24 21:25:18 ART 2014
[root@gluster-client-1 ~]# 

Podemos ver que los tiempos no son demasiado diferentes a los que obtuvimos anteriormente. 

Qué pasaría con un archivo mayor a 32Mbytes...? Escribimos un archivo de 128Mbytes para ver qué sucede:

[root@gluster-client-1 ~]# dd if=/dev/zero of=/mnt/gluster_vol/128MB bs=1M count=128
128+0 records in
128+0 records out
134217728 bytes (134 MB) copied, 2,403 s, 55,9 MB/s
[root@gluster-client-1 ~]# ll -h /mnt/gluster_vol/
total 153M
-rw-r--r--. 1 root root 128M ago 24 21:27 128MB
-rw-r--r--. 1 root root  25M ago 24 21:19 25MB
[root@gluster-client-1 ~]# 

Ahora lo leemos:

[root@gluster-client-1 ~]# for i in 1 2 3 4 5; do echo 3 > /proc/sys/vm/drop_caches; dd of=/dev/null if=/mnt/gluster_vol/128MB bs=1M; date; done
128+0 records in
128+0 records out
134217728 bytes (134 MB) copied, 1,95299 s, 68,7 MB/s
dom ago 24 21:29:09 ART 2014
128+0 records in
128+0 records out
134217728 bytes (134 MB) copied, 1,95518 s, 68,6 MB/s
dom ago 24 21:29:11 ART 2014
128+0 records in
128+0 records out
134217728 bytes (134 MB) copied, 1,96224 s, 68,4 MB/s
dom ago 24 21:29:13 ART 2014
128+0 records in
128+0 records out
134217728 bytes (134 MB) copied, 1,94886 s, 68,9 MB/s
dom ago 24 21:29:15 ART 2014
128+0 records in
128+0 records out
134217728 bytes (134 MB) copied, 1,98702 s, 67,5 MB/s
dom ago 24 21:29:17 ART 2014
[root@gluster-client-1 ~]#

En este caso vemos claramente que estamos teniendo velocidades de lectura muy bajas, lo que nos da la pauta de que no estamos utilizando la cache.

Modificando la configuración de cache:

Ahora vamos a aumentar nuestra capacidad de cache para lograr una buena velocidad de lectura en el caso del archivo de 128Mbytes. Seteamos la cache a 256Mbytes de la siguiente manera:

[root@gluster-test-1 ~]# gluster vol set volumen_prueba performance.cache-size 256MB                                                                             
volume set: success                                                                                                                                               
[root@gluster-test-1 ~]# gluster vol info volumen_prueba
Volume Name: volumen_prueba
Type: Replicate
Volume ID: 1197881d-ce2a-4f64-af17-53e5529b691c
Status: Started
Number of Bricks: 1 x 2 = 2
Transport-type: tcp
Bricks:
Brick1: gluster-test-1:/ladrillos/l1/l
Brick2: gluster-test-2:/ladrillos/l1/l
Options Reconfigured:
performance.cache-size: 256MB
[root@gluster-test-1 ~]# 

Podríamos pensar que no sucedió nada, pero...

[root@gluster-client-1 ~]# for i in 1 2 3 4 5; do echo 3 > /proc/sys/vm/drop_caches; dd of=/dev/null if=/mnt/gluster_vol/128MB bs=1M; date; done
128+0 records in
128+0 records out
134217728 bytes (134 MB) copied, 1,59836 s, 84,0 MB/s
dom ago 24 21:34:25 ART 2014
128+0 records in
128+0 records out
134217728 bytes (134 MB) copied, 1,26796 s, 106 MB/s
dom ago 24 21:34:26 ART 2014
128+0 records in
128+0 records out
134217728 bytes (134 MB) copied, 0,159935 s, 839 MB/s
dom ago 24 21:34:26 ART 2014
128+0 records in
128+0 records out
134217728 bytes (134 MB) copied, 0,152958 s, 877 MB/s
dom ago 24 21:34:27 ART 2014
128+0 records in
128+0 records out
134217728 bytes (134 MB) copied, 0,164556 s, 816 MB/s
dom ago 24 21:34:27 ART 2014
[root@gluster-client-1 ~]# 

Sin necesidad de reiniciar absolútamente nada, ni de desmontar el volumen, vemos como gluster fue capaz de reconocer el aumento del tamaño de cache y permitirnos leer el archivo de 128Mbytes hasta mas de 10 veces mas rápido!!!

El resto es cuento, solo hay que ponerse a jugar con los valores para obtener la política de cache que uno quiere. 

Dónde se almacena la cache?

Hice un par de preguntas al respecto en la lista de usuarios de gluster, dado que no me quedaba del todo claro dónde se almacena la cache. Según la documentación el translator performance/io-cache puede encontrarse presente tanto en el servidor como en el cliente con objetivos distintos. 
  • Estando en el servidor permite compartir la cache con varios clientes de manera simultánea.
  • Estando en el cliente permite ahorrar ancho de banda y CPU (del servidor).
En la lista me dijieron que el translator performance/io-cache se carga durante el proceso de montado del volumen así que la cache por defecto se encuentra en el cliente.

viernes, 8 de agosto de 2014

Gluster: graficando mi Gluster II

Luego de comentar la herramienta en la lista oficial de usuarios de gluster gluster-users@gluster.org, me recomendaron hacerla un proyecto oficial de la comunidad y me pareció una buena idea. Así es como nació GlusterGraph. Desde el link podrán acceder tanto a las fuentes de la herramienta como a una pequeña wiki que describe cómo utilizarla en uno pocos pasos.

Les dejo un ejemplo de ejecución para mas o menos cerrar la idea:

  • Clonar el repositorio:
jpavlik@corrientes:~/Escritorio/devnull/borrar$ git clone git://forge.gluster.org/glustergraph/glustergraph.git
Clonar en «glustergraph»...
remote: Counting objects: 73, done.
remote: Compressing objects: 100% (62/62), done.
remote: Total 73 (delta 20), reused 0 (delta 0)
Receiving objects: 100% (73/73), 58.33 KiB, done.
Resolving deltas: 100% (20/20), done.

  • Ubicar el archivo ejecutable:
jpavlik@corrientes:~/Escritorio/devnull/borrar$ ls glustergraph/GlusterGraph/ExecJar/
glustergraph.jar
jpavlik@corrientes:~/Escritorio/devnull/borrar$ 
  • Ejecutarlo pasando como entrada gluster volume info y redireccionando la salida a out.dot (debería ver algo como lo siguiente):
jpavlik@corrientes:~/Escritorio/devnull/borrar$ gluster volume info | java -jar glustergraph/GlusterGraph/ExecJar/glustergraph.jar > out.dot
GlusterGraph v0.1

Loading all volumes

New volume found: fernanda-02
New brick found: gfsc-nodo03:/ladrillos/l1                                                                                                                                                      
New node found: gfsc-nodo03
New brick found: gfsc-nodo03:/ladrillos/l3                                                                                                                                                      
New volume found: fernanda
New brick found: gfsc-nodo04:/ladrillos/l1
New node found: gfsc-nodo04
New brick found: gfsc-nodo01:/ladrillos/l1
New node found: gfsc-nodo01
New brick found: gfsc-nodo04:/ladrillos/l2
New brick found: gfsc-nodo01:/ladrillos/l2
New brick found: gfsc-nodo04:/ladrillos/l3
New brick found: gfsc-nodo02:/ladrillos/l1
New node found: gfsc-nodo02
New brick found: gfsc-nodo03:/ladrillos/l2
New brick found: gfsc-nodo02:/ladrillos/l2
New brick found: gfsc-nodo04:/ladrillos/l5
New brick found: gfsc-nodo02:/ladrillos/l3
New brick found: gfsc-nodo01:/ladrillos/l3
New brick found: gfsc-nodo04:/ladrillos/l4
jpavlik@corrientes:~/Escritorio/devnull/borrar$ 
  • Ahora graficamos el archivo con dot:
jpavlik@corrientes:~/Escritorio/devnull/borrar$ dot -Tpng out.dot > out.png
jpavlik@corrientes:~/Escritorio/devnull/borrar$ ls out*
out.dot  out.png
jpavlik@corrientes:~/Escritorio/devnull/borrar$ 
  • Abrimos la imagen:

domingo, 3 de agosto de 2014

Gluster: graficando mi Gluster I

Hace unos meses comencé a utilizar Gluster en el trabajo y la verdad que me resulta una herramienta para soluciones de almacenamiento mas que interesante. Gluster permite a partir de ladrillos (puntos de montaje en los servidores) crear volúmenes de almacenamiento de tamaños exorbitantes. Estos volúmenes creados, pueden ser:

  • Distribuidos: los archivos se distribuyen entre los diferentes ladrillos que componen el volumen. Este escenario tiene un rendimiento muy interesante pero carece de redundancia a nivel de gluster (claro que uno podría usar RAID para combatir esta falencia)
  • Distribuido-Replicado: aquí los archivos además de estar distribuidos en los diferentes ladrillos se encuentran replicados (1, 2, 3 o n veces), de forma tal que se penaliza la escritura por ejemplo pero se beneficia la lectura y la redundancia de la información. 
  • Otros.
Luego de unos meses de usarlo comencé a notar que se volvía cada vez mas complicado hacerme una imagen mental de la distribución de los ladrillos en el cluster y saber a qué volumen pertenece cada uno de ellos. Así fue que comencé a buscar formas de lograr una imagen que representara la configuración actual.
  • Papel: por mas precámbrico que parezca fue la primera aproximación y dada su simplicidad y la poca dinámica de la configuración fue útil por bastante tiempo.
  • Archivo de texto: el paso siguiente fue crear una imagen con graphviz a partir de un archivo de texto que se cargaba manualmente.
  • Java y script automático: el primer intento fue con perl, pero mi manejo de perl no fue suficiente y recurrí a la abstracción de Java.
Actualmente el script tiene dos entradas fundamentales:
  • Un archivo donde se definen los hosts que conforman el cluster de la forma: host:IP
  • Un archivo que se crea a partir de la salida del comando: gluster vol info > gluster_info
La imagen generada es la siguiente:


  • Los nodos son representados como rectángulos con su etiqueta y los ladrillos que contienen.
  • A la derecha tenemos el código de colores para cada volumen.
  • Cada ladrillo es del color del volumen al que pertenece.
  • Los ladrillos que formen parte de un volumen con réplica tendrán asociado un código de réplica. Éste servirá para identificar sus réplicas. Por ejemplo en el volumen vol4, el ladrillo l1 del nodo nodo01 y el ladrillo l1 del nodo nodo04 tienen el mismo código COD0 lo que indica que son réplicas uno de otro.

Demo:

Archivos que componen el script:

juan@moon:~/Escritorio/devnull$ ls
gluster_graph.jar  gluster_info  hosts  lanzar.sh
juan@moon:~/Escritorio/devnull$ 

Archivo hosts

juan@moon:~/Escritorio/devnull$ cat hosts
gfsc-nodo01:172.16.16.190
gfsc-nodo02:172.16.16.191
gfsc-nodo03:172.16.16.192
gfsc-nodo04:172.16.16.193
juan@moon:~/Escritorio/devnull$ 

Archivo gluster_info:

juan@moon:~/Escritorio/devnull$ cat gluster_info 
Volume Name: vol2
Type: Distribute
Volume ID: 1f9db37d-fc16-433e-9c39-af526ea32027
Status: Started
Number of Bricks: 1
Transport-type: tcp
Bricks:
Brick1: gfsc-nodo03:/ladrillos/l1
Options Reconfigured:
performance.cache-size: 256MB

Volume Name: vol1
Type: Distribute
Volume ID: 1f9db37d-fc16-433e-9c39-af526ea32024
Status: Started
Number of Bricks: 3
Transport-type: tcp
Bricks:
Brick1: gfsc-nodo01:/ladrillos/l4
Brick1: gfsc-nodo02:/ladrillos/l4
Brick1: gfsc-nodo03:/ladrillos/l3
Options Reconfigured:
performance.cache-size: 256MB
Volume Name: vol4
Type: Distributed-Replicate
Volume ID: f0570fe5-93fa-45f3-b875-41760a466a9a
Status: Started
Number of Bricks: 6 x 2 = 12
Transport-type: tcp
Bricks:
Brick1: gfsc-nodo04:/ladrillos/l1
Brick2: gfsc-nodo01:/ladrillos/l1
Brick3: gfsc-nodo04:/ladrillos/l2
Brick4: gfsc-nodo01:/ladrillos/l2
Brick5: gfsc-nodo04:/ladrillos/l3
Brick6: gfsc-nodo02:/ladrillos/l1
Brick7: gfsc-nodo03:/ladrillos/l2
Brick8: gfsc-nodo02:/ladrillos/l2
Brick9: gfsc-nodo04:/ladrillos/l5
Brick10: gfsc-nodo02:/ladrillos/l3
Brick11: gfsc-nodo01:/ladrillos/l3
Brick12: gfsc-nodo04:/ladrillos/l4
Options Reconfigured:
server.statedump-path: /var/log/glusterfs/
performance.cache-size: 640MB
diagnostics.client-log-level: ERROR

Volume Name: vol5
Type: Distributed-Replicate
Volume ID: 1f9db37d-fc16-433e-9c39-af526ea32024
Status: Started
Number of Bricks: 1 x 3 = 3
Transport-type: tcp
Bricks:
Brick1: gfsc-nodo01:/ladrillos/l5
Brick1: gfsc-nodo02:/ladrillos/l5
Brick1: gfsc-nodo03:/ladrillos/l4
Options Reconfigured:
performance.cache-size: 256MB
juan@moon:~/Escritorio/devnull$ 

El archivo lanzar.sh es un simple script en bash que facilita la ejecucón del jar y el armado del png:

juan@moon:~/Escritorio/devnull$ cat lanzar.sh 
#!/bin/bash
#
#Pavlik salles Juan Jose 02/08/2014
#
#Version 0.1: 
# - Admite volumenes Distribute y Distributed-Replicate sin importar el numero de ladrillos, ni de nodos, ni de replicas. Al menos en teoria.
# - Debido a que los colores estan hardcoded el numero maximo de volumenes es 18 (TOCHANGE)
# - 
#
#Comentarios a jjpavlik@gmail.com o en https://viviendolared.blogspot.com
#
#Requiere:
# - Graphviz y dot
#
#Funcionamiento:
# 1-Armar el archivos hosts con los hosts que conforman el cluster de gluster, el archivo tiene el formato hostname:IP
# 2-Armar el archivo de configuracion de gluster corriendo "gluster vol info > gluster_info"
# 3-Ubicar ambos archivos en el mismo directorio donde se encuentra este script
# 4-Lanzar este script ./lanzar
# 5-La imagen sera out.png
# --Los ladrillos de un mismo volumen tendran el mismo color
# --Los ladrillos con replicas podran ser identificados por su codigo. Por ejemplo si el ladrillo 1 del nodo 2 es replica del ladrillo 2 del nodo 1, ambos tendran el mismo codigo

if [ ! -e hosts ]; then
echo "Couldn't find hosts file."
exit
fi

if [ ! -e gluster_info ]; then
echo "Couldn't fine gluster_info file. You can build it running \"gluster vol info > gluster_info\"."
exit
fi

cat gluster_info | java -jar gluster_graph.jar > out.dot
dot -Tpng out.dot > out.png
juan@moon:~/Escritorio/devnull$ 

El archivo gluster_graph.jar es el jar del proyecto Java que hice en Eclipse.

Ejecución:

juan@moon:~/Escritorio/devnull$ ./lanzar.sh 
juan@moon:~/Escritorio/devnull$ ls
gluster_graph.jar  gluster_info  hosts  lanzar.sh  out.dot  out.png
juan@moon:~/Escritorio/devnull$ 

Ahora ye tenemos generada la imagen correspondiente en out.png.



El código de gluster_graph es bastante simple, pero aun no se dónde subirlo. Si a alguien le interesa por favor avisar y vemos cómo lo comparto. 

Por ahora solo lo probé con volumenes Distribute y Distributed-Replicate, con las configuraciones que mostré por lo tanto es posible que falta depurar muchas cosas.

Saludos