Diferencia entre revisiones de «Plataforma Logs»

De Ardemans Wiki
Saltar a: navegación, buscar
(Optimizaciones del proceso)
(Agentes de Logstash)
 
(14 revisiones intermedias por el mismo usuario no mostrado)
Línea 180: Línea 180:
 
'''También se puede revisar, para propositos de rendimiento, añadir el parámetro de bloqueo de uso de memoria, para garantizar que el proceso de elasticsearch no usa memoria swap, ya que eso hace que el rendimiento de la jvm caiga en picado'''
 
'''También se puede revisar, para propositos de rendimiento, añadir el parámetro de bloqueo de uso de memoria, para garantizar que el proceso de elasticsearch no usa memoria swap, ya que eso hace que el rendimiento de la jvm caiga en picado'''
  
 +
=== Tareas de mantenimiento de Elasticsearch ===
 +
==== Borrado automático de indices para un solo servidor ====
 +
En el caso de que solo tengamos un nodo he creado un script en ruby que borrar el índice más antiguo cuando nos acercamos a un umbral de espacio libre en el disco que contiene los indices.
 +
 +
El script es el siguiente:
 +
 +
<pre>
 +
#!/usr/bin/ruby
 +
 +
ESDATADISK='/mnt/esdata'
 +
TARGETFREESIZE=10485760
 +
ESSERVER='localhost'
 +
ESPORT='9200'
 +
 +
require "rubygems"
 +
require "json"
 +
require "net/http"
 +
require "uri"
 +
 +
def openurl(url)
 +
Net::HTTP.get(URI.parse(url))
 +
end
 +
 +
def deleteindex(indexname)
 +
puts "SE BORRARA INDICE #{indexname}"
 +
 +
http = Net::HTTP.start(ESSERVER, ESPORT)
 +
response = http.send_request('DELETE',"/#{indexname}")
 +
puts "RESPUESTA DEL DELETE: #{response}"
 +
 +
end
 +
 +
def getfreesize(disk)
 +
freesize = `df #{disk} |grep #{disk} |awk '{print $4}'`
 +
puts "respuesta #{freesize}"
 +
return freesize
 +
end
 +
 +
 +
starttime = Time.now
 +
 +
puts "* #{starttime.inspect}"
 +
 +
diskfree = getfreesize(ESDATADISK)
 +
puts "Disco disponible: #{diskfree}"
 +
 +
 +
if diskfree.to_i < TARGETFREESIZE
 +
 +
puts "Alcanzado umbral"
 +
 +
respuesta = openurl('http://localhost:9200/_status')
 +
json_respuesta = JSON.parse(respuesta)
 +
 +
indexcounter = 0
 +
json_respuesta["indices"].sort.each do |key_indice,data_indice|
 +
 +
if key_indice['logstash']
 +
indexcounter = indexcounter + 1
 +
puts "#{indexcounter} #{key_indice} #{data_indice["index"]["size_in_bytes"]}"
 +
if indexcounter == 1
 +
deleteindex(key_indice)
 +
end
 +
end
 +
 +
end
 +
 +
end
 +
</pre>
 +
 +
Y se ejecuta cada hora desde el crontab del usuario root:
 +
 +
<pre>
 +
59 * * * * /usr/bin/ruby /opt/elasticsearch/bin/ESdeleteoldindex.rb >> /var/log/ESdeleteoldindex.log 2>&1
 +
</pre>
  
 
== Instalacion de Kibana ==
 
== Instalacion de Kibana ==
Línea 215: Línea 290:
 
</pre>
 
</pre>
  
 +
=== Kibana 3 ===
 +
 +
Existe una nueva versión de kibana más avanzada, y que además está escrita en html y js completamente. La característica más llamativa de esta version es que es el browser del cliente el que tiene que lanzar las consultas didrectamente al ES.
 +
 +
La web de esta version es esta:http://three.kibana.org/ donde están los enlaces de descarga y las instrucciones de instalación. En realidad, la instalación es muy sencilla, ya que solo son muchos estaticos y js que han de estar disponibles para un navegador.
 +
 +
 +
 +
== Agentes de Logstash ==
 +
Logstash se descarga como un único jar, que dependiendo de los parámetros de ejecución y el fichero de configuración que le especifiquemos, sirve como agente o como frontal web. Nosotros solo lo usaremos como agente.
 +
 +
Para ejecutar un agente solo tendremos que ejecutar el java de la siguiente manera:
 +
 +
<pre>
 +
java -jar logstash-1.1.10-flatjar.jar agent -f indexer.conf
 +
</pre>
 +
 +
En el fichero de configuracion le especificamos el comportamiento que va a tener este agente, si por ejemplo va a escuchar por un puerto UDP para recibir los datos, o si los va a coger de un redis; y también, una vez recogidos, que filtros va a pasar a los datos y cual es el destino de estos.
 +
 +
En nuestro caso tenemos dos tipos de logstash agent:
 +
 +
* Fichero que recibe datos por UDP y los manda a una cola en REDIS:
 +
 +
<pre>
 +
input {
 +
        udp {
 +
                type    => "accesslog"
 +
                port    => 9999
 +
        }
 +
}
 +
 +
 +
filter {
 +
 +
        split {
 +
                type            => "accesslog"
 +
        }
 +
 +
}
 +
 +
output {
 +
        redis {
 +
                type            => "accesslog"
 +
                host            => "127.0.0.1"
 +
                port            => "6379"
 +
                data_type      => "list"
 +
                key            => "accesslog"
 +
        }
 +
}
 +
</pre>
 +
 +
 +
* Por otro lado tenemos el fichero que recoge los datos de REDIS, los procesa y los manda a elasticsearch
 +
 +
<pre>
 +
input {
 +
        redis {
 +
                host    => "127.0.0.1"
 +
                port    => "6379"
 +
                type => "accesslog"
 +
                data_type => "list"
 +
                key => "accesslog"
 +
                format => "json_event"
 +
        }
 +
}
 +
 +
 +
filter {
 +
 +
        grok {
 +
                type            => "accesslog"
 +
                pattern        => "%{WORD:source} %{DATA:host} %{DATA:logname} %{DATA:user} \[%{DATA:date}\] %{HOSTNAME:hostheader} \"%{DATA:method} %{DATA:path} %{DATA:protocol}\" %{NUMBER:code} %{DATA:size:int} %{NUMBER:duration:int} \"%{DATA:cache}\" %{WORD:server}"
 +
        }
 +
 +
        mutate {
 +
                type            => "accesslog"
 +
                add_field      => [ "hostheaderfix", "%{hostheader}" ]
 +
                gsub            => [ "cache", "\.", "_" ]
 +
        }
 +
 +
        mutate {
 +
                type            => "accesslog"
 +
                gsub            => [ "hostheaderfix", "\.", "_" ]
 +
        }
 +
 +
}
 +
 +
 +
 +
output {
 +
 +
        elasticsearch {
 +
                host    => "127.0.0.1"
 +
        }
 +
 +
        statsd {
 +
                type            => "accesslog"
 +
                host            => "10.90.9.129"
 +
                sender          => "http"
 +
                increment      => [
 +
                                        "%{source}.responsecode.%{code}",
 +
                                        "%{source}.hostheader.%{hostheaderfix}",
 +
                                        "%{source}.method.%{method}",
 +
                                        "%{source}.cache.%{cache}",
 +
                                        "%{source}.servers.%{server}.hits"
 +
 +
                                ]
 +
                count          => [
 +
                                        "%{source}.size", "%{size}"
 +
                                ]
 +
        }
 +
}
 +
</pre>
 +
 +
Para tener un arranque automático de la tarea de procesado de logs (indexer.conf) he creado el siguiente script de inicio:
 +
 +
<pre>
 +
#!/bin/sh
 +
#
 +
# logstash indexer
 +
#
 +
# chkconfig: 2345 95 50
 +
# description: Script de inicio de los procesos de indexacion de logs
 +
#              PSD - Pedro Miguel Blanco
 +
#              15/05/2013
 +
#
 +
 +
 +
# Nombre de este demonio
 +
LOGSTASH_PROCNAME="logstash-indexer"
 +
 +
# Numero de Workers
 +
LOGSTASH_WORKERS=4
 +
 +
# Definicion del entorno
 +
LOGSTASH_JAR="/opt/logstash/logstash-1.1.12-flatjar.jar"
 +
JAVA_HOME="/opt/java"
 +
JAVA="$JAVA_HOME/bin/java"
 +
 +
# Fichero de configuracion del indexer
 +
LOGSTASH_INDEXER_CONF="/opt/logstash/indexer.conf"
 +
 +
# Directorio de salida de logs
 +
LOGSTASH_INDEXER_LOG="/var/log/$LOGSTASH_PROCNAME.log"
 +
 +
# Directorio de pidfiles
 +
LOGSTASH_INDEXER_PIDFILE="/var/run/$LOGSTASH_PROCNAME.pid"
 +
 +
# Incluimos funciones de inicio de RedHat/CentOS
 +
. /etc/rc.d/init.d/functions
 +
 +
 +
 +
# FUNCIONES ------
 +
 +
start() {
 +
 +
        START_COMMAND="$JAVA -jar $LOGSTASH_JAR agent -f $LOGSTASH_INDEXER_CONF -w $LOGSTASH_WORKERS -l $LOGSTASH_INDEXER_LOG"
 +
        echo -n "Starting logstash indexer process: $LOGSTASH_PROCNAME"
 +
        daemon --pidfile $LOGSTASH_INDEXER_PIDFILE "$START_COMMAND &"
 +
        RETVAL=$?
 +
        echo
 +
        set_pidfile
 +
        return $RETVAL
 +
}
 +
 +
stop() {
 +
        echo -n "Stopping logstash indexer process: $LOGSTASH_PROCNAME"
 +
        killproc -p "$LOGSTASH_INDEXER_PIDFILE" -d 10
 +
        RETVAL=$?
 +
        echo
 +
        return $RETVAL
 +
}
 +
 +
status() {
 +
        if [ -f $LOGSTASH_INDEXER_PIDFILE ]; then
 +
                PID=$(cat $LOGSTASH_INDEXER_PIDFILE)
 +
                ps $PID > /dev/null
 +
                RETVAL=$?
 +
                if [ $RETVAL == 1 ]; then echo "PID FILE EXISTS BUT PROCCESS NOT RUNNIG"; fi
 +
        else
 +
                RETVAL=1
 +
        fi
 +
 +
        echo -n "Logstash indexer process: "
 +
 +
        if [ $RETVAL == 0 ]; then
 +
                echo "STARTED"
 +
        else
 +
                echo "STOPPED!!!"
 +
        fi
 +
        return $RETVAL
 +
}
 +
 +
 +
set_pidfile() {
 +
        PID=$(ps x |grep "$LOGSTASH_INDEXER_LOG" |grep -v grep | awk '{print $1}' )
 +
        if [ -n "$PID" ]; then
 +
                echo $PID > $LOGSTASH_INDEXER_PIDFILE
 +
        fi
 +
        return $PID
 +
}
 +
 +
 +
 +
case "$1" in
 +
 +
        start)
 +
                start
 +
                ;;
 +
        stop)
 +
                stop
 +
                ;;
 +
        status)
 +
                status
 +
                ;;
 +
        restart)
 +
                stop
 +
                start
 +
                ;;
 +
        *)
 +
                echo "Usage: $0 {start|stop|restart|status}"
 +
                ;;
 +
esac
 +
 +
 +
exit $RETVAL
 +
</pre>
 +
 +
Existen diferentes versiones del agente logstash, flatjar y monolithic. La diferencia entre estas dos versinoes es que la primera está empaquetada y preparada para optimizar el proceso de arranque. Se puede leer algo más [http://cookbook.logstash.net/recipes/faster-startup-time/ aqui]
  
 
== Instalación de graphite ==
 
== Instalación de graphite ==
Línea 391: Línea 696:
  
  
 +
=== Script de arranque automático de Carbon-cache ===
  
 +
Como script de arranque automático hemos creado el fichero /opt/graphite/bin/carbon-cache.init, y después hemos hecho un enlace simbólico desde /etc/init.d/
 +
 +
<pre>
 +
#!/bin/bash
 +
#
 +
# carbon-cache - This script starts and stops the carbon-cache service.
 +
#
 +
# chkconfig:  - 85 15
 +
# description: carbon-cache accepts graphite metrics and writes them to
 +
#              disk using whisper
 +
# processname: carbon-cache.py
 +
# config:      /etc/sysconfig/carbon-cache
 +
 +
# Source function library.
 +
. /etc/rc.d/init.d/functions
 +
 +
# Source networking configuration.
 +
. /etc/sysconfig/network
 +
 +
# Check that networking is up.
 +
[ "$NETWORKING" = "no" ] && exit 0
 +
 +
CARBON_HOME="/opt/graphite"
 +
 +
exec="$CARBON_HOME/bin/carbon-cache.py"
 +
prog=$(basename "$exec")
 +
CARBON_CONFIG_PATH="$CARBON_HOME/conf/carbon.conf"
 +
CARBON_CACHE_ARGS=""
 +
CARBON_CACHE_PIDFILE="/var/run/carbon-cache.pid"
 +
GRAPHITE_STORAGE_DIR="$CARBON_HOME/storage"
 +
 +
export GRAPHITE_STORAGE_DIR
 +
 +
restart() {
 +
    stop
 +
    start
 +
}
 +
 +
rh_status() {
 +
    status -p "$CARBON_CACHE_PIDFILE" "$prog"
 +
}
 +
 +
start() {
 +
    echo -n 'Starting carbon-cache...'
 +
    daemon --pidfile="$CARBON_CACHE_PIDFILE" "$exec" start $args \
 +
      --config="$CARBON_CONFIG_PATH" --pidfile="$CARBON_CACHE_PIDFILE" >/dev/null
 +
    retval=$?
 +
    echo
 +
    return $retval
 +
}
 +
 +
stop() {
 +
    echo -n 'Stopping carbon-cache...'
 +
    killproc -p "$CARBON_CACHE_PIDFILE" "$prog"
 +
    retval=$?
 +
    echo
 +
    return $retval
 +
}
 +
 +
case $1 in
 +
    condrestart|try-restart)
 +
        rh_status 2>/dev/null && restart
 +
        ;;
 +
    reload|force-reload)
 +
        restart
 +
        ;;
 +
    restart)
 +
        restart
 +
        ;;
 +
    start)
 +
        start
 +
        ;;
 +
    status)
 +
        rh_status
 +
        ;;
 +
    status_q)
 +
        rh_status >/dev/null 2>&1
 +
        ;;
 +
    stop)
 +
        stop
 +
        ;;
 +
    *)
 +
        echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload}"
 +
        exit 2
 +
        ;;
 +
esac
 +
 +
exit $?
 +
 +
</pre>
 +
 +
=== Tareas automáticas de mantenimiento ===
 +
Hacemos un rotado manual de los logs con comandos find en el crontab del usuario root. Para ello, ejecutamos el comando '''crontab -e''' desde el usuario root y añadimos las dos siguientes líneas:
 +
 +
<pre>
 +
21 1 * * * /bin/find /opt/graphite/storage/log/carbon-cache/carbon-cache-a/ -name "*log.*[0-9]" -type f -mtime +0 -exec gzip {} \;
 +
23 1 * * * /bin/bind /opt/graphite/storage/log/carbon-cache/carbon-cache-a/ -name "*.gz" -type f -mtime +5 -exec rm -f {} \;
 +
</pre>
  
 
== Instalacion de StatsD ==
 
== Instalacion de StatsD ==
Línea 486: Línea 890:
 
<pre>
 
<pre>
 
node stats.js config.js
 
node stats.js config.js
 +
</pre>
 +
 +
Para el arranque automático he creado el script /opt/statsd/statsd.init:
 +
 +
<pre>
 +
#!/bin/bash
 +
#
 +
# StatsD
 +
#
 +
# chkconfig: 3 50 50
 +
# description: StatsD init.d
 +
. /etc/rc.d/init.d/functions
 +
 +
prog=statsd
 +
STATSDDIR=/opt/statsd
 +
statsd=$STATSDDIR/stats.js
 +
LOG=/var/log/statsd.log
 +
ERRLOG=/var/log/statsderr.log
 +
CONFFILE=${STATSDDIR}/config.js
 +
pidfile=/var/run/statsd.pid
 +
lockfile=/var/lock/subsys/statsd
 +
nodebin=/opt/nodejs/bin/node
 +
RETVAL=0
 +
STOP_TIMEOUT=${STOP_TIMEOUT-10}
 +
 +
start() {
 +
        echo -n $"Starting $prog: "
 +
        cd ${STATSDDIR}
 +
 +
        # See if it's already running. Look *only* at the pid file.
 +
        if [ -f ${pidfile} ]; then
 +
                failure "PID file exists for statsd"
 +
                RETVAL=1
 +
        else
 +
                # Run as process
 +
                daemon "${nodebin} ${statsd} ${CONFFILE} >> ${LOG} 2>> ${ERRLOG} &"
 +
                RETVAL=$?
 +
 +
                # Store PID
 +
                #echo $! > ${pidfile}
 +
                ps a |grep ${CONFFILE} | grep -v grep | awk '{print $1}' > ${pidfile}
 +
 +
                # Success
 +
                [ $RETVAL = 0 ] && success "statsd started"
 +
        fi
 +
 +
        echo
 +
        return $RETVAL
 +
}
 +
 +
stop() {
 +
        echo -n $"Stopping $prog: "
 +
        killproc -p ${pidfile}
 +
        RETVAL=$?
 +
        echo
 +
        [ $RETVAL = 0 ] && rm -f ${pidfile}
 +
}
 +
 +
# See how we were called.
 +
case "$1" in
 +
  start)
 +
        start
 +
        ;;
 +
  stop)
 +
        stop
 +
        ;;
 +
  status)
 +
        status -p ${pidfile} ${prog}
 +
        RETVAL=$?
 +
        ;;
 +
  restart)
 +
        stop
 +
        start
 +
        ;;
 +
  condrestart)
 +
        if [ -f ${pidfile} ] ; then
 +
                stop
 +
                start
 +
        fi
 +
        ;;
 +
  *)
 +
        echo $"Usage: $prog {start|stop|restart|condrestart|status}"
 +
        exit 1
 +
esac
 +
 +
exit $RETVAL
 +
</pre>
 +
 +
He creado un enlace simbólico en /etc/init.d de este fichero y activado el arranque automático
 +
 +
<pre>
 +
chkconfig statsd.init on
 
</pre>
 
</pre>
  
Línea 516: Línea 1012:
  
 
== Optimizaciones del proceso ==
 
== Optimizaciones del proceso ==
 +
 +
=== Logstash ===
 +
 +
Durante el arranque del proceso de logstash se puede especificar el número de hilos que se van a lanzar para procesar los filtros. Este parámetro es '''-w''' y va acompañado del numero de hilos que queremos ejecutar.
 +
 +
Este parámetro debería ir en consonancia con el numero de hilos que recepcionan el contenido, sobre todo (y esto si lo he probado) si el plugin de inserccion es el que recoge datos de redis. En ese INPUT existe el parámetro threads, con el que le decimso la cantidad de hilos con el que vamos a ir a buscar datos a redis.
 +
 +
Poniendo estos dos parámetros con el mismo número de hilos (el numero de cores de la máquina) hace que mejore el rendimiento de procesado de las entradas de log, hasta aprovechar el máximo de la máquina.
  
 
=== Elasticsearch ===
 
=== Elasticsearch ===
Línea 625: Línea 1129:
 
http://tranlogpol01.prisadigital.int:9200/_nodes/?pretty=on&all
 
http://tranlogpol01.prisadigital.int:9200/_nodes/?pretty=on&all
 
</pre>
 
</pre>
 +
 +
 +
==== Template ====
 +
Existen ya templates de indices especificos para logstash, mis primeras pruebas han sido usando el siguiente template
 +
 +
https://gist.github.com/deverton/2970285
  
 
=== Graphite ===
 
=== Graphite ===
Línea 637: Línea 1147:
 
<falta contar el como hice el balanceo de carga los agent de logstas>
 
<falta contar el como hice el balanceo de carga los agent de logstas>
 
<Logstash que encola entradas y varios agent procesando>
 
<Logstash que encola entradas y varios agent procesando>
 +
 +
= Otras herramientas y complmentos para la monitorizacion =
 +
 +
== BrighcoveOS Diamond ==
 +
(por documentar)
 +
 +
== Elastic Search paramedic ==
 +
 +
Para una motorización online de ElastcSearch podemos usar la herramienta [https://github.com/karmi/elasticsearch-paramedic.git ElasticSearch Paramedic]. Es una app web que solo necesita publicación http, y las consultas se realizan desde el cliente.
 +
 +
La descarga del repositorio git la he hecho en /opt/esparamedic
 +
 +
<pre>
 +
cd /opt/esparamedic
 +
git clone https://github.com/karmi/elasticsearch-paramedic.git
 +
</pre>
 +
 +
Después configuramos un vhost apuntando a este directorio en nuestro apache
 +
 +
<pre>
 +
<VirtualHost *:80>
 +
        ServerName esparamedic.logs.prisadigital.int
 +
        DocumentRoot "/opt/esparamedic"
 +
        ErrorLog /var/log/httpd/esparamedic-error.log
 +
        CustomLog /var/log/httpd/esparamedic-access.log common
 +
 +
        <Directory /opt/esparamedic/>
 +
                Order deny,allow
 +
                Allow from all
 +
        </Directory>
 +
 +
</VirtualHost>
 +
</pre>
 +
 +
He añadido un registro en el DNS a ese vhost y al entrar solo hay que especificar la URL del elasticsearch

Última revisión de 14:21 3 jul 2013

Instalacion de redis

Para la instalación de redis primero nos bajamos la versión estable más reciente desde http://redis.io/download. En nuestro caso nos hemos bajado la version redis-2.6.12, y lo hemos descargado a /usr/src/redis-2.6.12.tar.gz. En ese mismo directorio lo hemos desempaquetado.

La compilación la hemos realizado de la siguiente manera:

make PREFIX=/opt/redis-2.6.12
make install PREFIX=/opt/redis-2.6.12

Después he copiado el fichero de configuración redis.conf en /opt/redis-2.6.12/etc. Antes he creado ese directorio

Tambien he creado los directorios

/opt/redis-2.6.12/var /opt/redis-2.6.12/var/log /opt/redis-2.6.12/var/data /opt/redis-2.6.12/var/run

Tambien se crea un enlace simbólico

ln -s /etc/redis-2.6.12 /etc/redis

En el fichero de configuración hemos cambiado los datos referentes a donde se guardan los logs, y tambien el parametro "dir" que indica cual es el directorio de datos.

Añadimos el siguiente fichero de inicio de redis para centos al /etc/init.d/redisd

#!/bin/sh
#
# redis - this script starts and stops the redis-server daemon
#
# chkconfig:   - 85 15
# description:  Redis is a persistent key-value database
# processname: redis-server
# config:      /etc/redis/redis.conf
# config:      /etc/sysconfig/redis
# pidfile:     /var/run/redis.pid

# Source function library.
. /etc/rc.d/init.d/functions

# Source networking configuration.
. /etc/sysconfig/network

# Check that networking is up.
[ "$NETWORKING" = "no" ] && exit 0

prefix="/opt/redis"

redis="$prefix/bin/redis-server"
prog=$(basename $redis)

REDIS_CONF_FILE="$prefix/etc/redis.conf"

[ -f /etc/sysconfig/redis ] && . /etc/sysconfig/redis

lockfile=/var/lock/subsys/redis

start() {
    [ -x $redis ] || exit 5
    [ -f $REDIS_CONF_FILE ] || exit 6
    echo -n $"Starting $prog: "
    daemon $redis $REDIS_CONF_FILE
    retval=$?
    echo
    [ $retval -eq 0 ] && touch $lockfile
    return $retval
}

stop() {
    echo -n $"Stopping $prog: "
    killproc $prog -QUIT
    retval=$?
    echo
    [ $retval -eq 0 ] && rm -f $lockfile
    return $retval
}

restart() {
    stop
    start
}

reload() {
    echo -n $"Reloading $prog: "
    killproc $redis -HUP
    RETVAL=$?
    echo
}

force_reload() {
    restart
}

rh_status() {
    status $prog
}

rh_status_q() {
    rh_status >/dev/null 2>&1
}

case "$1" in
    start)
        rh_status_q && exit 0
        $1
        ;;
    stop)
        rh_status_q || exit 0
        $1
        ;;
    restart|configtest)
        $1
        ;;
    reload)
        rh_status_q || exit 7
        $1
        ;;
    force-reload)
        force_reload
        ;;
    status)
        rh_status
        ;;
    condrestart|try-restart)
        rh_status_q || exit 0
            ;;
    *)
        echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload}"
        exit 2
esac

Después solo queda por darle permisos de ejecucion

chmod 755 /etc/init.d/redisd

y habilitar el script en el inicio del arranque

chkconfig redisd on


Instalación de java

Descargamos la version 7 de java en /usr/src y después desde /opt ejecutamos descompresión como:

tar zxvf /usr/src/jdk1.7.0_21.tar.gz

creamos el enlace simbolico /opt/java apuntando al directorio de descompresión y modificamos el /etc/bashrc para añadir el JAVA_HOME y añadir la ruta al PATH

export JAVA_HOME=/opt/java
export PATH=$PATH:$JAVA_HOME/bin

Instalacion de elasticsearch

Desde la página http://www.elasticsearch.org/ nos descargamos la última version estable. En el momento en el que escribo esta guia logstash recomienda usar la verion 0.20.5, pero puede que más adelante se puedan usar versiones superiores, asi que es lo primero que tenemos que revisar.

Descomprimimos el tar.gz desde /opt y creamos el enlace simbolico en /opt/elasticsearch.

Revisamos el numero de "open file descriptors" que tenemos en nuestra máquina, haciendo cat /proc/sys/fs/file-max. Elasticsaerch recomienda entre 32k y 64k.

Para configurar como servicio elasticsearch existe ya un conjunto de scripts que podemos descargar des github, en la dirección: https://github.com/elasticsearch/elasticsearch-servicewrapper/archive/master.zip. Después de descomprimirlo copiamos el directorio service que hay dentro de /opt/elasticsearch/bin

Para configurar el arranque creamos un enlace simbolico de /opt/elasticsearch/bin/service/elasticsearch en /etc/init.d. y añadimos al arranque automático con

chkconfig elasticsearch on


De entrada no hemos tocado nada de la configuración. Si mas adelante tenemos que crear unaconfiguracion en cluster tendremos que añadir algunos parámetros. Tambien habrá que cambiarlos si queremos que los datos de elasticsearch vayan a un disco especifico para este propósito.

También se puede revisar, para propositos de rendimiento, añadir el parámetro de bloqueo de uso de memoria, para garantizar que el proceso de elasticsearch no usa memoria swap, ya que eso hace que el rendimiento de la jvm caiga en picado

Tareas de mantenimiento de Elasticsearch

Borrado automático de indices para un solo servidor

En el caso de que solo tengamos un nodo he creado un script en ruby que borrar el índice más antiguo cuando nos acercamos a un umbral de espacio libre en el disco que contiene los indices.

El script es el siguiente:

#!/usr/bin/ruby

ESDATADISK='/mnt/esdata'
TARGETFREESIZE=10485760
ESSERVER='localhost'
ESPORT='9200'

require "rubygems"
require "json"
require "net/http"
require "uri"

def openurl(url)
	Net::HTTP.get(URI.parse(url))
end

def deleteindex(indexname)
	puts "SE BORRARA INDICE #{indexname}"
	
	http = Net::HTTP.start(ESSERVER, ESPORT)
	response = http.send_request('DELETE',"/#{indexname}")
	puts "RESPUESTA DEL DELETE: #{response}"
	
end

def getfreesize(disk)
		freesize = `df #{disk} |grep #{disk} |awk '{print $4}'`
		puts "respuesta #{freesize}"
		return freesize
end


starttime = Time.now

puts "* #{starttime.inspect}"

diskfree = getfreesize(ESDATADISK)
puts "Disco disponible: #{diskfree}"


if diskfree.to_i < TARGETFREESIZE

	puts "Alcanzado umbral"
	
	respuesta = openurl('http://localhost:9200/_status')
	json_respuesta = JSON.parse(respuesta)

	indexcounter = 0
	json_respuesta["indices"].sort.each do |key_indice,data_indice|

		if key_indice['logstash']
			indexcounter = indexcounter + 1
			puts "#{indexcounter} #{key_indice} #{data_indice["index"]["size_in_bytes"]}"
			if indexcounter == 1
				deleteindex(key_indice)
			end
		end

	end

end

Y se ejecuta cada hora desde el crontab del usuario root:

59 * * * * /usr/bin/ruby /opt/elasticsearch/bin/ESdeleteoldindex.rb >> /var/log/ESdeleteoldindex.log 2>&1

Instalacion de Kibana

Kibana corre con ruby, y para hacer funcionar kibana vamos a necesitar instalar varios paquetes:

yum install ruby ruby-devel rubygems gcc-c++

Despues, siguiend la instrucciones de instalación rápida de la página de kibana ejecutamos los siguientes pasos:

Primero descargamos el paquete de kibana desde http://kibana.org/intro.html en /usr/src. Hacemos el tar corresponidiente al fichero que nos descargamos y lo llevamos a /opt/kibana-0.2.0 (en mi caso). Creamos el típico enlace simbólico en /opt/kibana a este directorio

Dentro del directorio /opt/kibana editamos el fichero KibanaConfig.rb para ver la dirección de nuestro elasticsearch. En nuestro caso, como kibana y elasticsearch están en el mismo servidor no ten3emos que hacer ningun cambio, ya que por fecto viene localhost:9200. Tambien cambiamos el KibanaHost, que por defecto hace que abra el puerto solo escuchando por la ip de lo. Lo cambaimos a 0.0.0.0

Lo siguiente es instalar la gema bundler

gem install bundler

y lanzar la instalacion de bundler

bundler install

Esta parte no la controlo muy bien, pero son los pasos que se dan en la página de kibana.

Una vez hecho esto, para arrancar la interface de kibana solo hay que ejecutar

ruby kibana.rb

Kibana 3

Existe una nueva versión de kibana más avanzada, y que además está escrita en html y js completamente. La característica más llamativa de esta version es que es el browser del cliente el que tiene que lanzar las consultas didrectamente al ES.

La web de esta version es esta:http://three.kibana.org/ donde están los enlaces de descarga y las instrucciones de instalación. En realidad, la instalación es muy sencilla, ya que solo son muchos estaticos y js que han de estar disponibles para un navegador.


Agentes de Logstash

Logstash se descarga como un único jar, que dependiendo de los parámetros de ejecución y el fichero de configuración que le especifiquemos, sirve como agente o como frontal web. Nosotros solo lo usaremos como agente.

Para ejecutar un agente solo tendremos que ejecutar el java de la siguiente manera:

java -jar logstash-1.1.10-flatjar.jar agent -f indexer.conf

En el fichero de configuracion le especificamos el comportamiento que va a tener este agente, si por ejemplo va a escuchar por un puerto UDP para recibir los datos, o si los va a coger de un redis; y también, una vez recogidos, que filtros va a pasar a los datos y cual es el destino de estos.

En nuestro caso tenemos dos tipos de logstash agent:

  • Fichero que recibe datos por UDP y los manda a una cola en REDIS:
input {
        udp {
                type    => "accesslog"
                port    => 9999
        }
}


filter {

        split {
                type            => "accesslog"
        }

}

output {
        redis {
                type            => "accesslog"
                host            => "127.0.0.1"
                port            => "6379"
                data_type       => "list"
                key             => "accesslog"
        }
}


  • Por otro lado tenemos el fichero que recoge los datos de REDIS, los procesa y los manda a elasticsearch
input {
        redis {
                host    => "127.0.0.1"
                port    => "6379"
                type => "accesslog"
                data_type => "list"
                key => "accesslog"
                format => "json_event"
        }
}


filter {

        grok {
                type            => "accesslog"
                pattern         => "%{WORD:source} %{DATA:host} %{DATA:logname} %{DATA:user} \[%{DATA:date}\] %{HOSTNAME:hostheader} \"%{DATA:method} %{DATA:path} %{DATA:protocol}\" %{NUMBER:code} %{DATA:size:int} %{NUMBER:duration:int} \"%{DATA:cache}\" %{WORD:server}"
        }

        mutate {
                type            => "accesslog"
                add_field       => [ "hostheaderfix", "%{hostheader}" ]
                gsub            => [ "cache", "\.", "_" ]
        }

        mutate {
                type            => "accesslog"
                gsub            => [ "hostheaderfix", "\.", "_" ]
        }

}



output {

        elasticsearch {
                host    => "127.0.0.1"
        }

        statsd {
                type            => "accesslog"
                host            => "10.90.9.129"
                sender          => "http"
                increment       => [
                                        "%{source}.responsecode.%{code}",
                                        "%{source}.hostheader.%{hostheaderfix}",
                                        "%{source}.method.%{method}",
                                        "%{source}.cache.%{cache}",
                                        "%{source}.servers.%{server}.hits"

                                ]
                count           => [
                                        "%{source}.size", "%{size}"
                                ]
        }
}

Para tener un arranque automático de la tarea de procesado de logs (indexer.conf) he creado el siguiente script de inicio:

#!/bin/sh
#
# logstash indexer
#
# chkconfig: 2345 95 50
# description: Script de inicio de los procesos de indexacion de logs
#              PSD - Pedro Miguel Blanco
#              15/05/2013
#


# Nombre de este demonio
LOGSTASH_PROCNAME="logstash-indexer"

# Numero de Workers
LOGSTASH_WORKERS=4

# Definicion del entorno
LOGSTASH_JAR="/opt/logstash/logstash-1.1.12-flatjar.jar"
JAVA_HOME="/opt/java"
JAVA="$JAVA_HOME/bin/java"

# Fichero de configuracion del indexer
LOGSTASH_INDEXER_CONF="/opt/logstash/indexer.conf"

# Directorio de salida de logs
LOGSTASH_INDEXER_LOG="/var/log/$LOGSTASH_PROCNAME.log"

# Directorio de pidfiles
LOGSTASH_INDEXER_PIDFILE="/var/run/$LOGSTASH_PROCNAME.pid"

# Incluimos funciones de inicio de RedHat/CentOS
. /etc/rc.d/init.d/functions



# FUNCIONES ------

start() {

        START_COMMAND="$JAVA -jar $LOGSTASH_JAR agent -f $LOGSTASH_INDEXER_CONF -w $LOGSTASH_WORKERS -l $LOGSTASH_INDEXER_LOG"
        echo -n "Starting logstash indexer process: $LOGSTASH_PROCNAME"
        daemon --pidfile $LOGSTASH_INDEXER_PIDFILE "$START_COMMAND &"
        RETVAL=$?
        echo
        set_pidfile
        return $RETVAL
}

stop() {
        echo -n "Stopping logstash indexer process: $LOGSTASH_PROCNAME"
        killproc -p "$LOGSTASH_INDEXER_PIDFILE" -d 10
        RETVAL=$?
        echo
        return $RETVAL
}

status() {
        if [ -f $LOGSTASH_INDEXER_PIDFILE ]; then
                PID=$(cat $LOGSTASH_INDEXER_PIDFILE)
                ps $PID > /dev/null
                RETVAL=$?
                if [ $RETVAL == 1 ]; then echo "PID FILE EXISTS BUT PROCCESS NOT RUNNIG"; fi
        else
                RETVAL=1
        fi

        echo -n "Logstash indexer process: "

        if [ $RETVAL == 0 ]; then
                echo "STARTED"
        else
                echo "STOPPED!!!"
        fi
        return $RETVAL
}


set_pidfile() {
        PID=$(ps x |grep "$LOGSTASH_INDEXER_LOG" |grep -v grep | awk '{print $1}' )
        if [ -n "$PID" ]; then
                echo $PID > $LOGSTASH_INDEXER_PIDFILE
        fi
        return $PID
}



case "$1" in

        start)
                start
                ;;
        stop)
                stop
                ;;
        status)
                status
                ;;
        restart)
                stop
                start
                ;;
        *)
                echo "Usage: $0 {start|stop|restart|status}"
                ;;
esac


exit $RETVAL

Existen diferentes versiones del agente logstash, flatjar y monolithic. La diferencia entre estas dos versinoes es que la primera está empaquetada y preparada para optimizar el proceso de arranque. Se puede leer algo más aqui

Instalación de graphite

Preparación de la máquina

Comprobamos si está instalado phyton en la máquina. Hacienod un rpm -q -a |grpe -i python vemos que está instalada una version 2.6.

Instalamos el paquete Pycairo, con yum install picairo

Instalamos apache httpd con yum install httpd

Instalamos el modulo de apache para python, que en centos 6.4 se llama mod_wsgi. Lo hacemos con yum install mod_wsgi

Después toca instalar django, pero por defecto no viene en los repositorios de centos 6.4. Tendremos que añadir EPEL. Para añadirlo haremos lo siguiente:

wget  http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
rpm -ivh epel-release-6-8.noarch.rpm

Una vez que ya tenemos el repositorio de EPEL ya podemos instalar Django

yum install Django

y tambien hará falta el modulo django-taggin

yum install django-tagging

Si vamos a usar un recolector desde un gestor de colas tendremos que poner el siguiente paquete tambien

yum install python-txamqp

Tambien vamos a conectar graphite contra nuestro servidor ldap, así que instalaremos el modulo ldap de python:

yum install python-ldap

En sistemas de la familia de redhat es necesario instalar fuentes de texto bitmap

yum install bitmap-fonts

También, para carbon, es neceseario instalar otro paquete de python:

yum install python-twisted

No es obligatorio, pero al parecer si muy recomendado, instalar el modulo de memcached de python

yum install python-memcached


Descarga de paquetes

Desde la siguiente página nos descargamos los componentes necesarios. En el momento de hacer este documento la version más reciente es la 0.9.10:

https://launchpad.net/graphite/+download/

Graphite web Carbon Whisper

Nos descargamos esos tres tar.gz en el directorio /usr/src/graphite y desempaquetamos los tres

Instalacion de whisper

Es la aplicación que almacena los datos en un formato muy parecido a RRD. Para hacer la instalacion entramos en el directorio que acabamos de desempaquetar y ejecutamos

python setup.py install

y con eso ya tenemos lo necesario

Instalación de carbon

Para la instalación de carbon, algo parecido. Entramos en eldirectorio que hemos desempaquetado con su instalable. Veremos que hay un fichero setup.cfg. En el podemos encontrar el prefix de donde lo queremos instalar. Vamos a dejarlo por defecto en el directorio /opt/graphite. Volvemos a ejecutar

python setup.py install

Una vez instalado ya tendremos el directorio /opt/graphite con los componentes de carbon.

Instalación de graphite

Entramos en le directorio despempaquetado de graphite. Si todas las instalaciones de los prerequisitos han ido bien no tendremos ningun error en la comprobación de las dependencias. Lo podremos comprobrobar con

python check-dependencies.py

Asi que podremos lanzar la instalación. Al igual que en la instalación de carbon existe un fichero con la configuracion de la instalacion, donde le podremos indicar el prefix de donde queremos instalarlo, pero es altamente recomendable dejarlo en el mismo lugar donde hemos instalado carbon.

python setup.py install

configuracion de graphite

Entramos en el directorio recien creado /opt/graphite/webapp/graphite y copiamos el fichero local_settings.py.example como local_settings.py. Ahi es donde vamos a poner nuestras configuraciones expeciales:

En primer lugar pondremos bien el parametro de la zona horaria, para que los datos salgan en la hora correcta que queremos:

TIME_ZONE = 'Europe/Madrid'

Luego nos iremos a la sección de Authentication Configuration, para configurar los parámetros de nuestro servidor ldap. En nuestro ejemplo es algo como esto:

#####################################
# Authentication Configuration #
#####################################
## LDAP / ActiveDirectory authentication setup
USE_LDAP_AUTH = True
#LDAP_SERVER = "ldap.mycompany.com"
#LDAP_PORT = 389
#       OR
LDAP_URI = "ldaps://sdc3w2k8.prisadigital.int:636"
LDAP_SEARCH_BASE = "OU=Usuarios,DC=prisadigital,DC=int"
LDAP_BASE_USER = "cn=ldapuser,cn=Users,dc=prisadigital,dc=int"
LDAP_BASE_PASS = "%$·%·"%"·$%&%$"
LDAP_USER_QUERY = "(sAMAccountName=%s)"  #For Active Directory use "(sAMAccountName=%s)"

Creación de la DB de django

Antes de ponder utilizar graphite necesitamos crear la base de datos que usa django para almacenar sus configuraciones, usuarios, etc... para ello, desde el directorio de antes, opt/graphite/webapp/graphite, ejecutamos lo siguiente:

python manage.py syncdb

Se crearan todas las tablas que necesita y además nos preguntará si queremos crear el usuario superuser. Nosotros le decimos que si y le damos un password.

Configuración de apache

En el directorio /opt/graphite/examples viene ya un fichero de configuracion de un vhost de apache. Se lo podemos copiar a nuestro apache que acabamos de instalar. Si no hemos cambiado el prefix de nuestra instalacion podremos dejarlo tal cual está.

Tambien en el directorio /opt/graphite/conf tendremos que hacer una copia del fichero de configuracion de ejemplo graphite.wsgi.example como graphite.wsgi. Lo mismo, si no hemos cambiando el prefix lo podremos dejar como está, sino tendremos que buscar y cambiar los paths.


Configuracion de carbon

Para que nos arranque el servicio carbon-cache, en el directorio /opt/graphite/conf, tendremos que hacer copia del fichero carbon.conf.example como carbon.conf. Este fichero tiene todos los datos de comportamiento de carbon, pero en este momento lo dejamos como está, ya que no nos hace falta ningun cambio especial para hacerlo funcionar.

Tambien tendremos que hacer copia del fichero de ejemplo de los esquemas de almacenamiento, de storage-schemas.conf.example a storage-schemas.conf. Este fichero tiene la configuracion de la precisión con la que guardaremos los datos y la retención.


Cambiando algunos permisos

Para que funcione la web de graphite hemos tenido que hacer algunos cambios de permisos. Para empezar, como el python de la web se ejecuta con el usuario apache tenemos que caambiar de owner al directorio /opt/graphite/storage/log/webapp, para que pueda escribir los logs.

Además, tambien necesita escribir un fichero "index" en /opt/graphite/storage, así que hemos cambiado el owner tambien de /otp/graphite/storage... sin recursividad.

Arrancando los servicios

Primero arrancamos carbon, que es el que se encarga de recoger datos:

/opt/graphite/bin/carbon-cache.py start

Y graphite estará disponible a traves de la web de apache, así que si después de añadir el fichero de vhost no se ha reiniciado apache habrá que hacerlo ahora.


Script de arranque automático de Carbon-cache

Como script de arranque automático hemos creado el fichero /opt/graphite/bin/carbon-cache.init, y después hemos hecho un enlace simbólico desde /etc/init.d/

#!/bin/bash
#
# carbon-cache - This script starts and stops the carbon-cache service.
#
# chkconfig:   - 85 15
# description: carbon-cache accepts graphite metrics and writes them to
#              disk using whisper
# processname: carbon-cache.py
# config:      /etc/sysconfig/carbon-cache

# Source function library.
. /etc/rc.d/init.d/functions

# Source networking configuration.
. /etc/sysconfig/network

# Check that networking is up.
[ "$NETWORKING" = "no" ] && exit 0

CARBON_HOME="/opt/graphite"

exec="$CARBON_HOME/bin/carbon-cache.py"
prog=$(basename "$exec")
CARBON_CONFIG_PATH="$CARBON_HOME/conf/carbon.conf"
CARBON_CACHE_ARGS=""
CARBON_CACHE_PIDFILE="/var/run/carbon-cache.pid"
GRAPHITE_STORAGE_DIR="$CARBON_HOME/storage"

export GRAPHITE_STORAGE_DIR

restart() {
    stop
    start
}

rh_status() {
    status -p "$CARBON_CACHE_PIDFILE" "$prog"
}

start() {
    echo -n 'Starting carbon-cache...'
    daemon --pidfile="$CARBON_CACHE_PIDFILE" "$exec" start $args \
      --config="$CARBON_CONFIG_PATH" --pidfile="$CARBON_CACHE_PIDFILE" >/dev/null
    retval=$?
    echo
    return $retval
}

stop() {
    echo -n 'Stopping carbon-cache...'
    killproc -p "$CARBON_CACHE_PIDFILE" "$prog"
    retval=$?
    echo
    return $retval
}

case $1 in
    condrestart|try-restart)
        rh_status 2>/dev/null && restart
        ;;
    reload|force-reload)
        restart
        ;;
    restart)
        restart
        ;;
    start)
        start
        ;;
    status)
        rh_status
        ;;
    status_q)
        rh_status >/dev/null 2>&1
        ;;
    stop)
        stop
        ;;
    *)
        echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload}"
        exit 2
        ;;
esac

exit $?

Tareas automáticas de mantenimiento

Hacemos un rotado manual de los logs con comandos find en el crontab del usuario root. Para ello, ejecutamos el comando crontab -e desde el usuario root y añadimos las dos siguientes líneas:

21 1 * * * /bin/find /opt/graphite/storage/log/carbon-cache/carbon-cache-a/ -name "*log.*[0-9]" -type f -mtime +0 -exec gzip {} \;
23 1 * * * /bin/bind /opt/graphite/storage/log/carbon-cache/carbon-cache-a/ -name "*.gz" -type f -mtime +5 -exec rm -f {} \;

Instalacion de StatsD

Una página interesante antes de ponerse a instalar statsd, para entender conceptos básicos:

http://blog.pkhamre.com/2012/07/24/understanding-statsd-and-graphite/

Y esta es otra página en la que esplica como instalar graphite, y lo que a nosotros nos interesa ahora mismo, instalar statsd.

Instalando nodejs

La clave para esto es el nodejs, así que nos ponemos a instalarlo desde el código fuente.

Primero nos creamos el directorio /usr/src/nodejs y en el descargamos el codigo fuente con git.

git clone http://github.com/joyent/node.git .

NOs vamos al tag de la version más reciente. Para saberlo me he ido a la web de nodejs y he visto que era la version 0.10.5

git checkout v0.10.5

Como lo vamos a tener que compliar, primero tendremos que instalar el compilador apropiado:

yum install gcc-g++

Después lo compilamos

./configure --prefix=/opt/nodejs-0.10.5
make
make install

Después lo añadimos en nuestro path, editamos el fichero /etc/bashrc para que tenga al final lo siguiente:

export NODEJS_HOME=/opt/nodejs
export PATH=$PATH:$NODEJS_HOME/bin

Nos va a hacer falta tambien ejecutar lo sigiuente, que es instalar el paquete nodeunit de nodejs. Lo hacemos con el gestor de paquetes que va incluido en nodejs: npm (node package manager)

npm install nodeunit

statsd

statsd es un programa que corre sobre nodejs, por lo tanto lo único que hay que hacer es bajarselo y ejecutarlo.

Creamos el directorio /opt/statsd y en el ejecutamos

git clone https://github.com/etsy/statsd.git .

Después creamos una copia del fichero de configuracion de ejemplo que hay en el directorio de statsd y lo llamamos config.js. Lo editamos para que tenga algo como lo siguiente al final:

{
        graphitePort: 2003,
        graphiteHost: "127.0.0.1",
        port: 8125,
        backends: [ "./backends/graphite" ],
}

Es decir, que le decimos donde está nuestro graphite donde finalmente van a ser insertados los datos.

Ahora ejecutamos el test

./run_test.sh

Y veremos que nos van saliendo errores de paquetes que nos hacen falta. Los iremos instalando uno a uno. En mi ejemplo, los que he instalado son los siguientes:

npm install temp
npm install underscore

después de instalar esos dos modulos el test me da un ok.

Ahora, para arrancar statsD solo hay que ir al directorio de la aplicacion de statsD /opt/statsd y ejecutar

node stats.js config.js

Para el arranque automático he creado el script /opt/statsd/statsd.init:

#!/bin/bash
#
# StatsD
#
# chkconfig: 3 50 50
# description: StatsD init.d
. /etc/rc.d/init.d/functions

prog=statsd
STATSDDIR=/opt/statsd
statsd=$STATSDDIR/stats.js
LOG=/var/log/statsd.log
ERRLOG=/var/log/statsderr.log
CONFFILE=${STATSDDIR}/config.js
pidfile=/var/run/statsd.pid
lockfile=/var/lock/subsys/statsd
nodebin=/opt/nodejs/bin/node
RETVAL=0
STOP_TIMEOUT=${STOP_TIMEOUT-10}

start() {
        echo -n $"Starting $prog: "
        cd ${STATSDDIR}

        # See if it's already running. Look *only* at the pid file.
        if [ -f ${pidfile} ]; then
                failure "PID file exists for statsd"
                RETVAL=1
        else
                # Run as process
                daemon "${nodebin} ${statsd} ${CONFFILE} >> ${LOG} 2>> ${ERRLOG} &"
                RETVAL=$?

                # Store PID
                #echo $! > ${pidfile}
                ps a |grep ${CONFFILE} | grep -v grep | awk '{print $1}' > ${pidfile}

                # Success
                [ $RETVAL = 0 ] && success "statsd started"
        fi

        echo
        return $RETVAL
}

stop() {
        echo -n $"Stopping $prog: "
        killproc -p ${pidfile}
        RETVAL=$?
        echo
        [ $RETVAL = 0 ] && rm -f ${pidfile}
}

# See how we were called.
case "$1" in
  start)
        start
        ;;
  stop)
        stop
        ;;
  status)
        status -p ${pidfile} ${prog}
        RETVAL=$?
        ;;
  restart)
        stop
        start
        ;;
  condrestart)
        if [ -f ${pidfile} ] ; then
                stop
                start
        fi
        ;;
  *)
        echo $"Usage: $prog {start|stop|restart|condrestart|status}"
        exit 1
esac

exit $RETVAL

He creado un enlace simbólico en /etc/init.d de este fichero y activado el arranque automático

chkconfig statsd.init on

Configuracion de logstash para enviar a statsd

Para hacer que nuestro logstash envie datos a statsd tendremos que cambiar ligeramente la configuración

de nuestro fichero de configuracion indexer.conf de logstash para añadir lo siguiente al output:

        statsd {
                host            => "<servidor de statsd>"
                increment       => [
                                        "varnish.responsecode.%{code}",
                                        "varnish.hostheader.%{hostheaderfix}",
                                        "varnish.method.%{method}",
                                        "varnish.cache.%{cache}"
                                ]
                count           => [
                                        "varnish.size", "%{size}"
                                ]
        }

Lo que le estamos enviando son datos que iran a parar a graphite, después de hacer acumulados o lo que

queramos que haga con esos datos.

Optimizaciones del proceso

Logstash

Durante el arranque del proceso de logstash se puede especificar el número de hilos que se van a lanzar para procesar los filtros. Este parámetro es -w y va acompañado del numero de hilos que queremos ejecutar.

Este parámetro debería ir en consonancia con el numero de hilos que recepcionan el contenido, sobre todo (y esto si lo he probado) si el plugin de inserccion es el que recoge datos de redis. En ese INPUT existe el parámetro threads, con el que le decimso la cantidad de hilos con el que vamos a ir a buscar datos a redis.

Poniendo estos dos parámetros con el mismo número de hilos (el numero de cores de la máquina) hace que mejore el rendimiento de procesado de las entradas de log, hasta aprovechar el máximo de la máquina.

Elasticsearch

Enlaces intersantes sobre esto:

Algunas tareas para optimizar elasticsearch para el uso que le damos nosotros:

Asignación de memoria

Importante es no dejar que java use memoria paginada, para lo cual podemos configurar logstash para que

al arrancar reserve la memoria que necesita de nuestro sistema. En primer lugar decidimos que la

cantidad de memoria que vamos a reservar es la mitad de la que tiene la máquina en la que corre ES. En

nuestro caso eso significa que vamos a reservar 4096Mb de Ram. Para hacer esto primero cambiamos el

fichero de configuración del script de arranque de Elasticsearch

(/opt/elasticsearch/bin/service/elasticsearch.conf), Poniendo el valor por defecto de la variable

ES_HEAP_SIZE

set.default.ES_HEAP_SIZE=4096

después tendremos que indicarle a la configuracion de elasticsearch que queremos hacer la reserva de

memoria al arrancar. Descomentamos el siguiente parámetro del fichero

/opt/elasticsearch/config/elasticsearch.yml

bootstrap.mlockall: true


Memoria dedicada a la indexación

Por defecto ES da más preferencia a las operaciones de busqueda que a las de indexación asignando un 90%

de la memoria para ello y un 10% para el proceso de indexacion, lo cual es lógico, pero en nuestro caso

vamos a realizar más operaciones de indexación que de búsqueda. Lo que interesa es que el proceso de

indexación sea lo más rápido posible. Por ello podemos añadir el siguente parámetro en el fichero de

configuración de ES:

indices.memory.index_buffer_size=50%

Con esto indicamos que vamos a usar el 50% de memoria para el proceso de index.

Flush de log transaccional

Cada shard tiene un log transaccional de operaciones que modifican los datos en disco. Tambien estos

parámetros están puestos por defecto para cuando hay pocas operaciones de inserción y más de búsqueda,

haciendo por defecto un flush de los datos cuando se han insertado más de 200Mb, o 5000 operaciones o

por tiempo finalmente a los 30 minutos. En las primeras pruebas estamos insertando a razón de unos 600

entradas por segundo, lo cual quiere decir que estamos haciendo flush cada 8 segundos o menos. Poniendo

lo siguiente en el ficher de configuración:

index.translog.flush_threshold_ops=40000

conseguimos hacer que el flush se haga cada minuto en vez de cada 8 segundos, y evitamos repetir el

proceso de escritura de esos cambios a disco.

Numero de shards

Sería necesiario realizar muchas pruebas para ver con cuantos shards daría mejor rendimiento. Puede que

si solo tenemos un nodo 5 shards (por defecto) sean demasiados y podríamos bajarlo un poco. Lo que si

hay que tener en cuenta para configurar estos shards es la cantidad de nodos que vamos a usar. En mi

caso lo voy a dejar como está... con el valor por defecto


los threadpools

Parece ser que internamente ES trabaja con diferentes hilos dependiendo de la operación que vayamos a

realizar. Se puede configurar la memoria asignada a los grupos de hilos dependiendo de la operación que

queramos mejorar.

Algunos enlaces de referencia sobre este tema: http://www.elasticsearch.org/guide/reference/modules/threadpool/

También aqui hay un comentario de alguien que dice haber hecho pruebas de indexación con difernetes

combinaciones de numero de shards (aunque sea en el mismo nodo), consiguiendo mejoras importantes:

http://elasticsearch-users.115913.n3.nabble.com/Understanding-Threadpools-td4028445.html

Si queremos ver información sobre la configuración actual de los nodos podemos verlo en la URL

http://tranlogpol01.prisadigital.int:9200/_nodes/?pretty=on&all


Template

Existen ya templates de indices especificos para logstash, mis primeras pruebas han sido usando el siguiente template

https://gist.github.com/deverton/2970285

Graphite

Hay algunos aspectos a tener en cuenta en la optimización de statsd y graphite.

StatsD se come todas las peticiones que le llegan de logstash a través del modulo output de statsd. Esos datos van en un flujo constante de peticiones a statsD por UDP, un envio por cada línea de log que ha llegado a logstash. Statsd funciona como un memcached, de hecho, abre un puerto que llama de mantenimiento 8126 por defecto, en el que se pueden realizar consultas al estilo memcached. Cada vez que por UDP le llega una nueva métrica a statsd este la acumula, suma o lo que tenga que hacer con esa métrica en memoria y cada cierto tiempo lanza la actualización a graphite.

El problema son estas oleadas de actualizaciones a grahpite.


<falta contar el como hice el balanceo de carga los agent de logstas> <Logstash que encola entradas y varios agent procesando>

Otras herramientas y complmentos para la monitorizacion

BrighcoveOS Diamond

(por documentar)

Elastic Search paramedic

Para una motorización online de ElastcSearch podemos usar la herramienta ElasticSearch Paramedic. Es una app web que solo necesita publicación http, y las consultas se realizan desde el cliente.

La descarga del repositorio git la he hecho en /opt/esparamedic

cd /opt/esparamedic
git clone https://github.com/karmi/elasticsearch-paramedic.git

Después configuramos un vhost apuntando a este directorio en nuestro apache

<VirtualHost *:80>
        ServerName esparamedic.logs.prisadigital.int
        DocumentRoot "/opt/esparamedic"
        ErrorLog /var/log/httpd/esparamedic-error.log
        CustomLog /var/log/httpd/esparamedic-access.log common

        <Directory /opt/esparamedic/>
                Order deny,allow
                Allow from all
        </Directory>

</VirtualHost>

He añadido un registro en el DNS a ese vhost y al entrar solo hay que especificar la URL del elasticsearch