PMM2: Haproxy exporter


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

Para ello le damos a import:

Pegamos el id de la dashboard:

Ya podemos visualizar las gráficas:

NOTA: La dashboard está bugeada tendremos que modificar la query de uptime para que quede del siguiente modo:

time() - haproxy_process_start_time_seconds{instance=~"$host:$port",job="haproxy"}

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í.
Autor: kr0m -- 31/05/2020 02:26:56