Graficación personalizada con Cacti

Tras mucho tiempo en borradores, por fin he terminado esta entrada, y lo he hecho principalmente debido a que recientemente me he visto en la necesidad de utilizar nuevamente cacti y ya no recordaba como crear gráficas personalizadas, que es el objetivo de este blog, así que desempolvé mis apuntes y aquí está 🙂

Una de las herramientas mas útiles para un SysAdmin es Cacti, a simple vista, una herramienta fea que encierra una utilidad tremenda para ver de un vistazo el estado de nuestra plataforma…, comportamientos que nos puedan hacer anticipar un posible fallo cercano o que estén fuera de lugar, permitiéndonos tomar acciones preventivas, o en caso que ya estemos en medio de una crisis, nos puede ayudar a vislumbrar por donde puede ir el problema, orientándonos en una dirección o en otra para resolver lo antes posible la emergencia. De por si, Cacti ya trae muchos “templates” para redes y máquinas que nos serán muy útiles, además de la gran cantidad de templates (para MySQL, Switches, NAS…) que la comunidad que existe en torno a Cacti ha creado, pero lo mas normal es que necesitemos graficar algo de nuestra plataforma que se salga de lo habitual, o queramos algo mas concreto que lo que esos templates nos dan, momento en el cual sacaremos nuestra vena desarrolladora y con ayuda de nuestro lenguaje de scripting favorito (Python en mi caso), crearemos nuestra propia gráfica de forma rápida y sencilla.

Balanceador de Carga

Gráfica de conexiones HTTP en Tiempo Real a un KeepAlived

Entendamos un poco como funciona Cacti… Cacti no es mas que un poller que periódicamente (5 minutos en la instalación básica) consulta por SNMP o lanza los scripts configurados para una serie de hosts que tiene almacenados en una base de datos MySQL, almacenando los valores devueltos en una series de ficheros .rrd, pertenecientes a RRDtool (RoundRobin Database Tool), una herramienta que permite guardar los datos en ficheros estructurados en buffers de forma circular, con marcas temporales, de tal forma que cada dato está asociado a un momento concreto, lo que nos permite posteriormente dibujarlo en gráficas cuyo eje X es un eje temporal. En la opción mas simple, el poller lanzará cada 5 minutos (o el tiempo que tengamos configurado) nuestro script, analizará la salida que devuelva este, y la incorporará en el fichero rrd correspondiente. Otra opción es que nuestro propio script actualice el fichero rrd con los valores obtenidos. Esto es útil si queremos almacenar datos con una frecuencia mayor que la que Cacti nos proporciona, pues al final se basa en el cron, y el intervalo mínimo sería de 1 minuto, lo que puede ser excesivo, por ejemplo para el caso de un Balanceador de Carga, el Script está constantemente recopilando datos, por lo que no podemos hacer uso del poller. CactiLog

Lo único que necesitamos es tener claro que es lo que queremos graficar, e implementarlo en un script Python, sabiendo que la salida del script debe ser uno o varios valores numéricos, para que Cacti sea capaz de interpretarlos y pintarlos en nuestra gráfica.

Tal como he comentado antes, existen dos maneras para actualizar los valores de los ficheros RRD, que utilizaremos según mas nos convenga:

  • Una manera mas elegante, a través del poller de Cacti, de tal manera que nuestro script devolverá como salida los valores y variables que queremos que cacti almacene
  • Y una manera no tan elegante, en la que será nuestro propio script el encargado de actualizar directamente el fichero RRD

A continuación un pequeño ejemplo de Script en Python que nos devolvería el espacio libre y ocupado de una partición, en este caso utilizando el poller de cacti.

import sys
from subprocess import STDOUT, PIPE, Popen
from tempfile import NamedTemporaryFile
### Variables ###
usuario = "user"
particion = "MD0"

#Procedimiento que ejecuta comandos remotos y devuelve el resultado
# comando: Comando Bash a ejecutar
# Return: Primera linea devuelta por la ejecucion del comando.
def ejecutarComando(comando):
    tmpout = NamedTemporaryFile(mode='w+')
    p = Popen(comando, stdout=PIPE, stderr=PIPE, shell=True)
    pstdout, pstderr = p.communicate()
    tmpout.write(pstdout)
    tmpout.seek(0) #Regresamos al principio del archivo
    fichero = open(tmpout.name,'r')
    linea = fichero.readline().strip()
    return linea

#Procedimiento que obtiene el espacio libre, usado y ocupado de una particion dada
#y lo pinta en pantalla
# host: IP/FQDN del host del que queremos obtener los datos de espacio
# part: Particion que chequearemos
# Return: Este procedimiento no devuelve valores
def espacioParticion(host,part):
    comando = "ssh "+usuario+"@"+host+" df | grep "+part
    cadena = ejecutarComando(comando).split()
    total = str(int(cadena[1])*1024)
    usado = str(int(cadena[2])*1024)
    libre = str(int(cadena[3])*1024)
    print "TOTAL:"+total+" USED:"+usado+" FREE:"+libre

## INICIO ##
host = sys.argv[1]#Obtenemos el argumento que nos pasan de entrada y que sera el host a monitorizar
espacioParticion(host,particion)

Como podemos ver, el script devolverá por pantalla la siguiente cadena: “TOTAL:XXXX USED:YYYY FREE:ZZZZ”. Cacti analizará esta salida y realizará un match con las variables que está esperando (y que veremos mas adelante como configurar) y almacenará los datos en el fichero RRD.

Una vez tengamos nuestro script listo, será hora de crear lo necesario en Cacti para poder mostrar la información. En esta guía no crearé templates, si no que lo haremos por la vía sencilla, siguiendo estos pasos:

  1. Creamos el Script en nuestro lenguaje favorito
  2. Creamos un “Data Input Method”, que llamará a nuestro script pasándole los parámetros oportunos, y especificará que salida espera Cacti
  3. Creamos un “Data Sources”, que especificará la ruta (automática) del RRD, el host al que se le aplica, el Data Template (que no usaremos en este caso) y establecerá los Data Source Items que contendrá el RRD
  4. Creamos la gráfica que mostrará los datos
  5. Añadimos la gráfica al árbol de gráficas

Data Input Method

Data Input Method

En el Data Input Method elegiremos que método queremos para recopilar los datos, en este caso un Script/Command, especificaremos la ruta y el intérprete para el script, elegiremos las entradas que se le pasarán al script, ninguna en este caso, y cuales son las salidas que esperamos del mismo.

El Name de los “Output Fields” deberá coincidir con el texto que escribirá nuestro script en su salida, para que cacti pueda hacer un match con el mismo, pero podemos poner un nombre mas ‘amigable’ en el campo de “Friendly Name” para nuestra comodidad.

Una vez que lo tengamos todo completado, nos aseguraremos que nuestro PHP puede alcanzar la ruta que hemos seleccionado para el script, en caso contrario deberemos modificar el open_basedir de nuestro php.ini para asegurarnos que la carpeta es accesible, y procederemos a salvar.

Data SourcesData Source

En el Data Source elegiremos un nombre para nuestra fuente de datos, y algo muy importante, el Step, que es el tiempo en segundos entre actualizaciones de nuestro RRD. Si cambiamos este dato en algún momento, deberemos eliminar el fichero RRD y crearlo de nuevo, pues cambiará sustancialmente.

En esta sección deberemos añadir un Data Source Item por cada elemento que devuelva nuestro script, teniendo buen cuidado de seleccionar el “Output Field” correcto, ya que el match que cacti haga con la salida de nuestro script se usará para el campo que elijamos aquí, y teniendo también muy en cuenta el “Maximum Value”, que será el valor máximo que esperamos que nos devuelva nuestro script. En caso que nos quedemos cortos veremos como la gráfica nos indica NaN, y no mostrará ningún valor ni pintará ese campo.

Graph Management

Graph Management

En la zona de administración de gráficas añadiremos una nueva, y comenzaremos la ardua tarea de configurar qué queremos ver en la gráfica, para ello iremos añadiendo los Items que queremos mostrar, ordenándolos según queramos.

Graph Item

Las opciones de configuración de cada Item darían para una entrada por si mismas, pero veremos de un somero vistazo algunas de las mas importantes:

  • Data Source – Aquí elegiremos que elemento es el que queremos mostrar
  • Color – Obviamente el color del elemento a mostrar
  • Graph Item Type – Tipo de Item, los mas utilizados serán Área (sección completa de dibujo), Stack (apilado de datos), Gprint (Texto de leyenda) y Line (Líneas)
  • Text Format – Texto que se mostrará. En caso que seleccionemos Area,Stack o Line, esto hará que en la leyenda se muestre lo que es cada color
  • Hard Return – Introducir un “enter” en la leyenda tras este elemento

Graph Tree

Graph Tree

Cuando ya tenemos lista nuestra gráfica, llega el momento de mostrarla en Cacti, por lo que iremos al Graph Tree y procederemos a añadirla en la sección que deseemos.

Apache Graph

Y con eso estaremos listos! Espero que os haya sido de utilidad y gracias por visitarme!

Málaga, Febrero de 2014