Tabla de Contenidos

Graficar tráfico del enlace con RRDTool

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.

Introducción a RRDTool

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:

Instalación y configuración

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 :

Creación de la base de datos

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:

creardatos.sh
#! /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:

Consultar el dispositivo

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.

Registrar los 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)

enrutador.sh
#! /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.

Graficar

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.)

graficar.sh
#! /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

Resultados

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:

Atribuciones

1)
Es probable que puedan encontrarse soluciones más eficientes (como crear un daemon), pero esta al menos funciona y se prepara rápido.