PMM2: PHP-FPM exporter


Continuando con la instalación de php-fpm del artículo anterior vamos a configurar php-fpm-exporter, de este modo podremos monitorizar FPM, configurar alertas y visualizar gráficas de los datos obtenidos mediante Grafana.

 

En la web de Prometheus encontramos el exporter de bakins, este se encuentra alojado en GitHub, por ello compilamos e instalamos git para bajarnos el código:

emerge -av dev-vcs/git

Este está programado en Go, así que compilamos e instalamos Go:

emerge -av dev-lang/go

Clonamos el repositorio y compilamos el binario:

git clone https://github.com/bakins/php-fpm-exporter
cd php-fpm-exporter
./script/build

Comprobamos que haya compilado correctamente:

./php-fpm-exporter.linux.amd64 --help
usage: php-fpm-exporter.linux.amd64 [<flags>]

Flags:
  -h, --help                   Show context-sensitive help (also try --help-long and --help-man).
      --addr="127.0.0.1:8080"  listen address for metrics handler
      --endpoint="http://127.0.0.1:9000/status"  
                               url for php-fpm status
      --fastcgi=FASTCGI        fastcgi url. If this is set, fastcgi will be used instead of HTTP
      --web.telemetry-path="/metrics"  
                               Path under which to expose metrics. Cannot be /

Compilamos e instalamos php con soporte para FPM:

echo "dev-lang/php acl berkdb bzip2 cli ctype fileinfo filter flatfile gdbm iconv ipv6 json nls opcache phar posix readline session simplexml ssl tokenizer unicode xml zlib -apache2 -argon2 -bcmath -calendar -cdb -cgi -cjk -coverage -curl -debug -embed -enchant -exif -ffi -firebird fpm -ftp -gd -gmp -imap -inifile -intl -iodbc -kerberos -ldap -ldap-sasl -libedit -libressl -lmdb -mhash -mssql -mysql -mysqli -oci8-instant-client -odbc -pcntl -pdo -phpdbg -postgres -qdbm -selinux -session-mm -sharedmem -snmp -soap -sockets -sodium -spell -sqlite -systemd -sysvipc -test -threads -tidy -tokyocabinet -truetype -webp -xmlreader -xmlrpc -xmlwriter -xpm -xslt -zip" > /etc/portage/package.use/php
echo "app-eselect/eselect-php fpm" >> /etc/portage/package.use/php
emerge -av dev-lang/php

Habilitamos el status de FPM:

vi /etc/php/fpm-php7.4/fpm.d/www.conf
[www]
user = nobody
group = nobody
listen = /run/php-fpm.socket
pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
pm.status_path = /status
ping.path = /ping
ping.response = pong

Reiniciamos el servicio:

/etc/init.d/php-fpm restart

El estatus se puede consultar a través de un servidor web que nos reenvíe al status de php-fpm o directamente al php-fpm:

--endpoint string   url for php-fpm status (default "http://127.0.0.1:9000/status")
--fastcgi string    fastcgi url. If this is set, fastcgi will be used instead of HTTP

Lo mas sencillo es que el exporter acceda directamente al FPM, bindearlo a la loopback y configurar Nginx o el servidor que vayamos a utilizar para que pida credenciales de acceso:

./php-fpm-exporter.linux.amd64 --addr 127.0.0.1:8080 --fastcgi unix:///run/php-fpm.socket

NOTA: Otra opción sería insertar reglas de firewall para permitir solo la ip de PMM pero ya no podríamos consultar las las métricas directamente desde nuestro navegador, no al menos sin hacer algún tipo de túnel del estilo proxy socks.

Demonizamos el servicio:

vi /etc/local.d/php-fpm-exporter.start
nohup /root/php-fpm-exporter/php-fpm-exporter.linux.amd64 --addr 127.0.0.1:8080 --fastcgi unix:///run/php-fpm.socket &

Le asignamos los permisos necesarios:

chmod 700 /etc/local.d/php-fpm-exporter.start

Lo arrancamos:

/etc/local.d/php-fpm-exporter.start

Comprobamos que haya arrancado y que esté a la escucha:

netstat -nputa|grep LISTEN|grep 8080
tcp        0      0 127.0.0.1:8080          0.0.0.0:*               LISTEN      841/php-fpm-exporte 

Comprobamos que aparezcan las métricas consultándolas desde local:

curl http://localhost:8080/metrics|grep -v '#'
phpfpm_accepted_connections_total 6
phpfpm_active_max_processes 1
phpfpm_listen_queue_connections 0
phpfpm_listen_queue_length_connections 0
phpfpm_listen_queue_max_connections 0
phpfpm_max_children_reached_total 0
phpfpm_processes_total{state="active"} 1
phpfpm_processes_total{state="idle"} 1
phpfpm_scrape_failures_total 0
phpfpm_slow_requests_total 0
phpfpm_up 1

Compilamos e instalamos el servidor web, en mi caso Nginx:

emerge -av www-servers/nginx

Ahora configuraremos Nginx para que sirva las métricas al exterior pero requiriendo autenticación previa, para ello modificamos el bloque server de la configuración:

vi /etc/nginx/nginx.conf
...
server {
    listen SERVER_IP:8080;
    server_name _;

    location / {
        auth_basic "Restricted Content";
        auth_basic_user_file /etc/nginx/.htpasswd;
        proxy_pass http://localhost:8080;
    }
}
...

Reiniciamos el servicio para aplicar la configuración:

/etc/init.d/nginx restart

Generamos el fichero de passwords:

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

La configuración de Prometheus quedaría así.

vi prometheusConf/prometheus.base.yml
scrape_configs:
- job_name: fpm-status
  scrape_interval: 1m
  scrape_timeout: 10s
  metrics_path: /metrics
  scheme: http
  static_configs:
  - targets:
    - SERVER:8080
  basic_auth:
    username: admin
    password: PASSWORD

Aplicamos la configuración nueva reiniciando PMM:

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

Accedemos desde el exterior con las credenciales:

curl -u admin:PASSWORD http://SERVER_IP:8080/metrics|grep -v '#'

En Prometheus ya podremos ver el target:

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

- name: fpmRules
  rules:
  - alert: fpmExporterDown
    expr: up{job="fpm-status"} == 0
    for: 5m
    labels:
      severity: critical

  - alert: fpmDown
    expr: phpfpm_up == 0
    for: 5m
    labels:
      severity: critical

  - alert: fpmMaxChildrenReached
    expr: phpfpm_max_children_reached_total{job="fpm-status"} == 1
    for: 5m
    labels:
      severity: critical

Si paramos el FPM en el servidor veremos la siguiente alarma:



Ahora cargamos la Dashboard de Grafana:

https://grafana.com/grafana/dashboards/3901

Pegamos la url del dashboard e importamos:

Y el resultado es el siguiente:

Si te ha gustado el artículo puedes invitarme a un redbull aquí.
Si tienes cualquier pregunta siempre puedes enviarme un Email o escribir en el grupo de Telegram de AlfaExploit.
Autor: kr0m -- 11/09/2020 00:48:49 -- Categoria: Http Monitoring