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 exporter puede consultar el status de FPM a través de un servidor web que nos reenvie al FPM o directamente al 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 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, whitelisteamos la ip del PMM para que no pida password desde esa dirección ip:
vi /etc/nginx/nginx.conf
...
server {
listen SERVER_IP:8080;
server_name _;
location / {
satisfy any;
allow PMM_SERVER_IP/32;
auth_basic "Restricted Content";
auth_basic_user_file /etc/nginx/.htpasswd;
deny all;
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
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:
Si hemos seguido la guía sobre Alertmanager: https://www.alfaexploit.com/readArticle/363 veremos en Telegram alertas como esta:
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í.