Monitoreo de servicios con Prometheus y Grafana

En este artículo se describe el proceso de instalación y configuración de la solución de monitoreo Prometheus junto al panel de visualización Grafana en un sistema Debian 10.

Las herramientas

  • Prometheus es un sistema de monitoreo que permite recoger datos métricos de series temporales de cualquier sistema objetivo. Su interfaz web permite realizar potentes consultas, visualizar los datos recogidos y configurar alertas. Es un proyecto de software de código abierto. Las métricas del se recogen utilizando extracciones HTTP, lo que permite un mayor rendimiento y escalabilidad.
    Otras características que lo constituyen una herramienta de vigilancia completa son:

    • Exporters: Se trata de librerías que ayudan a exportar métricas de sistemas de terceros como métricas de Prometheus.
    • PromQL: Lenguaje de consulta de Prometheus que permite filtrar datos de series temporales multidimensionales.
  • Grafana es un panel de métricas y un editor de gráficos para Graphite, Elasticsearch, OpenTSDB, Prometheus e InfluxDB.

Instalar Prometheus

Crearemos un usuario de sistema y un grupo dedicado para Prometheus. El parámetro –system se utiliza para este propósito.

# groupadd --system prometheus

Un grupo con ID < 1000 es un grupo de sistema. Una vez añadido al grupo de sistema, creamos el usuario del sistema Prometheus y asignamos el grupo creado. Como no necesita el shell /bin/bash, usamos -s /sbin/nologin

# useradd -s /sbin/nologin --system -g prometheus prometheus

Configuración y directorios de datos

Prometheus necesita un directorio para almacenar sus datos. Lo crearemos en /var/lib/prometheus.

# mkdir /var/lib/prometheus

El directorio principal de archivos de configuración de Prometheus es /etc/prometheus/. Tendrá algunos subdirectorios:

# for i in rules rules.d files_sd; do sudo mkdir -p /etc/prometheus/${i}; done

Descarga e instalación

Descargamos la última versión de Prometheus. Podés comprobar las versiones en Github.

# mkdir -p /tmp/prometheus && cd /tmp/prometheus
# curl -s https://api.github.com/repos/prometheus/prometheus/releases/latest \
 | grep browser_download_url \
 | grep linux-amd64 \
 | cut -d '"' -f 4 \
 | wget -qi -

Nota: El comando anterior no muestra progreso, uno puede sentirse tentado a abortar el proceso. Paciencia.

Extraemos los archivos.

# tar xvf prometheus*.tar.gz
# cd prometheus*/

Movemos los binarios a /usr/local/bin/.

# mv prometheus promtool /usr/local/bin/

Verificamos la versión instalada

# prometheus --version
prometheus, version 2.23.0 (branch: HEAD, revision: 26d89b4b0776fe4cd5a3656dfa520f119a375273)
 build user: root@37609b3a0a21
 build date: 20201126-10:56:17
 go version: go1.15.5
 platform: linux/amd64
# promtool --version
promtool, version 2.23.0 (branch: HEAD, revision: 26d89b4b0776fe4cd5a3656dfa520f119a375273)
 build user: root@37609b3a0a21
 build date: 20201126-10:56:17
 go version: go1.15.5
 platform: linux/amd64

Movemos la plantilla de configuración de prometheus al directorio /etc/prometheus.

# mv prometheus.yml /etc/prometheus/prometheus.yml

También movemos consoles y console_libraries al directorio /etc/prometheus:

# mv consoles/ console_libraries/ /etc/prometheus/
# cd ~/
# rm -rf /tmp/prometheus

Archivo de configuración

# nano /etc/prometheus/prometheus.yml

El archivo de configuración predeterminado es similar al siguiente.

# my global config
global:
 scrape_interval: 15s # Set the scrape interval to every 15 seconds. Default is every 1 minute.
 evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute.
 # scrape_timeout is set to the global default (10s).
# Alertmanager configuration
alerting:
 alertmanagers:
 - static_configs:
 - targets:
 # - alertmanager:9093
# Load rules once and periodically evaluate them according to the global 'evaluation_interval'.
rule_files:
 # - "first_rules.yml"
 # - "second_rules.yml"
# A scrape configuration containing exactly one endpoint to scrape:
# Here it's Prometheus itself.
scrape_configs:
 # The job name is added as a label `job=<job_name>` to any timeseries scraped from this config.
 - job_name: 'prometheus'
 # metrics_path defaults to '/metrics'
 # scheme defaults to 'http'.
 static_configs:
 - targets: ['localhost:9090']

Nota: La sección scrape_configs no puede arrancar en la columna 0.

Crear un archivo de unidad de servicio systemd para Prometheus

Para poder gestionar el servicio Prometheus con systemd, es necesario definir explícitamente este archivo.

tee /etc/systemd/system/prometheus.service<<EOF
[Unit]
Description=Prometheus
Documentation=https://prometheus.io/docs/introduction/overview/
Wants=network-online.target
After=network-online.target

[Service]
Type=simple
User=prometheus
Group=prometheus
ExecReload=/bin/kill -HUP  ""$MAINPID
ExecStart"" =/usr/local/bin/prometheus \
 --config.file=/etc/prometheus/prometheus.yml \
 --storage.tsdb.path=/var/lib/prometheus \
 --web.console.templates=/etc/prometheus/consoles \
 --web.console.libraries=/etc/prometheus/console_libraries \
 --web.listen-address=0.0.0.0:9090 \
 --web.external-url=

SyslogIdentifier=prometheus
Restart=always

[Install]
WantedBy=multi-user.target
EOF

Cambiamos la propiedad de los directorios y archivos al usuario y grupo de Prometheus.

# for i in rules rules.d files_sd; do chown -R prometheus:prometheus /etc/prometheus/${i}; done
# for i in rules rules.d files_sd; do chmod -R 775 /etc/prometheus/${i}; done
# chown -R prometheus:prometheus /var/lib/prometheus/

Recargamos el demonio de systemd e iniciamos el servicio.

# systemctl daemon-reload
# systemctl start prometheus
# systemctl enable prometheus

Verificamos que el servicio se está ejecutando.

# systemctl status prometheus
● prometheus.service - Prometheus
 Loaded: loaded (/etc/systemd/system/prometheus.service; enabled; vendor prese
 Active: active (running) since Wed 2020-12-23 10:24:58 -03; 4min 28s ago
 Docs: https://prometheus.io/docs/introduction/overview/
 Main PID: 30863 (prometheus)
 Tasks: 12 (limit: 4915)
 CGroup: /system.slice/prometheus.service
 └─30863 /usr/local/bin/prometheus --config.file=/etc/prometheus/prome
dic 23 10:24:59 hostprometheus prometheus[30863]: level=info ts=2020-12-23T13:24:59.44

Confirmamos que podemos conectarnos al puerto 9090 accediendo la interfaz web de Prometheus en http://[ip_host]:9090 desde algún navegador web.

Instalar node_exporter

Descargamos los el binario

# mkdir -p /tmp/node_exporter && cd /tmp/node_exporter
# curl -s https://api.github.com/repos/prometheus/node_exporter/releases/latest \
 | grep browser_download_url \
 | grep linux-amd64 \
 | cut -d '"' -f 4 \
 | wget -qi -

Extraemos el archivo descargado y lo movemos a /usr/local/bin.

# tar -xvf node_exporter*.tar.gz
# cd node_exporter*/
# cp node_exporter /usr/local/bin
# cd ~/
# rm -rf /tmp/node_exporter

Verificamos la instalación.

# node_exporter --version
node_exporter, version 1.0.1 (branch: HEAD, revision: 3715be6ae899f2a9b9dbfd9c39f3e09a7bd4559f)
 build user: root@1f76dbbcfa55
 build date: 20200616-12:44:12
 go version: go1.14.4

Creamos el servicio node_exporter.

tee /etc/systemd/system/node_exporter.service <<EOF
[Unit]
Description=Node Exporter
Wants=network-online.target
After=network-online.target
[Service]
User=prometheus
ExecStart=/usr/local/bin/node_exporter
[Install]
WantedBy=default.target
EOF

Recargamos systemd e iniciamos el servicio.

# systemctl daemon-reload
# systemctl start node_exporter
# systemctl enable node_exporter

Verificamos el estado:

# systemctl status node_exporter.service
● node_exporter.service - Node Exporter
 Loaded: loaded (/etc/systemd/system/node_exporter.service; enabled; vendor preset: enabled)
 Active: active (running) since Sun 2020-11-15 09:58:20 -03; 1h 8min ago
 Main PID: 22879 (node_exporter)
 Tasks: 6 (limit: 4585)
 Memory: 6.6M
 CGroup: /system.slice/node_exporter.service
 └─22879 /usr/local/bin/node_exporter
.................................................

Agregamos node_exporter al servidor Prometheus.

# nano /etc/prometheus/prometheus.yml

Agregamos un nuevo job a la sección scrape_config.

- job_name: 'node_exporter'
 static_configs:
 - targets: ['localhost:9100']

Reiniciamos Prometheus:

# systemctl restart prometheus

Instalar Apache exporter

Descargamos los el binario

# mkdir -p /tmp/apache_exporter && cd /tmp/apache_exporter
# curl -s https://api.github.com/repos/Lusitaniae/apache_exporter/releases/latest \
 | grep browser_download_url \
 | grep linux-amd64 \
 | cut -d '"' -f 4 \
 | wget -qi -

Extraemos el archivo descargado y lo movemos a /usr/local/bin.

# tar -xvf apache_exporter*.tar.gz
# cd apache_exporter*/
# cp apache_exporter /usr/local/bin
# cd ~/
# rm -rf /tmp/apache_exporter

Verificamos la instalación.

# apache_exporter --version
apache_exporter, version (branch: , revision: )
 build user:
 build date:
 go version: go1.13.9

Creamos el servicio apache_exporter.

# tee /etc/systemd/system/apache_exporter.service <<EOF
[Unit]
Description=Prometheus
Documentation=https://github.com/Lusitaniae/apache_exporter
Wants=network-online.target
After=network-online.target
[Service]
Type=simple
User=prometheus
Group=prometheus
ExecReload=/bin/kill -HUP  """"""""""$MAINPID
ExecStart"""""""""" =/usr/local/bin/apache_exporter \
 --insecure \
 --scrape_uri=http://localhost/server-status/?auto \
 --telemetry.address=0.0.0.0:9117 \
 --telemetry.endpoint=/metrics
SyslogIdentifier=apache_exporter
Restart=always
[Install]
WantedBy=multi-user.target
EOF

El servicio escuchará en el puerto 9117, y la métrica expuesta en /metrics. Si las métricas de Apache no están en http://localhost/server-status/?auto tendrás que cambiar la URL.

Recargamos systemd e iniciamos el servicio.

# systemctl daemon-reload
# systemctl start apache_exporter
# systemctl enable apache_exporter

Verificamos el estado:

# systemctl status apache_exporter.service
● apache_exporter.service - Prometheus
 Loaded: loaded (/etc/systemd/system/apache_exporter.service; enabled; vendor
 Active: active (running) since Thu 2020-11-12 10:40:16 -03; 3 days ago
 Docs: https://github.com/Lusitaniae/apache_exporter
 Main PID: 23714 (apache_exporter)
 Tasks: 13 (limit: 4915)
 CGroup: /system.slice/apache_exporter.service
 └─23714 /usr/local/bin/apache_exporter --insecure --scrape_uri=https:

Confirme que el puerto está escuchando las solicitudes.

# sudo ss -tunelp | grep 9117
tcp LISTEN 0 128 :::9117 :::* users:(("apache_exporter",pid=23714,fd=3)) uid:998 ino:75927058 sk:23 v6only:0 <->

Agregamos apache_exporter al servidor Prometheus.

# nano /etc/prometheus/prometheus.yml

Agregamos un nuevo job a la sección scrape_config.

# Servidores Apache
 - job_name: apache1
 static_configs:
 - targets: ['localhost:9117']
 labels:
 alias: servidor1

Reiniciamos Prometheus:

# systemctl restart prometheus

Instalar Bind exporter

BIND debe soportar libxml2, lo cual se puede confirmar usando:

# named -V | grep libxml2
compiled with libxml2 version: 2.9.4
linked to libxml2 version: 20909

Descargamos los el binario

# mkdir -p /tmp/bind_exporter && cd /tmp/bind_exporter
# curl -s https://api.github.com/repos/prometheus-community/bind_exporter/releases/latest \
 | grep browser_download_url \
 | grep linux-amd64 \
 | cut -d '"' -f 4 \
 | wget -qi -

Extraemos el archivo descargado y lo movemos a /usr/local/bin.

# tar -xvf bind_exporter*.tar.gz
# cd bind_exporter*/
# mv bind_exporter /usr/local/bin
# cd ~/
# rm -rf /tmp/bind_exporter

Verificamos la instalación.

# bind_exporter --version
bind_exporter, version 0.3.0 (branch: HEAD, revision: c34ff3d6b4817f42e74b2b05b3797cf99683b4a9)
 build user: root@48c85d39c9a6
 build date: 20200109-18:54:09
 go version: go1.12.14

Es necesario configurar BIND para abrir un canal de estadísticas. Como el exportador y BIND están en el mismo host, el puerto se abre localmente.

Editamos el archivo /etc/bind/named.conf.options.

statistics-channels {
 inet 127.0.0.1 port 8053 allow { 127.0.0.1; };
};

Reiniciamos Bind para que los cambios entren en efecto

# systemctl restart bind9

Creamos el servicio bind_exporter.

# tee /etc/systemd/system/bind_exporter.service<<EOF
[Unit]
Description=Prometheus
Documentation=https://github.com/digitalocean/bind_exporter
Wants=network-online.target
After=network-online.target
[Service]
Type=simple
User=prometheus
Group=prometheus
ExecReload=/bin/kill -HUP  """"""""""$MAINPID
ExecStart"""""""""" =/usr/local/bin/bind_exporter \
 --bind.pid-file=/var/run/named/named.pid \
 --bind.timeout=20s \
 --web.listen-address=0.0.0.0:9153 \
 --web.telemetry-path=/metrics \
 --bind.stats-url=http://localhost:8053/ \
 --bind.stats-groups=server,view,tasks
SyslogIdentifier=prometheus
Restart=always
[Install]
WantedBy=multi-user.target
EOF

Recargamos systemd e iniciamos el servicio.

# systemctl daemon-reload
# systemctl start bind_exporter
# systemctl enable bind_exporter

Verificamos el estado:

# systemctl status bind_exporter.service
● apache_exporter.service - Prometheus
 Loaded: loaded (/etc/systemd/system/apache_exporter.service; enabled; vendor
 Active: active (running) since Thu 2020-11-12 10:40:16 -03; 3 days ago
 Docs: https://github.com/Lusitaniae/apache_exporter
 Main PID: 23714 (apache_exporter)
 Tasks: 13 (limit: 4915)
 CGroup: /system.slice/apache_exporter.service
 └─23714 /usr/local/bin/apache_exporter --insecure --scrape_uri=https:

Confirme que el puerto está escuchando las solicitudes.

# ss -tunelp | grep 9153
tcp LISTEN 0 128 :::9153 :::* users:(("bind_exporter",pid=2595,fd=3)) uid:999 ino:33550831 sk:48 v6only:0 <->

Agregamos bind_exporter al servidor Prometheus.

# nano /etc/prometheus/prometheus.yml

Agregamos un nuevo job a la sección scrape_config.

 - job_name: dns-master
 static_configs:
 - targets: ['localhost:9153']
 labels:
 alias: servidor1

Reiniciamos Prometheus:

# systemctl restart prometheus

Instalar Grafana

Vamos a usar el repositorio apt, ya que se puede actualizar fácilmente a la última versión usando el gestor de paquetes apt. No obstante, también se puede realizar la instalación desde paquetes .deb

Agregamos la llave gpg de Grafana que permite instalar paquetes firmados.

# apt-get install -y gnupg2 curl software-properties-common
# curl https://packages.grafana.com/gpg.key | sudo apt-key add -

Luego agregamos el repositorio de Grafana

# add-apt-repository "deb https://packages.grafana.com/oss/deb stable main"

Actualizamos los repositorios y procedemos a instalar Grafana

# apt-get update
# apt-get -y install grafana

Iniciamos el servicio

# systemctl enable --now grafana-server

Debería estar funcionando ahora

# systemctl status grafana-server.service
● grafana-server.service - Grafana instance
   Loaded: loaded (/usr/lib/systemd/system/grafana-server.service; enabled; vendor preset: enabled)
   Active: active (running) since Mon 2020-12-21 13:59:27 -03; 1 day 23h ago
     Docs: http://docs.grafana.org
 Main PID: 19628 (grafana-server)
    Tasks: 13 (limit: 4915)
   CGroup: /system.slice/grafana-server.service
           └─19628 /usr/sbin/grafana-server --config=/etc/grafana/grafana.ini --pidfile=/var/run/grafana/grafana-server.pid --packaging=deb cfg:default.paths.logs=/var/l

dic 22 17:36:48 hostname grafana-server[19628]: t=2020-12-22T17:36:48-0300 lvl=info msg="Request Completed" logger=context userId=0 orgId=0 uname= method=GET path=/ stat
dic 22 17:49:23 hostname grafana-server[19628]: t=2020-12-22T17:49:23-0300 lvl=info msg="Request Completed" logger=context userId=0 orgId=0 uname= method=GET path=/ stat
dic 22 17:49:41 hostname grafana-server[19628]: t=2020-12-22T17:49:41-0300 lvl=info msg="Successful Login" logger=http.server User=admin@localhost
dic 22 17:52:08 hostname grafana-server[19628]: t=2020-12-22T17:52:08-0300 lvl=info msg="Successful Logout" logger=http.server User=admin@localhost
~

En este punto podremos acceder a Grafana usando la dirección IP del servidor o el nombre del host y el puerto 3000.

Las credenciales predeterminadas son: Usuario, admin; Clave, admin.

Para modificar la clave y el nombre de usuario navegamos hasta el panel de usuario, ubicado en el extremo inferior izquierdo.

Detalles del paquete Grafana

  • Instala el binario en /usr/sbin/grafana-server
  • Crea un archivo de variables de entorno en /etc/default/grafana-server, utilizado por el servicio systemd
  • Instala el archivo de configuración en /etc/grafana/grafana.ini
  • Instala el servicio systemd como grafana-server.service
  • La configuración predeterminada alamacena el log en /var/log/grafana/grafana.log
  • La configuración especifica una BD sqlite3 en /var/lib/grafana/grafana.db
  • Instala archivos HTML/JS/CSS y otros archivos de Grafana en /usr/share/grafana

Añadir fuentes de datos a Grafana

Para que Grafana sea útil, se debe agregar fuentes de datos para su monitoreo.

Ingresá y hace clic en Agregar fuente de datos

Desplazate hacia abajo hasta que veas la entrada de Prometheus. Al pasar el cursor sobre esa entrada veremos la opción Seleccionar, hacé clic ahí.

En la ventana resultante, se deben rellenar los detalles de la conexión. Los datos requeridos son:

  • Nombre – un identificador para la fuente de datos
  • URL – la dirección IP y el puerto del servidor Prometheus

Las demás opciones se pueden dejar como están.

Una vez que hayas completado los detalles, haz clic en Guardar & probar. Esto debería conectar con éxito a la fuente de datos Prometheus y guardar la configuración.

A continuación, puede agregar la fuente de datos a un nuevo tablero, para que Grafana pueda comenzar a monitorear la base de datos que ha seleccionado.

El paso final es crear tu propio Dashboard para visualizar la métricas o usar alguno de los disponibles. Debes tener la fuente de datos Prometheus ya debe estar añadida a Grafana.

¿Y si me olvido la clave?

En algún momento podrías olvidar la contraseña de administrador de grafana y probablemente desearás recuperarla en lugar de reinstalarlo. Si tu grafana ha estado usando sqlite como almacenamiento backend, el proceso de recuperación es fácil. Aquí están los pasos para hacerlo:

  1. Instalamos el paquete sqlite3
    apt-get install sqlite3
  2. Nos conectamos a la base de datos de grafana
    sqlite3 /var/lib/grafana/grafana.db
  3. Restablecemos la contraseña de administrador mediante SQL (la nueva contraseña será admin)
    sqlite> update user set password = '59acf18b94d7eb0694c61e60ce44c110c7a683ac6a8f09580d626f90f4a242000746579358d77dd9e570e83fa24faa88a8a6', salt = 'F3FAxVm33R' where login = 'admin';
    sqlite> .exit

Ahora, puedes volver a ingresar a grafana usando el usuario: admin y la contraseña: admin

 

La información brindada en este artículo es una recopilación realizada por su autor, basada en material disponible principalmente en computingforgeeks.com