Esta pagina se ve mejor con JavaScript habilitado

PMM2 Nginx exporter

 ·  🎃 kr0m

El módulo VTS(Virtual Host Traffic Status) de Nginx nos permite visualizar estadísticas de Nginx por vhost, estas resultan muy interesantes para detectar posibles problemas de rendimiento o preveer futuras ampliaciones de hardware, en este artículo se explicará como configurar VTS y el exporter para que Prometheus sea capaz de leer dicha información.

La monitorización de Nginx mediante Prometheus se puede realizar empleando distintos exporters:

  • Librerias Lua en Nginx que ejecutan un script de logeo de métricas en cada petición recibida, esto es un performance killer además de que no funciona(el script se ejecuta con errores).
  • Cambio del formato de log de Nginx para que guarde tiempos de respuesta en los logs y así parsearlos mediante mtail, tampoco funciona(solo saca las métricas del stat no del mtail).
  • Habilitar el stats de Nginx y arrancar un exporter que lea el status y exporte los datos en forma de métricas, proporciona una información demasiado básica.
  • Habilitar el VTS de Nginx y arrancar un exporter que lea el vts y exporte los datos en forma de métricas.

En la web de Prometheus podemos encontrar el enlace de dos exporters, la librería Lua y el VTS . Vamos a utilizar VTS ya que es la opción que mejor se adapta a mis necesidades.

Para que el exporter pueda leer los datos hay que compilar Nginx con el módulo VTS . Según el programador del módulo:

This is similar to the live activity monitoring of nginx plus

Nos bajamos el código fuente y recompilamos Nginx indicándole donde encontrar módulos adicionales:

cd /usr/src
git clone git://github.com/vozlt/nginx-module-vts.git
echo ‘NGINX_ADD_MODULES="/usr/src/nginx-module-vts"’ » /etc/portage/make.conf
emerge -av www-servers/nginx

En el configure que ejecuta emerge podemos ver:

configuring additional modules
adding module in /usr/src/nginx-module-vts
 + ngx_http_vhost_traffic_status_module was configured

Comprobamos que el Nginx compilado realmente soporte VTS:

nginx -V 2>&1 | tr -- - ‘\n’|grep vts

vts

Configuramos Nginx para que solo permita el acceso a las estadísticas desde localhost ya que solo debe acceder a estas el exporter local:

vi /etc/nginx/nginx.conf

http {
        ...
        vhost_traffic_status_zone;
        server {
            listen 80;
            server_name _;

            access_log /var/log/nginx/localhost.access_log main;
            error_log /var/log/nginx/localhost.error_log info;

            root /var/www/localhost/htdocs;

            location /status {
                allow 127.0.0.1;
                deny all;
                vhost_traffic_status_display;
                vhost_traffic_status_display_format html;
            }
        }
        ...
}

Creamos un docroot básico para hacer las pruebas:

mkdir /var/www/localhost/htdocs/
vi /var/www/localhost/htdocs/index.html

<html>
<header><title>This is title</title></header>
<body>
kr0mtest
</body>
</html>

Reiniciamos el servicio:

/etc/init.d/nginx restart

Comrpobamos que podamos acceder al status desde local:

curl http://localhost/status/format/json | jq

Compilamos e instalamos el exporter:

mkdir /etc/portage/package.accept_keywords
echo “app-metrics/nginx-vts-exporter ~amd64” > /etc/portage/package.accept_keywords/nginx-vts-exporter
emerge -av app-metrics/nginx-vts-exporter

Arrancamos el exporter:

/etc/init.d/nginx-vts-exporter start
rc-update add nginx-vts-exporter default

Comprobamos que el exporter esté a la escucha y que saque las métricas:

netstat -nputa|grep LISTEN|grep vts

tcp6       0      0 :::9913                 :::*                    LISTEN      30387/nginx-vts-exp
curl http://SERVER_IP:9913/metrics|grep -v ‘#’

Filtramos el acceso al exporter ya que vamos a poner una capa de autenticación por delante mediante Nginx:

iptables -I INPUT 1 ! -s 127.0.0.1 -p tcp --dport 9913 -j DROP
/etc/init.d/iptables save
rc-update add iptables default

Ahora el curl debería de fallar:

curl http://SERVER_IP:9913/metrics|grep -v ‘#’

curl: (28) Failed to connect to SERVER_IP port 9913: Operation timed out

Añadimos autenticación, si la petición viene del servidor PMM no pedimos credenciales:

vi /etc/nginx/nginx.conf

http {
        ...
        vhost_traffic_status_zone;
        server {
            listen 80;
            server_name _;

            access_log /var/log/nginx/localhost.access_log main;
            error_log /var/log/nginx/localhost.error_log info;

            root /var/www/localhost/htdocs;

            location /status {
                allow 127.0.0.1;
                deny all;
                vhost_traffic_status_display;
                vhost_traffic_status_display_format html;
            }
        }
        server {
            listen 9914;
            server_name _;
            location /metrics {
                satisfy any;
                allow  PMM_SERVER_IP/32;
                auth_basic "Restricted Content";
                auth_basic_user_file /etc/nginx/.htpasswd;
                deny   all;

                proxy_pass http://127.0.0.1:9913;
            }
        }
        ...
}

Reiniciamos el servicio:

/etc/init.d/nginx restart

Generamos el fichero de passwords:

emerge -av app-admin/apache-tools
htpasswd -c /etc/nginx/.htpasswd admin

Volvemos a consultar las métricas pero esta vez a través de Nginx y utilizando las credenciales:

curl --user admin:PASSWORD http://SERVER_IP:9914/metrics|grep -v ‘#’

El proceso de acceso a las métricas sigue la siguiente lógica:

  • Puerto 9914 protegido por auth mediante Nginx -> proxy_pass localhost:9913
  • Puerto 9913 filtrado por Iptables para que solo se acceda desde localhost -> /stats
  • /stats filtrado por Nginx para que solo se acceda desde localhost

La configuración de Prometheus sería esta:

vi prometheusConf/prometheus.base.yml

scrape_configs:
- job_name: nginxExporter
  scrape_interval: 1m
  scrape_timeout: 10s
  metrics_path: /metrics
  scheme: http
  static_configs:
  - targets:
    - kr0mtest3:9914
    - kr0mtest4:9914

Podemos ver el exporter en targets:

Ahora tan solo queda importar la dashboard correspondiente en Grafana y ya podremos visualizar los datos.

Vamos a Dashboards -> Manage

Importamos esta dashboard:
https://grafana.com/grafana/dashboards/2949

Para ello le damos a import:

Pegamos el id de la dashboard:

Ya podemos visualizar las gráficas:

Las alertas de Prometheus serían estas, recordad que en PMM2 las alertas se configuran desde Grafana( http://pmm.alfaexploit.com/graph/d/pmm-settings/) :

groups:
- name: nginxRules
  rules:
  - alert: NginxDown
    expr: sum(up{job="nginxExporter"} == 0) by (instance)
    for: 5m
    labels:
      severity: critical

Si paramos un Nginx podemos ver la alarma:

Si hemos seguido la guía sobre Alertmanager veremos en Telegram alertas como esta:

Si te ha gustado el artículo puedes invitarme a un RedBull aquí