Esta pagina se ve mejor con JavaScript habilitado

PMM2 Haproxy exporter

 ·  🎃 kr0m

A partir de la versión 2.0 de Haproxy este lleva incorporado el exporter de Prometheus, de este modo podremos visualizar multitud de métricas mediante Grafana y recibir alertas en base a estas, en este tutorial explicaré como configurarlo bajo PMM2.

Compilamos e instalamos Haproxy con la opción prometheus-exporter habilitada:

echo “net-proxy/haproxy crypt net_ns pcre ssl threads zlib -51degrees -device-atlas -doc -examples -libressl -lua -pcre-jit -pcre2 -pcre2-jit prometheus-exporter -slz -systemd -tools vim-syntax -wurfl” > /etc/portage/package.use/haproxy
emerge -av net-proxy/haproxy

La configuración del exporter se realiza en el mismo puerto que las stats pero dependiendo del path servirá las stats o las métricas.

vi /etc/haproxy/haproxy.cfg

frontend stats
   bind :8405
   option http-use-htx
   http-request use-service prometheus-exporter if { path /metrics }
   stats enable
   stats uri /stats
   stats refresh 10s

Debemos proteger el acceso mediante password, la configuración completa sería esta:

global
        stats socket ipv4@0.0.0.0:9999 level admin
        stats socket /var/run/haproxy.sock mode 666 level admin
        stats timeout 2m

defaults
        option forwardfor
        option http-server-close

        mode    http
        timeout connect 5000
        timeout client  50000
        timeout server  50000

userlist statsuser
        user admin insecure-password PASSWORD

frontend stats
        bind :8405
        acl pmmserver src PMM_SERVER_IP/32
        acl statsauthok http_auth(statsuser)
        http-request auth if !pmmserver !statsauthok

        option http-use-htx
        http-request use-service prometheus-exporter if { path /metrics }
        stats enable
        stats uri /stats
        stats refresh 10s

frontend www-http
        bind *:80
        default_backend www-backend

backend www-backend
        server www00 SERVERIP:80 check
        server www01 SERVERIP:80 check

NOTA: Con la configuración anterior solo pedirá password si se consultan las métricas desde un ip distinta a la del PMM server.

Arrancamos Haproxy:

/etc/init.d/haproxy start
rc-update add haproxy default

Comprobamos que los servicios se hayan bindeado a las interfaces correctas:

netstat -nputa|grep LISTEN | grep 8405

tcp        0      0 0.0.0.0:8405          0.0.0.0:*               LISTEN      10154/haproxy       

Podemos ver las métricas accediendo a la url:

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

Comprobamos que las stats sigan funcionando con normalidad:
http://SERVER_IP:8405/stats
admin/PASSWORD

Comprobamos que desde Prometheus no pida password:

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

Configuramos el scrape en Prometheus:

vi prometheusConf/prometheus.base.yml

scrape_configs:
- job_name: haproxy
  scrape_interval: 1m
  scrape_timeout: 10s
  metrics_path: /metrics
  scheme: http
  static_configs:
  - targets:
    - SERVER_IP:8405

Recargamos la configuración:

docker stop pmm-server && docker start pmm-server

En la sección de targets podemos ver el exporter, en mi caso monitorizo dos Haproxys:

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/12693

Para ello le damos a import:

Pegamos el id de la dashboard:

Ya podemos visualizar las gráficas:

Para el sistema de alertas podemos dumpear las métricas y definir las alarmas:

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

groups:
- name: haproxyRules
 rules:
 - alert: HaproxyDown
 expr: up{job="haproxy"} == 0
 for: 5m
 labels:
 severity: critical

 - alert: HaproxyHighHttp4xxErrorRate
 expr: sum(rate(haproxy_server_http_responses_total{code="4xx"}[1m])) by (server) / sum(rate(haproxy_server_http_responses_total{}[1m])) by (server) * 100 > 5
 for: 5m
 labels:
 severity: critical

 - alert: HaproxyHighHttp5xxErrorRate
 expr: sum(rate(haproxy_server_http_responses_total{code="5xx"}[1m])) by (server) / sum(rate(haproxy_server_http_responses_total{}[1m])) by (server) * 100 > 5
 for: 5m
 labels:
 severity: critical

 - alert: HaproxyBackendConnectionErrors
 expr: rate(haproxy_backend_connection_errors_total[1m]) * 100 > 5
 for: 5m
 labels:
 severity: critical

 - alert: HaproxyServerResponseErrors
 expr: rate(haproxy_server_response_errors_total[1m]) * 100 > 5
 for: 5m
 labels:
 severity: critical

 - alert: HaproxyServerConnectionErrors
 expr: rate(haproxy_server_connection_errors_total[1m]) * 100 > 5
 for: 5m
 labels:
 severity: critical

 - alert: HaproxyPendingRequests
 expr: haproxy_backend_current_queue > 0
 for: 5m
 labels:
 severity: warning

 - alert: HaproxyServerHealthcheckFailure
 expr: increase(haproxy_server_check_failures_total[1m]) > 0
 for: 5m
 labels:
 severity: warning

 - alert: HaproxyMaxConnectionsReached
 expr: (haproxy_process_max_connections - haproxy_process_current_connections) <= 0
 for: 5m
 labels:
 severity: critical

 - alert: BackendWithoutActiveServers
 expr: haproxy_backend_active_servers == 0
 for: 5m
 labels:
 severity: critical

 - alert: UnhealthyBackendStatus
 expr: haproxy_backend_status != 1
 for: 5m
 labels:
 severity: warning

 - alert: UnhealthyServerStatus
 expr: haproxy_server_status != 1
 for: 5m
 labels:
 severity: critical

 - alert: HaproxyFrontendSecurityBlockedRequests
 expr: rate(haproxy_frontend_requests_denied_total[1m]) > 10
 for: 5m
 labels:
 severity: warning

Recargamos la configuración:

docker stop pmm-server && docker start pmm-server

Si paramos el haproxy veremos la siguiente alarma:

Si hemos seguido la guía sobre Alertmanager: https://www.alfaexploit.com/readArticle/363 veremos en Telegram alertas como esta:

Si paramos un servidor web:

En Telegram:

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