Centralizar y consultar las trazas de las aplicaciones con Elasticsearch, Logstash y Kibana

Escrito por el .
planeta-codigo programacion
Enlace permanente Comentarios

Las aplicaciones monolíticas solo generan un archivo de trazas, es fácil de monitorizar, basta con conectarse por SSH a la máquina de su entorno de ejecución y utilizar los comandos grep o tail o descargarlo para examinarlo con otra herramienta de forma local. Pero aún siendo una aplicación monolítica es raro que una organización tenga solo una aplicación sino varias diferentes y las aplicaciones complejas se dividen en varias aún siendo parte de la misma aplicación. Esto hace que haya múltiples aplicaciones en cuyo caso acceder por SSH a una máquina diferente en cada caso no es cómodo. En el caso de múltiples aplicaciones o aplicaciones basadas en microservicios se opta por centralizar las trazas provenientes de múltiples fuentes en una única herramienta, una de las herramientas es la combinación de Elasticsearch, Logstash y Kibana que forma la pila ELK.

Elastic Stack

Las trazas de una aplicación permiten conocer en tiempo real el estado de la aplicación, las trazas contienen cualquier información que haya considerado el desarrollador de interés para la monitorización cuando el código se ejecuta, la información pueden ser los valores de ciertos datos, cualquier mensaje que indique por qué líneas de código se están ejecutando en el caso de sentencias condicionales, de bucle o que varían el flujo del programa, si es una traza de error, de información, de advertencia o su marca de tiempo.

Las trazas se suelen almacenar en un registro como un archivo que además permita consultarlas en un futuro en caso necesario. A veces un problema se descubre pasadas varias horas o días, en este caso acceder al registro de trazas permite obtener información para averiguar que ha sucedido y si es el caso descubrir la causa del error en el código fuente.

En una aplicación monolíticas guardar las trazas en un archivo puede ser suficiente, en las aplicaciones distribuidas y compuestas por varios microservicios cada uno emitiendo su propio registro de trazas se hace necesario recopilarlos y centralizarlos en una herramienta para su almacenamiento y consulta sencilla.

La monitorización y las trazas son dos de las necesidades de funcionalidad de las aplicaciones basadas en microservicios aunque es también aplicable a las aplicaciones monolíticas. El complemento a las trazas son las métricas y monitorización con Prometheus y Grafana.

Para cubrir la necesidad de monitorización y trazas de las aplicaciones hay múltiples herramientas, entre las que tienen una licencia de software libre o de código abierto están la combinación de Elasticsearch, Logstash y Kibana también conocidas por las siglas ELK.

ElasticSearch, Logstash, Filebeat y Kibana

ElasticSearch proporciona la indexación y el almacenamiento, Logstash que permite la recolección, tratamiento y envío a Elasticsearch y Kibana permite su consulta y visualización con una interfaz web.

Cada aplicación que emite trazas necesita tener un recolector de trazas asociado que permite enviarlas a Elasticsearch para su indexación y almacenamiento. Logstash es una herramienta pesada como para incluirla en cada máquina donde se instancian los servicios, por ello la propia empresa Elasticsearch ha desarrollado herramientas más ligeras, Beats, compuestas de varias herramientas como por ejemplo para archivos de log, métricas, de red o de actividad entre algunos otros.

En vez de usar Logstash se puede usar la herramienta más ligera Filebeat para indexar la salida estándar de las aplicaciones directamente en Elasticsearch o para enviar a una instancia de Logstash que realice el procesado y el indexado en Elasticsearch.

Arquitectura de la plataforma ELK

Arquitectura de la plataforma ELK

ELK también cubre algunas funcionalidades de monitorización y visualización de datos de métricas, que se solapa en algunos aspectos con la funcionalidad proporcionada por Prometheus y Grafana.

ELK solo son las herramientas que se encargan de almacenar y permitir el acceso a las trazas, son las aplicaciones las que se encargan de emitirlas con el formato, información y nivel de detalle que desean. En Java una de las librerías que se suele emplear de soporte para emitir trazas es Log4j 2.

Por otro lado, al centralizar las trazas en una herramienta hace que todas estén mezcladas de modo que encontrar las correlacionadas que se ha emitido por una aplicación en una petición o todas las trazas que ha desencadenado en diferentes servicios es necesario utilizar identificadores globales y Sleuth. Teniendo el identificador global único basta con hacer una búsqueda para encontrar todas las relacionadas que permiten analizar en detalle el comportamiento de la aplicación para una petición.

Otra parte importante en las trazas es no incluir u ofuscar los datos sensibles como datos personales o contraseñas.

Ejemplo monitorización de trazas con ELK y Docker

ELK son en realidad tres herramientas individuales diferentes que en conjunto proporcionan la funcionalidad que permite monitorizar las trazas de los servicios de forma centralizada y almacenarlas para su consulta en un futuro. Pueden ser cuatro herramientas si se usa Logstash como intermediario entre Filebeat y Elasticsearch.

Utilizando Docker y Docker Compose en un archivo se puede definir la colección de contenedores para arrancarlos como una unidad. En este caso se inicia un contenedor para Elasticsearch, para Kibana y otro para Filebeats que monitoriza el servicio de Docker con todos los contenedores que se inicien.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
version: '3'
services:
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.9.1
    container_name: elasticsearch
    environment:
      - node.name=elasticsearch
      - cluster.name=elasticsearch-cluster
      - discovery.seed_hosts=
      - cluster.initial_master_nodes=elasticsearch
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms2048m -Xmx2048m"
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - /usr/share/elasticsearch/data
    ports:
      - 9200:9200
    networks:
      - elk

  kibana:
    image: docker.elastic.co/kibana/kibana:7.9.1
    container_name: kibana
    ports:
      - 5601:5601
    environment:
      ELASTICSEARCH_URL: http://elasticsearch:9200
      ELASTICSEARCH_HOSTS: http://elasticsearch:9200
    networks:
      - elk

  filebeat:
    image: docker.elastic.co/beats/filebeat:7.9.1
    container_name: filebeat
    user: root
    command:
      - "-e"
      - "--strict.perms=false"
      - "-E"
      - output.elasticsearch.hosts=["elasticsearch:9200"]
    volumes: 
      - "./filebeat.docker.yml:/usr/share/filebeat/filebeat.yml:ro"
      - "/var/lib/docker/containers:/var/lib/docker/containers:ro"
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
    depends_on:
      - elasticsearch
    networks:
      - elk

networks:
  elk:
    name: elk
    driver: bridge

docker-compose-elk.yml
1
2
3
4
5
$ # Para evitar este error que impide iniciar Elasticsearch  hay que cambiar esta configuración en el sistema (solo afecta a la ejecución actual, en el siguiente inicio no se conserva)
$ # [1]: max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]
$ sudo sysctl -w vm.max_map_count=262144

$ docker-compose -f docker-compose-elk.yml up
docker-compose-elk.sh

Filebeat permite indexar las trazas de un archivo de log que genera la aplicación o en el caso de un contenedor de Docker las que emite en la salida estándar o en la salida de error. Filebeat monitoriza los contenedores de Docker y según las etiquetas que se le asignan al contenedor personaliza la indexación de las trazas. Filebeat ofrece módulos para indexar las trazas de algunas herramientas como el servidor web Nginx o Apache, entiende su formato, procesa la traza emitida, la enriquece con sus propios datos y las envía a Elascticsearch o si fuese el caso a Logstash.

Para configurar Elascticsearch y Filebeat es necesario realizar una configuración con un contenedor y comando de Filebeat que crea el índice en Elasticsearch y configura algunos paneles de visualización.

1
2
$ docker run --rm --network elk docker.elastic.co/beats/filebeat:7.9.1 setup -E setup.kibana.host=kibana:5601 -E output.elasticsearch.hosts=["elasticsearch:9200"]

filebeat-setup.sh

El siguiente comando arranca un contenedor con una instancia de Nginx. El archivo de Docker Compose para iniciar el contenedor de Nginx incluye varias etiquetas para activar la monitorización de trazas de Filebeat. Filebeat monitoriza los contenedores que se inician y las trazas que emiten los contenedores que tiene asociadas las etiquetas que activan Filebeat.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
version: '3'
services:
  nginx:
    image: nginx:latest
    container_name: nginx
    labels:
      - "co.elastic.logs/enabled=true"
      - "co.elastic.logs/module=nginx"
      - "co.elastic.logs/fileset.stdout=access"
      - "co.elastic.logs/fileset.stderr=error"
    ports:
      - "8080:80"
docker-compose-nginx.yml
1
2
$ docker-compose -f docker-compose-nginx.yml up

docker-compose-nginx.sh

Al acceder a alguna página del servidor web emite una traza como salida. En este caso se solicita la página por defecto y el navegador intenta encontrar el favicon de la web, la página se devuelve con un código de estado 200 y el favicon como no está configurado se devuelve un código de estado 404 de recurso no encontrado.

1
2
nginx    | 172.23.0.1 - - [25/Sep/2020:15:24:32 +0000] "GET / HTTP/1.1" 200 612 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:80.0) Gecko/20100101 Firefox/80.0" "-"
nginx    | 172.23.0.1 - - [25/Sep/2020:15:24:32 +0000] "GET /favicon.ico HTTP/1.1" 404 153 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:80.0) Gecko/20100101 Firefox/80.0" "-"
nginx.out

Kibana es la herramienta como cliente web que permite consultar las trazas almacenadas en Elasticsearch, permite crear filtros para precisar las trazas a buscar y limitar las consultas a ciertos periodos de tiempo, muestra las ocurrencias encontradas y el número de ellas en un cierto periodo de tiempo. Filebeat además de las trazas que generan los contenedores indexa algunas propiedades adicionales como el nombre del contenedor, la imagen del contenedor, datos del agente que realiza la solicitud, marca de tiempo de generación junto a más datos que permite filtrar para encontrar las trazas deseadas entre todas las indexadas de todos los contenedores. También permite seleccionar las trazas en un rango de tiempo y los campos de datos a mostrar como resultado. Kibana tiene su propia sintaxis para realizar las consultas y permite guardarlas para futuros usos y compartirlas, además de poder construir avanzados paneles de información.

En el ejemplo Kibana se accede a través de la dirección http://localhost:5601 con un navegador web.

Búsqueda en Kibana de trazas del contenedor Docker de Nginx Página de inicio por defecto de Nginx

Búsqueda en Kibana de trazas del contenedor Docker de Nginx al solicitar la página por defecto
Terminal

El código fuente completo del ejemplo puedes descargarlo del repositorio de ejemplos de Blog Bitix alojado en GitHub.


Comparte el artículo: