Este tutorial puede tener muchos aspectos sin pulir, porque es la primera vez que utilizo esta herramienta. Mi acercamiento fue motivado por el deseo de tener una solución rápida y de bajo consumo de recursos que me permitiera muestrear y graficar la transferencia del enlace de mi trabajo en intervalos de tiempo inferiores a los 5 minutos que suele utilizar MRTG.
RRDTool es una aplicación desarrollada por Tobias Oetiker (creador del popular MRTG) específicamente para registrar y graficar series de datos basados en el tiempo.
Esta herramienta ofrece mayor flexibilidad para graficar que MRTG y también mejor rendimiento, pues los gráficos se generan solo bajo demanda, de modo que la única carga para el sistema es el registro de los datos, que tiene muy bajo consumo de recursos.
Los datos se almacenan en una base de datos RRD (round robin database), que mantiene un tamaño constante y permite registrar diferentes intervalos de tiempo.
Aunque RRDTool puede utilizarse para muchas cosas, en este tutorial explicaremos cómo utilizarlo para llevar un registro histórico de la transferencia de un enlace.
Algunas cosas que se asumen en este tutorial:
Además de necesitar instalar RRDTool, para comunicarnos con el enrutador mediante SNMP necesitaremos tener instalados varios paquetes, pero podemos instalarlos todos de una vez:
sudo aptitude install snmp smistrip snmp-mibs-downloader rrdtool
Una aclaración:
A partir de Debian Squeeze los archivos MIB ya no pertenecen al paquete libsnmp-base
, sino que por un cambio en su licencia se movieron a la sección de componentes non-free
, de modo que para evitar errores en algunos comandos, conviene instalar el paquete snmp-mibs-downloader
, al menos temporalmente. También debemos colocar una marca de comentario en el archivo /etc/snmp/snmp.conf
, de modo que quedaría así:
#mibs :
El primer paso para utilizar RRDTool es crear la base de datos. Pueden utilizarse diferentes parámetros, sobre los cuales podremos conocer más con el comando man rrdcreate
. No obstante, para abreviar, utilizaremos un simple script de bash
:
#! /bin/sh # Script para crear base de datos RRD para monitoreo de enlace # Directorio de la base de datos RRDATADIR=/var/log/rrd # Archivo de la base de datos RRDATAFILE=enrutador.rrd # Crear directorio si no existe mkdir -p $RRDATADIR # Crear base de datos, si no existe if [ ! -f "$RRDATADIR/$RRDATAFILE" ]; then sudo rrdtool create "$RRDATADIR/$RRDATAFILE" \ --step 10 \ DS:in:COUNTER:20:0:20000 \ DS:out:COUNTER:20:0:20000 \ RRA:AVERAGE:0.5:3:8640 \ RRA:AVERAGE:0.5:30:25920 \ RRA:AVERAGE:0.5:720:4380 fi exit 0
El significado de este script básicamente es el siguiente:
Para consultar el enrutador utilizaremos el protocolo SNMP. Hay muchas herramientas que lo soportan, pero en este tutorial haremos el proceso manualmente.
Primeramente, necesitamos saber cuál es la interfaz del enrutador que deseamos monitorear, y para esto podemos utilizar el siguiente comando:
snmpwalk -v1 -c MiComunidad 192.168.1.1 interfaces.ifTable.ifEntry.ifDescr
Este comando debería producir un listado de interfaces, parecido a este:
IF-MIB::ifDescr.10000 = STRING: eth-0 IF-MIB::ifDescr.40000 = STRING: dsl-0 IF-MIB::ifDescr.140000 = STRING: atm-0 IF-MIB::ifDescr.150000 = STRING: aal5-0 IF-MIB::ifDescr.150001 = STRING: aal5-1 IF-MIB::ifDescr.150002 = STRING: aal5-2 IF-MIB::ifDescr.150003 = STRING: aal5-3 IF-MIB::ifDescr.150004 = STRING: aal5-4 IF-MIB::ifDescr.150005 = STRING: aal5-5 IF-MIB::ifDescr.150006 = STRING: aal5-7 IF-MIB::ifDescr.150007 = STRING: aal5-6
En este caso, nos interesa la interfaz dsl-0
, de modo que apuntamos su número (4000). Una vez hecho esto, buscamos las entradas MIB ifInOctets
y ifOutOctets
, que son las que devuelven los valores de los bytes recibidos y enviados. Hay varias formas de encontrarlas, pero la mejor manera (para el sistema) es por su valor numérico, de modo que utilizaremos los siguientes comandos:
snmptranslate -Tz | grep ifInOctets snmptranslate -Tz | grep ifOutOctets
Deberíamos obtener valores como estos:
1.3.6.1.2.1.2.2.1.10 1.3.6.1.2.1.2.2.1.16
Si deseamos conocer el significado de esta secuencia de números, podemos utilizar el siguiente comando:
snmptranslate -Onf -IR ifInOctets
Obtendremos algo como esto:
.org.dod.internet.mgmt.mib-2.interfaces.ifTable.ifEntry.ifInOctets
De todas maneras, consultaremos ahora el enrutador con la secuencia de números que obtuvimos, y al final agregaremos el número de la interfaz que obtuvimos anteriormente (4000):
snmpget -v1 -c MiComunidad 192.168.1.1 .1.3.6.1.2.1.2.2.1.10.40000 .1.3.6.1.2.1.2.2.1.16.40000
Deberíamos obtener algo como esto:
IF-MIB::ifInOctets.40000 = Counter32: 78906432 IF-MIB::ifOutOctets.40000 = Counter32: 26193216
Esto significa que el enrutador está respondiendo con los valores que tienen los contadores, que son los que necesitaremos para poblar la base de datos.
Como mencionamos anteriormente, para poblar la base de datos, utilizaremos un script de bash
, que consulte al enrutador y envíe los valores obtenidos a la base de datos. Como la consulta debe hacerse cada diez segundos, a mi se me ocurrió algo simple como esto:1)
#! /bin/sh REPEAT=1 RRDATAFILE=/var/log/rrd/enrutador.rrd while [ "$REPEAT" -eq 1 ]; do BYTESIN=$(snmpget -v1 -c MiComunidad 192.168.1.1 .1.3.6.1.2.1.2.2.1.10.40000 | awk '{print $4}') BYTESOUT=$(snmpget -v1 -c MiComunidad 192.168.1.1 .1.3.6.1.2.1.2.2.1.16.40000 | awk '{print $4}') rrdtool update $RRDATAFILE N:$BYTESIN:$BYTESOUT sleep 10 done
Como vemos, en este caso, utilizamos el comando snmpget
en un ciclo que se repite mientras se ejecute el script, extraemos solo las cifras de los contadores mediante el comando AWK, las asignamos a variables, y luego las pasamos a la base de datos mediante el comando rrdtool update
(aquí N significa la hora actual). Al final se hace una pausa de 10 segundos.
Podría utilizarse otra variante sin ciclo y simplemente llamar el script desde una tarea programada, pero crontab
tiene un límite inferior de un minuto.
De modo que como no utilizaremos crontab
, queda decidir desde dónde llamaremos al script. Tiene sentido que se consulte al enrutador en cuanto el servidor levante las interfaces de red, asi que por ejemplo, podríamos colocar el script (que por cierto, debe tener permisos de ejecución) en /etc/network/if-up.d/
o también puede agregarse esta línea al archivo /etc/network/interfaces
:
up /etc/network/enrutador.sh &
Una vez terminado este paso, podemos reiniciar la red o la interfaz, o simplemente llamar el script manualmente para que comience a llenar la base de datos. En todo caso, debemos esperar algunos minutos antes de hacer nuestra primera graficación, porque de lo contrario solo veremos unas barras enormes.
Evidentemente, la parte más interesante y creativa es la graficación. Con RRDTool pueden hacerse gráficos realmente complejos, pues las versiones recientes soportan incluso niveles de transparencia.
(Pretendo terminar esta sección pronto, pero para los impacientes, aqui va un script que ejemplifica como utilizar el comando de graficación.)
#! /bin/sh RRDATAFILE=/var/log/rrd/enrutador.rrd if [ $# -lt 2 ]; then echo "Faltan los momentos de inicio y fin. Ej. (end-6h now)" exit 0 else sudo rrdtool graph /var/www/rrd/rrdtool_ejemplo.png --imgformat PNG \ --start $1 --end $2 \ --title "Comportamiento del enlace" \ --vertical-label "Tasa de transferencia (kbps)" \ --upper-limit 160 \ --lower-limit 0 \ --rigid \ --width 600 --height 240 \ DEF:dsin=$RRDATAFILE:in:AVERAGE \ DEF:dsout=$RRDATAFILE:out:AVERAGE \ CDEF:download=dsin,0.008,* \ CDEF:down96=download,96,GT,0,download,IF \ CDEF:down64=download,64,GT,0,download,IF \ CDEF:down32=download,32,GT,0,download,IF \ CDEF:down13=download,13,GT,0,download,IF \ CDEF:upload=dsout,0.008,* \ HRULE:128#0000FF:"Capacidad contratada (128 kbps)\n" \ AREA:download#35DF7F:"Recepción superior al 75%\n" \ AREA:down96#AFDF3F:"Recepción inferior al 75% (96 kbps)\n" \ AREA:down64#EFDF1F:"Recepción inferior al 50% (64 kbps)\n" \ AREA:down32#FF9F00:"Recepción inferior al 25% (32 kbps)\n" \ AREA:down13#FF0000:"Recepción inferior al 10% (13 kbps)\n" \ LINE1:download#006000 \ LINE1.5:upload#005FBF:"Envío" fi exit 0
El primer parámetro que espera recibir el script es el timestamp de inicio y el segundo es el timestamp final, donde cada timestamp es la cantidad de segundos transcurridos desde 1970-01-01 00:00:00 UTC.
Afortunadamente, Oetiker también implementó abreviaturas al estilo de horario del comando at
:
Abreviatura | Significado |
---|---|
now | El momento actual |
s | Segundos |
h | Horas |
d | Días |
w | Semanas |
m | Meses |
y | Años |
start | Referencia al momento inicial |
end | Referencia al momento final |
midnight | 00:00 |
noon | 12:00 |
teatime | 16:00 |
yesterday | Referencia al día anterior |
today | Referencia al día actual |
tomorrow | Referencia al día próximo |
epoch | 1970-01-01 00:00:00 UTC |
Además puede utilizarse la hora (en formato de 24 horas), el nombre de los días (en inglés) o la fecha en alguno de estos formatos:
Esto facilita la invocación de nuestro script, por ejemplo, para obtener la última hora:
./graficar.sh now-1h now
Con RRDTool se pueden obtener resultados visualmente superiores a los que brinda MRTG, aqui tienen un ejemplo del gráfico generado con el script anterior: