El monitorizado de sistemas y aplicaciones proporciona un importante mecanismo para el análisis del funcionamiento de estos, pudiéndose llevar a cabo en tiempo real midiendo su comportamiento en el momento actual para poder detectar posibles futuros problemas y anticiparse a estos consultando las métricas definidas. Esto permite actuar con premeditación tomando las acciones necesarias para aplicar las correcciones antes que se produzcan los problemas o una vez detectados los problemas, implementar sus soluciones.
Grafana es una solución que permite el monitorizado completo de sistemas y aplicaciones mediante la recolección de métricas y logs desde multitud de fuentes de datos.
El stack de Grafana cubre todas las fases desde la recolección del dato hasta su visualización gracias a los diferentes componentes que la componen:
- Prometheus: Encargado de la recolección de métricas. Utiliza un modelo Pull de recolección por el cual es el propio Prometheus quién requiere los datos al sistema monitorizado, que debe disponer de un endpoint al cual se pueda conectar. El stack dispone del componente Node-Exporter que proporciona acceso a multitud de métricas al instalarlo en el sistema objeto (CPU, uso de memoria, disco, red…). Es apropiado para la recolección de datos en intervalos de tiempo programados, aunque también proporciona mecanismos para su uso en ejecuciones batch u one-shot.
- Graphite: Encargado de la recolección de métricas. A diferencia de Prometheus, funciona mediante un modelo Push, por lo que es el propio sistema objeto de la monitorización el encargado de enviar los datos a Graphite a través de un endpoint que este provee.
- Loki: Encargado de la recolección de trazas de log. Como Graphite utiliza un modelo Push para publicar los datos en Loki pero afortunadamente en este caso el componente Promtail facilita la tarea encargándose de extraer las trazas de log y dándoles el formato apropiado para su publicación.
- Grafana: Permite la visualización y explotación de métricas y trazas de log accesibles mediante la conexión a diversas fuentes de datos, entre las que se incluyen los mencionados Prometheus, Graphite y Loki, pero que también incluyen plug-ins para la conexión a servicios en la nube como AWS CloudWatch, Azure Monitor, Google Cloud Monitoring, bases de datos relacionales (MySQL, PostgreSQL, MSSSQL…), NoSQL (ElasticSearch, OpenTSBD…) o sistemas de recolección de trazas de log (Jaeger, Zipkin…).
Este es el inicio de una serie de artículos donde se propondrá la construcción de un sistema centralizado de monitorizado de sistemas y aplicaciones con capacidad de análisis de métricas y trazas de log.
El sistema propuesto estará compuesto por los siguientes componentes:
- Prometheus: Centralizará los datos de métricas de aplicaciones y sistemas. En los sistemas monitorizados se utilizará la utilidad Node-Exporter para extraer las métricas requeridas des del Grafana.
- Loki: Centralizará los datos de las trazas de log extraídas de cada una de las aplicaciones y sistemas monitorizados. La utilidad Promtail permitirá extraer y transformar las trazas en el sistema origen antes de enviarlas a Loki.
- Grafana: Será el componente utilizado para la presentación y análisis de los datos recogidos. Se conectará a Prometheus y Loki de los que extraerá la información requerida por las diferentes visualizaciones que se pueden configurar.
En el presente artículo se introduce el proceso de instalación del stack de Grafana propuesto. En posteriores artículos se tratarán los procesos de extracción de datos, prestando atención a las configuraciones especificas de los componentes Promtail y Node-Exporter; el proceso de integración de los datos contenidos en Prometheus y Loki dentro de Grafana; y por último, la visualización y explotación de estos en dashboards.
Preparación
En el ejemplo expuesto en este artículo, se realizará la instalación del stack de Grafana en un sistema Ubuntu 18.04 Bionic, pero las instrucciones utilizadas son compatibles o son fácilmente portables a versiones posteriores.
Instalación de Docker
Los servicios principales del stack Prometheus, Loki y Grafana se ejecutaran como contenedores de Docker. Al tratarse de múltiples contenedores que se ejecutaran de forma conjunta, se utilizará Docker Compose para gestionarlos en bloque. Para ello, primeramente será necesario instalar los mencionados Docker y Docker-Compose realizando las siguientes acciones:
– Instalación de paquetes necesarios
sudo apt-get update
sudo apt-get install \
apt-transport-https \
ca-certificates \
curl \
gnupg-agent \
software-properties-common
– Configuración del repositorio de Docker
# Añadir la clave gpg del repositorio al registro
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
# Añadir el repositorio al registro
sudo add-apt-repository "deb https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
El comando lsb_release
sirve para inferir la versión de Ubuntu que se está ejecutando, en este caso bionic
.
– Instalación de los paquetes de Docker necesarios
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose
Configuración de los componentes del stack
Los componentes de stack de Grafana propuesto en este artículo comprenden 2 tipologías de instalación:
- Los componentes Node-Exporter y Promtail se ejecutarán de forma nativa en cada uno de los sistemas de los que se quiera obtener información. Naturalmente, esto incluye el host que ejecutará los contenedores de Docker del punto anterior, pero no están limitados a este. Para garantizar la ejecución automatizada de estos componentes, se instalarán como servicios en los sistemas requeridos.
- Los componentes Prometheus, Loki y Grafana se ejecutarán en forma de contenedores Docker en el host principal donde se quiera centralizar la información recogida. Para estos componentes el proceso de instalación se detallará en 2 apartados diferentes en esta misma sección: Uno correspondiente a las configuraciones necesarias en el sistema (si procede) y el apartado final Docker-Compose Service con las instrucciones para crear la configuración de servicios unificada mediante Docker-Compose.
otro con las instrucciones necesarias para crear el contenedor de Docker correspondiente
La instalación de los diferentes componentes en cada uno de los sistemas se realizará tomando /usr/local/grafana
como directorio base. Todas las rutas relativas que se especifican a continuación tomarán esta ubicación como referencia a no ser que se indique lo contrario.
Node-Exporter
El ejecutable de Node-Exporter se puede descargar desde la siguiente dirección y dispone de diferentes versiones dependiendo de la arquitectura en la que se vaya a instalar.
Una vez descargado el binario y descomprimido en el directorio node_exporter/bin
, se creará la configuración del servicio encargado de ejecutarlo. Se deberá crear el fichero /etc/systemd/system/node_exporter.service
con la configuración expuesta a continuación. Para este ejemplo, se presupone en el sistema el usuario grafana
con permisos de acceso a los directorios correspondientes de la instalación de Node-Exporter. Será posible modificar este valor con otro usuario según sea el caso.
[Unit]
Description=Node Exporter (Node Exporter Service)
After=syslog.target
After=network.target
[Service]
Type=simple
User=grafana
Group=grafana
WorkingDirectory=/usr/local/grafana
ExecStart=/usr/local/grafana/node_exporter/bin/node_exporter
Environment=USER=grafana HOME=/usr/local/grafana
[Install]
WantedBy=multi-user.target
Para habilitar y arrancar el servicio, se deberán ejecutar los siguientes comandos:
sudo systemctl enable node-exporter
sudo systemctl start node-exporter
Con el servicio en ejecución, se habilitará un endpoint http (http://localhost:9100/metrics) donde posteriormente se conectará Prometheus para extraer las métricas del sistema.
Nota En un posterior artículo se detallará qué métricas concretas se exponen y cómo pueden ser filtradas.
En caso de que el sistema del que se quieren explotar los datos sea Windows, en lugar de Node-Exporter se deberá utilizar Windows-Exporter. En este apartado se refiere únicamente el proceso de instalación para sistemas Ubuntu o similares.
Promtail
El ejecutable de Promtail se puede descargar desde la [siguiente dirección][promtail-dowload] y dispone de diferentes versiones dependiendo de la arquitectura en la que se vaya a instalar. Para asegurar total compatibilidad, se deberá escoger la misma versión que la escogida para el contenedor Docker de Loki (Mirar la definición del servicio de Docker-Compose en sección Docker-Compose Service). En el ejemplo correspondo a la versión 1.4.1
.
A diferencia de Node-Exporter el componente Promtail es quien inicia el envío de datos del sistema objeto del monitorizado hacia Loki. Su funcionamiento se basa en realizar el seguimiento de los ficheros de log indicados en la configuración, guardando la última posición de que ya se ha tratado. Si detecta que se han añadido nuevas trazas, las extrae de dichos ficheros, les aplicará unas transformaciones establecidas y las enviará al endpoint de Loki configurado.
Todo esto se plasmará en un fichero de configuración en formato yaml llamado promtail-config.yml
que se ubicará en el directorio promtail/conf
. A continuación se muestra una configuración de ejemplo donde se puede ver como se especifica todo esto.
Nota En un posterior artículo se analizará con mayor detalle, sobretodo en lo que concierne a las fases de extracción y transformación:
# Se indica el fichero donde se guardarán los punteros al contenido de los ficheros de log que ya han sido tratados.
# Estos punteros se irán actualizado conforme se vayan procesando los ficheros para evitar enviar contenidos duplicados.
positions:
filename: /usr/local/grafana/tmp/positions.yaml
# Se configura el endpoint de Loki a donde se enviará la información de las trazas extraidas
client:
url: http://localhost:3100/loki/api/v1/push
# Configuración de la extracción
scrape_configs:
# Se podrán definir multiples jobs para diferentes tipologias de log a los que se le aplica un nombre elegido por el usuario para diferenciarlos
- job_name: application_logs
# El proceso de extracción y transformación consta de diferentes fases antes del envío
pipeline_stages:
- match:
selector: '{host="localhost"}'
stages:
- regex:
expression: '^(?P<timestamp>\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}\.\d{2,3})\s\[(?P<thread>.+)\]\s(?P<level>INFO|WARN|DEBUG|ERROR)\s(?P<logger>[a-zA-Z0-9\.]+)\s(?P<message>.*)$'
- labels:
level:
thread:
logger:
- timestamp:
# 01=MM; 02=DD; 03=HH; 15=HH24; 04=MI; 05=SS; 2006=YYYY
format: '2006-01-02 15:04:05.000'
source: timestamp
- template:
source: message
template: '{{ Replace .Value "\u2028" "\r\n" -1 }}'
# Configuración de los ficheros a monitorizar y las etiquetas adicionales que se añadirán a los datos extraídos
static_configs:
- targets:
- localhost
labels:
# Ruta de los ficheros a monitorizar
__path__: /logs/application/*.log
job: application_logs
host: localhost
Una vez descargado el binario y descomprimido en el directorio promtail/bin
, se creará la configuración del servicio encargado de ejecutarlo. Se deberá crear el fichero /etc/systemd/system/promtail.service
con la configuración expuesta a continuación. Para este ejemplo, se presupone en el sistema el usuario grafana
con permisos de acceso a los directorios correspondientes de la instalación de Promtail. Será posible modificar este valor con otro usuario según sea el caso.
[Unit]
Description=Promtail (Promtail Service)
After=syslog.target
After=network.target
[Service]
Type=simple
User=grafana
Group=grafana
WorkingDirectory=/usr/local/grafana
ExecStart=/usr/local/grafana/promtail/bin/promtail-linux-amd64 -config.file=/usr/local/grafana/promtail/conf/promtail-config.yml
Environment=USER=grafana HOME=/usr/local/grafana
[Install]
WantedBy=multi-user.target
Para habilitar y arrancar el servicio, se deberán ejecutar los siguientes comandos:
sudo systemctl enable promtail
sudo systemctl start promtail
Prometheus
Dado que Prometheus utiliza un modelo Pull para la recogida de métricas, es necesario especificar los host y frecuencia con las que se conectará a ellos para extraer datos. Toda esta información se recogerá un el fichero en formato yaml llamado prometheus.yml
. Se ubicará en el directorio prometheus/conf
que posteriormente se montará en forma de volumen al correspondiente contenedor de Docker. A continuación se muestra una posible configuración de este fichero a modo de ejemplo de la conexión al sistema host donde se ejecuta el contenedor Docker de Prometheus para extraer las métricas recogidas por la instancia de Node-Exporter local.
Nota En un posterior artículo se analizará con mayor detalle.
# Configuración global de prometheus. Contiene variables globales para las diferentes configuraciones de scrap
global:
scrape_interval: 15s # Por defecto, el proceso de scrap se ejecuta cada 15 segundos
# Configuració de scrap
scrape_configs:
# Nombre del job que se añade como etiqueta `job=<job_name>` a cualquier timeseries recolectada a partir de esta configuración
- job_name: 'prometheus'
# Es posible sobreescribir propiedades definidas de forma global para adaptarlas a cada poceso local
scrape_interval: 5s
# IP configurada en /etc/docker/daemon.json (parametro bip).
# Se utiliza para hacer referencia al host desde un contenedor de docker. Por defecto 172.17.0.1
# En este ejemplo el puerto corresponde con el que se ha configurado para Node-Exporter anteriormente (9100)
static_configs:
- targets: [ '172.17.0.1:9100' ]
Loki
Como en el caso anterior, se creará el directorio loki/conf
donde se ubicará la configuración que se especificará al contenedor de Docker correspondiente a Loki. El fichero nombrarse como loki-config.yaml
. Al tratarse de un componente que recibe la información de forma pasiva, por ahora bastará con hacer referencia a los parámetros por defecto recogidos en los ejemplos de la documentación oficial de Loki.
Nota En un posterior artículo se analizarán con mayor detalle las posibilidades de configuración.
Docker-Compose Service
Una vez realizadas las configuraciones expuestas en los apartados anteriores, se definirá la configuración de servicios de Docker compose para el conjunto de contenedores del stack Prometheus / Loki / Grafana en el fichero docker-compose.yml
. Esto se deberá hacer únicamente en el host
donde se quiera centralizar la información. Siguiendo la pauta de directorios expuesta en el resto de apartados, este fichero se ubicará en el directorio /usr/local/grafana
. El contenido del fichero será el siguiente:
version: "3"
networks:
grafana:
services:
loki:
image: grafana/loki:1.4.1
container_name: loki_1
ports:
- "3100:3100"
volumes:
- /usr/local/grafana/loki/conf:/etc/loki
command: -config.file=/etc/loki/loki-config.yaml
networks:
- grafana
restart: always
prometheus:
image: prom/prometheus:v2.17.2
container_name: prometheus_1
ports:
- "9090:9090"
volumes:
- /usr/local/grafana/prometheus/conf:/etc/prometheus
networks:
- grafana
restart: always
grafana:
image: grafana/grafana:master
container_name: grafana_1
ports:
- "3000:3000"
networks:
- grafana
restart: always
Los puntos clave de esta definición son:
- Se define en la sección
networks
una red interna con el nombregrafana
que permitirá la comunicación interna entre los diferentes contenedores definidos en la secciónservices
. - Se definen en la sección
services
la configuración de los contenedores para Loki, Prometheus y Grafana. Para cada uno de ellos se define la imagen proveniente de docker hub que se utilizará como base del contenedor y uncontainer_name
. Una vez sea creado, servirá como referencia para identificarlo en la lista de contenedores gestionados por Docker en el sistema. - En la definición del service
loki
:- Se mapea el puerto
3100
del contenedor al puerto3100
del sistema host para hacer accesibles los endpoints de Loki fuera del contenedor. De otra manera los componentes Promtail instalados no serán capaces de registrar información de las trazas extraídas. - Se mapea el directorio
/usr/local/grafana/loki/conf
del sistema host a la ruta/etc/loki
del contenedor para hacer accesible la configuración externa a la instancia de Loki que se ejecuta dentro del contenedor.
- Se mapea el puerto
- El la definición del service
prometheus
:- Aunque la visualización de los datos gestionados por Prometheus se puede hacer integramente desde Grafana, Prometheus provee de un frontal web desde el que se pueden realizar consultas directamente. Para habilitarlo se mapea el puerto
9090
del contenedor al puerto9090
del sistema host. Este frontal será accesible desde la urlhttp://localhost:9090/graph
- Como en el caso del service de Loki se mapea el directorio del sistema host que contiene la configuración externa para la instancia (
/usr/local/grafana/prometheus/conf
) a la correspondiente ruta del contenedor (/etc/prometheus
).
- Aunque la visualización de los datos gestionados por Prometheus se puede hacer integramente desde Grafana, Prometheus provee de un frontal web desde el que se pueden realizar consultas directamente. Para habilitarlo se mapea el puerto
- El la definición del service
grafana
:- Se mapea el puerto
3000
del contenedor al puerto3000
del sistema host para hacer accesible la interfaz web de Grafana fuera del contenedor. - A diferencia de los otros 2 contenedores, Grafana no require la especificación de configuraciones externas, por lo que no es necesario el mapeo de directorios al contenedor.
- Se mapea el puerto
- A todos los servicios se les especifica que usen la red interna
grafana
(apartadonetworks
) y que deben aplicar la política de reinicioalways
que permite reiniciar la ejecución de los contenedores al iniciar el sistema.
Una vez finalizada la edición del fichero docker-componse.yml
, se procederá a la ejecución del siguiente comando para crear los contenedores y iniciar su ejecución:
sudo docker-compose up -d
Dado que se ha especificado una política de reinicio always
en cada uno de los servicios, no será necesario volver a ejecutar este comando a menos que se paren los servicios manualmente.
Se podrá acceder a la interfaz web de Grafana a través de la url http://localhost:3000
en un navegador. El nombre de usuario y contraseña iniciales son admin
/ admin
. Después de la primera identificación estos podrán ser cambiados a otros valores más adecuados.