Recolectando logs de Amazon ECS con ELK

Eloy Vega
KarmaPulse Developers
4 min readMay 20, 2016

En Karma utilizamos Amazon ECS (EC2 Container Service) para desplegar, monitorear y escalar nuestros microservicios. También usamos Elasticsearch + Kibana para almacenamiento y visualización de nuestra data. Y teniendo estos dos elementos, pensamos ¿por qué no agregamos Logstash a la fórmula para recolectar los logs de nuestros contenedores?

La forma tradicional para ver los logs de un contenedor de Docker es usando el comando “docker logs <container_id>” sin embargo esto no escala bien, mucho menos en un clúster auto-administrado como en ECS. Tampoco queríamos acoplar un contenedor a cada una de nuestras aplicaciones para una necesidad tan sencilla como la extracción de los logs, por eso usamos Logspout en cada instancia EC2 para esta tarea.

Primero lo primero, a donde van los datos

En este ejemplo usamos Amazon Elasticsearch Service pero, si tu lo prefieres, pudes levantar Elasticsearch y Kibana en tu computadora. Para instrucciones de como levantar un clúster en Amazon Elasticsearch Service revisa su documentación (spoiler alert: es muy fácil).

Al final tendremos nuestro clúster y dos URL’s: una del API Endpoint de Elasticsearch que usaremos para acceder desde Logstash y una para nuestra interfaz de Kibana:

Amazon Elasticsearch Service

Creando una instancia para Logstash

Con Logstash recibimos los logs desde nuestros contenedores, los formateamos (si queremos) e insertamos a Elasticsearch. Para esto vamos a levantar una instancia de EC2 e instalaremos Logstash como dicen las instrucciones oficiales. Y creamos la variable de entorno LOGSTASH_HOME para todo lo que sigue:

$ echo "export LOGSTASH_HOME=/ruta/de/la/carpeta/logstash" >> ~/.bashrc ; source ~/.bashrc

Ya que nosotros usamos Elasticsearch Service debemos instalar el plugin para Logstash:

$ $LOGSTASH_HOME/bin/plugin install logstash-output-amazon_es

Y en $LOGSTASH_HOME/config creamos nuestro archivo de configuración logs.conf:

input {
tcp {
port => 5000
type => syslog
}
udp {
port => 5000
type => syslog
}
}
output {
amazon_es {
hosts => [“foo.us-example-1.es.amazonaws.com”]
region => “us-example-1”
aws_access_key_id => ‘ACCESS_KEY’
aws_secret_access_key => ‘SECRET_KEY’
index => “prod-logs-%{+YYYY.MM.dd}”
}
}

En el ejemplo anterior la sección de output tiene parámetros de Amazon Elasticsearch Service. Para ejemplos de salida hacia un Elasticsearch normal, revisa su guía oficial. Es importante notar que nuestro index tiene la fecha incorportada para mejor visualización en Kibana.

Ahora creamos un archivo de upstart para iniciar Logstash como servicio:

# vi /etc/init/logs.conf

Con el siguiente contenido:

description “Logstash service”start on runlevel [2345]
stop on runlevel [!2345]
respawn
setuid ubuntu
setgid ubuntu
exec $LOGSTASH_HOME/bin/logstash agent -f $LOGSTASH_HOME/config/logs.conf

Guardamos el archivo y ahora podemos iniciar el servicio con:

# service logs start

¡Ya tenemos Kibana, Elasticsearch y Logstash listos para empezar a recibir logs! Ahora debemos escuchar a nuestros contenedores y reenviar su salida hacia nuestra IP de Logstash con puerto 5000.

Dame los logs, ECS!

Lo primero que debemos hacer es crear una imagen de Logspout con el adaptador para enviar a Logstash y subirla a un registro de imágenes como DockerHub para usarla desde ECS. O puedes usar la imagen de KarmaPulse (karmapulse/logspout_logstash) que ya está lista para hacer eso.

En nuestra consola de Amazon vamos a EC2 Container Service y creamos una nueva definición de tarea llamada log_collector y agregamos un volúmen con las siguientes características:

Volúmen para montar en nuestro contenedor

Y a continuación llenamos la definición de nuestro contenedor:

Definición de imágen, memoria y puertos
Comando de ejecución

Nuestro contenedor no hace uso del puerto 1025, pero lo definimos así para asegurarnos que cada instancia de EC2 ejecute solo una instancia de nuestra tarea. La dirección IP que se indica en la sección Command debe ser la de nuestra máquina con Logstash.

Finalmente definimos donde montaremos el volumen que creamos al principio:

Montar el volúmen creado previamente

Ahora estamos listos para ejecutar nuestro servicio con el número de tareas igual al número de instancias que contiene nuestro clúster o si lo prefieres con un número mucho mayor para que cada vez que se incremente nuestro número de máquinas, también lo haga nuestro número de recolectores de logs:

Servicio de ECS

Con todas las piezas funcionando correctamente, nuestros logs ya están ingresando a Elasticsearch y ahora solo debemos entrar a Kibana y empezar a ver los eventos del clúster.

Kibana, the tip of the iceberg

En la sección de Setting configura un nuevo index de la siguiente forma:

Index en Kibana

Y en la sección de Discover ya puedes ver tus logs:

Con este sencillo stack puedes extraer los logs de clúster de ECS sin modificar los parámetros de tus aplicaciones ni acoplar contenedores a cada una de ellas.

Si tienes alguna duda o comentario no dudes en dejarla en los comentarios o contactarme en twitter.

--

--