miércoles, 19 de febrero de 2014

Agrupando el log de rails con rsyslog

En teowaki el servicio de API lo tenemos balanceado entre dos servidores. Los objetivos principales de balancearlo, más que la carga, han sido la protección ante fallos y la posibilidad de hacer pruebas con diferentes configuraciones en los servidores.

Por ejemplo, inicialmente teníamos ruby 2.0 y unicorn en ambos servidores. En Navidad se publicó la versión 2.1, la instalamos en uno de los servidores y durante unas semanas tuvimos las dos versiones conviviendo en produccion. Las conclusiones fueron que más o menos el tiempo de respuesta bajaba un  20% y el consumo de memoría subía tambien sobre un 20%, así que decidimos instalarlo en las dos máquinas.

De la misma forma queremos hacer la prueba más adelante de usar diferentes servidores de aplicaciones simultáneamante (passenger / unicorn / puma) para ver cual funciona mejor. Tambien tenemos la intención de probar JRuby 9K en cuanto esté listo para producción.

El problema del balanceo es que el log queda distribuido y es imposible seguir una petición. Afortunadamente hay una solución muy simple usando rsyslog.

El primer paso es cambiar la configuración de rails para que use syslog, que viene por defecto en ruby, por lo que no es necesario instalar ninguna gema. Tan simple como añadir una línea en config/production.rb, donde 'teowaki-api' en nuestro caso indica el nombre que usaremos para la configuración de rsyslog.

$ more config/production.rb 
...
config.logger = Syslog::Logger.new 'teowaki-api'

A partir de ahora, el log en modo production lo procesará rsyslog.

Para configurar rsyslog, primero de todo editamos /etc/rsyslog.conf en el servidor que recibirá los logs (misc en nuestro caso), permitiendo acceso por TCP en el puerto 10514 y dando permiso de escritura solo a los servidores de API.

En la configuración por defecto de rsyslog el puerto de TCP es 514, pero en ubuntu hay un problema de privilegios al usar puertos por debajo del 1024, así que he usado el 10514

$ more /etc/rsyslog.conf
....
# provides TCP syslog reception
$ModLoad imtcp
$InputTCPServerRun 10514
...
$AllowedSender TCP, api01, api02

Ahora creamos el fichero de configuración cada servidor de API, donde le decimos que guarde el log en /var/log en local y que tambien lo mande al servidor misc al puerto 10514


$ more /etc/rsyslog.d/40-teowaki-api.conf 
if $programname == 'teowaki-api' then /var/log/rails/teowaki-api.log 
if $programname == 'teowaki-api' then @@misc:10514 
& ~  

Y finalmente, en el servidor misc le decimos que guarde el log, que le llegará desde los servidores de API, en /var/log

$ more /etc/rsyslog.d/40-teowaki-api.conf 
if $programname == 'teowaki-api' then /var/log/rails/teowaki-api.log 
& ~  

El número 40 indica la prioridad del fichero, para que se ejecute antes que el fichero 50-default.conf, tal y como explican en este blog, que fue el que me dio la idea para esta configuración

Y esto es todo, así de simple y ya tenemos la configuración completa.

La instalación en producción la he hecho con un par de roles de ansible, uno para los servidores de API y otro para el servidor que recibe los logs y además le he añadido logrotate, pero bueno, de ansible ya hablaremos en otro post...

Más adelante quiero probar otras soluciones más potentes como Kibana y logstash, pero por ahora ya tenemos el log centralizado, que era el objetivo inicial.



jueves, 6 de febrero de 2014

Recuperando el blog

Hace ya casi 6 años escribí la primera entrada en este blog. Mi idea inicial era escribir una entrada cada mes, mantuve bien el ritmo en el 2008 y el 2009, el 2010 empecé a flaquear y en el 2013 no he escrito ni una triste entrada :(

El 2013 ha sido un año de muchos cambios, dejé la empresa donde había estado trabajando desde el 2007 para intentar junto a Javi la loca aventura de montar un producto SaaS que haga más felices a los desarrolladores. Desde diciembre tenemos teowaki en producción, y estamos bastante orgullosos del resultado.

Uno de las consecuencias ha sido que mi stack tecnológico ha cambiado mucho. Estos años la mayoría de mis proyectos estaban basados en ruby on rails en el servidor, MySQL como almacen de datos y una parte cliente que cada vez iba siendo más compleja, pero casi siempre basada en las vistas de rails y jQuery.

Aprovechando que teniamos 'poder absoluto' para decidir la tecnología a usar, optamos por una arquitectura que por ahora está dando muy buen resultado.

Para empezar, queríamos que la API fuera un ciudadano de primera clase del proyecto, así que hemos desarrollado por un backend en modo API y el front es simplemente un cliente más de esa API.

Tambien hemos empezado a usar redis para mucho más que para la gestión de colas y nuestra base de datos es PostgreSQL.

Aunque ya hacía algo de sistemas anteriormente, tambien me he introducido un poco más en el mundo devops, instalando los servidores con Ansible. Otro cambio ha sido que en lugar de usar apache / passenger como servidor web y de aplicaciones, estamos probando la combinación nginx / unicorn.

Del mismo modo, he tenido que resetear lo que sabía de JavaScript, aprendiendo a usar AngularJS en el cliente de la API.

Así que creo que tengo bastantes cosas que contar sobre mi trabajo y voy a intentar recuperar el ritmo de una entrada por mes, a ver si lo consigo al menos durante otros dos años como cuando empecé este blog.