Controlar los mongrels con monit en Slicehost

Recientemente me he estado pegando con mi mongrel cluster en un una de mis aplicaciones en Slicehost… Los mongrel comenzaban ocupando menos de 50 Mb de memoria pero conforme pasaban los días iban ganando peso y llegaban a chupar cerca de 200 Mb, acabando con la memoria disponible…

Parece que esta facilitar para ganar peso de los mongrels es en parte natural (van creciendo conforme van cargando códigos de la aplicación) y en parte debido a bugs en el propio código de mongrel, plugins de rails, etc. Sea como sea, es necesario mantenerlos a raya.

Para ello, qué mejor que monit. Esta aplicación se emplea para controlar los procesos de un servidor, de manera que podemos medir continuamente el tamaño de ram que emplean (y otras medidas como uso de cpu, carga…) y reiniciarlos en caso necesario. También puede encargarse de comprobar que los procesos están corriendo y lanzarlos en caso de que se hubieran caído. Lo podemos usar para todos los procesos del servidor, no sólo los mongrels: nginx, apache, mysqld, sendmail, etc.

Os cuento cómo lo monté en mi servidor debian en slicehost:

1.- En primer lugar, instalamos monit:

sudo apt-get install monit

2.- Una vez instalado, tenemos un fichero de configuración de monit. Está bien guardarlo como ejemplo pues vienen muchos casos útiles, pero para simplemente controlar mongrels, podéis hacer como en este ejemplo:

set daemon 60
set mailserver localhost
set mail-format { from: monit@tuaplicacion.com }
set alert tu@email.com

set logfile /var/log/monit.log

##### mongrel 12000 #####
check process mongrel-12000 with pidfile /home/usuario/apps/aplicacion/tmp/pids/mongrel.12000.pid
    start program = "/usr/bin/mongrel_rails cluster::start -C /home/usuario/apps/aplicacion/config/mongrel_cluster.yml --clean --only 12000"
    stop program  = "/usr/bin/mongrel_rails cluster::stop -C /home/usuario/apps/aplicacion/config/mongrel_cluster.yml --clean --only 12000"

    if totalmem is greater than 75.0 MB for 5 cycles then restart       # eating up memory?
    if cpu is greater than 50% for 2 cycles then alert                  # send an email to admin
    if cpu is greater than 80% for 3 cycles then restart                # hung process?
    if loadavg(5min) greater than 10 for 8 cycles then restart          # bad, bad, bad
    if 3 restarts within 5 cycles then timeout                          # something is wrong, call the sys-admin

    if failed port 12000 protocol http                   # check for response
        with timeout 10 seconds
        then restart
    group mongrel

El código es muy fácil de entender:

  • La primera línea establece cada cuántos segundos se despertará monit para hacer sus comprobaciones
  • El siguiente bloque establece la configuración para los envíos de email de alerta
  • La línea de logfile indica en qué ficheros guardar los logs
  • Y después, un bloque para cada proceso que se quiera vigilar. Para cada proceso hay que indicar el nombre que le daremos a este, dónde puede encontrar el PID del proceso, y cuál es el comando para arrancarlo y para pararlo. A continuación, se pueden poner varias directivas para las comprobaciones. En este ejemplo, si el mongrel consume más de 75 Mb de RAM durante 5 comprobaciones (cycles) seguidas, se reiniciará el proceso (vamos, se le hará un stop y un start con los comandos arriba indicados). Hay otras comprobaciones adicionales debajo. También se comprueba que el mongrel esté accesible en su puerto, y si no se reinicia, etc.

En mi caso tengo 3 mongrels… para controlar los otros dos se copia ese ultimo parrafo exactamente igual para cada uno, pero cada uno en su puerto, claro… 12001 y 12002 en mi caso.

3.- Ya casi estamos… para indicar que monit se arranque al iniciar el servidor, editaremos el fichero /etc/default/monit y lo indicaremos mediante la línea startup=1

4.- Y finalmente, para lanzar monit ahora sin tener que reiniciar el servidor…

sudo /etc/init.d/monit start

5.- Como nota final, un tema que me encontré es que cuando monit entraba en acción y reiniciaba algún mongrel, me los lanzaba como usuario root en lugar de como el usuario no-root con el que normalmente lanzo el mongrel cluster. Esto era porque me faltaba indicar en el fichero config/mongrel_cluster.yml de mi aplicación el usuario y grupo con el que se deben ejecutar los mongrels:

---
user: usuario
group: grupo
(...)

Eso es todo amigos… espero que os venga bien y os facilite la vida al tener que estar menos pendientes del servidor…

Gracias a Marze y The Robot por sugerirme usar monit, y a Guillermo por darme la pista sobre el tema del usuario no-root en la lista hacking-es.