Prometheus: мониторинг PHP-FPM + Ansible роль

By | 06/08/2018
 

Задача – собирать метрики с PHP-FPM /status.

Используем lusotycoon/phpfpm-exporter.

Кроме этого экспортёра есть bakins/php-fpm-exporter – но контейнер из его Docker образа постоянно возвращает “Empty reply from server“.

Есть peakgames/php-fpm-prometheus – но для него нет Docker образа, а собирать свой не хочется.

Имеется также hipages/php-fpm_exporter – но с ним возникли ошибки вида “Error scraping PHP-FPM: invalid character ‘A’ looking for beginning of value“.

lusotycoon/phpfpm-exporter удобен тем, что:

  • он запустился без ошибок 🙂
  • умеет собирать метрики с пулов через unix-сокеты, при этом достаточно просто указать директорию с сокетами.

PFP-FPM status

Для сбора статистики – пулы должны быть сконфигурированы с поддержкой /status, например:

[dev.domain.com]

listen = /var/run/php/php-fpm-dev.domain.com.sock
listen.owner = www-data
listen.group = www-data

user = username
group = groupname

pm = static
pm.max_children = 1
pm.max_requests = 200

;pm = dynamic
;pm.max_children = 300
;pm.min_spare_servers = 64
;pm.start_servers = 128
;pm.max_spare_servers = 128
;pm.process_idle_timeout = 10s
;pm.max_requests = 200

pm.status_path = /status

request_slowlog_timeout = 30s
slowlog = /var/log/php-dev.domain.com-slow.log

php_admin_value[error_log] = /var/log/fpm-php-dev.domain.com.log
php_admin_flag[log_errors] = on

PHP-FPM експортер

Создаём Compose файл:

version: "3.3"
services:
  php-fpm-exporter:
    image: lusotycoon/phpfpm-exporter
    command: "--phpfpm.socket-directories /var/run/php/"
    environment:
      - PHP_FPM_SCRAPE_URI="unix:///var/run/php-fpm-dev.domain.com.sock"
    volumes:
      - "/var/run/php:/var/run/php"
    ports: 
      - 9253:9253

Запускаем сервис:

root@bm-backed-app-dev:/home/admin# docker-compose -f php-fpm-exporter.yml up
Starting admin_php-fpm-exporter_1 ... done
Attaching to admin_php-fpm-exporter_1
php-fpm-exporter_1  | 2018/06/07 11:55:31 Starting phpfpm_exporter (version=0.3.0, branch=HEAD, revision=2cd2fd5e8c888c242cdb844f7f36a6e3ed297ea9)
php-fpm-exporter_1  | 2018/06/07 11:55:31 Build context (go=go1.10, user=root@9cf351de7094, date=20180228-18:53:21)
php-fpm-exporter_1  | 2018/06/07 11:55:31 Starting Server: :9253
...

Проверяем:

root@bm-backed-app-dev:/home/admin# curl -s localhost:9253/metrics | grep -v \#| grep fpm | head -n5
php_fpm_accepted_connections_total{socket_path="/var/run/php/php-fpm-dev-domain-meditation.com.sock"} 2
php_fpm_accepted_connections_total{socket_path="/var/run/php/php-fpm-dev.admin.domain-meditation.com.sock"} 2
php_fpm_accepted_connections_total{socket_path="/var/run/php/php-fpm-dev.admin.domain.com.sock"} 2
php_fpm_accepted_connections_total{socket_path="/var/run/php/php-fpm-dev.domain.com.sock"} 2
php_fpm_active_processes{socket_path="/var/run/php/php-fpm-dev-domain-meditation.com.sock"} 1

В каждой метрике имеется лейбл “socket_path“, по которому потом в Prometheus/Grafana можно будет легко определить пул.

Ansible роль

Создаём каталоги:

mkdir -p roles/php-fpm-exporter/{tasks,files,defaults}

Создаём файл roles/php-fpm-exporter/tasks/main.yml, описываем создание каталога, копирвоание Compose файла и запуск сервиса:

- name: Create {{ exporter_opt_path }} directory
  file:
    path: "{{ exporter_opt_path }}"
    state: directory
    mode: 0755

- name: Copy Docker Compose file
  copy:
    src: "files/{{ exporter_compose_file }}"
    dest: "{{ exporter_opt_path }}"

- name: Start Prometheus PHP-FPM exporter
  docker_service:
    project_src: "{{ exporter_opt_path }}"
    files: "{{ exporter_compose_file }}"

Создаём файл roles/php-fpm-exporter/files/php-fpm-exporter.yml, аналогичный тому, с которым тестили выше, толкьо передаём --phpfpm.socket-directories вместо одного сокета:

version: "3.3"
services:
  php-fpm-exporter:
    image: lusotycoon/phpfpm-exporter
    command: "--phpfpm.socket-directories /var/run/php/"
    volumes:
      - "/var/run/php:/var/run/php"
    ports:
      - 9253:9253

И файл roles/php-fpm-exporter/defaults/main.yml с дефолтными переменными:

exporter_opt_path: /opt/php-fpm-exporter
exporter_compose_file: php-fpm-exporter.yml

Запускаем ansibe-playbook:

./ansible_exec.sh -a -S
Tags: app
Env: backend-dev
Vault: /home/setevoy/.ssh/backend_aws_credentials.yml
RSA: /home/setevoy/Work/aws-credentials/bm-backend-dev.pem
Are you sure to proceed? [y/n] y
Installing dependencies...
[WARNING]: - manala.logrotate (1.0.1) is already installed - use --force to change version to unspecified
[WARNING]: - jnv.unattended-upgrades (v1.6.0) is already installed - use --force to change version to unspecified
Done.
Executing syntax-check...
playbook: backend.yml
Syntax check passed.
Skipping dry-run.
Applying roles...
PLAY [all] ****
TASK [Gathering Facts] ****
ok: [bm-mb-dev-ssh.domain.world]
...
TASK [php-fpm-exporter : Create /opt/php-fpm-exporter directory] ****
ok: [bm-mb-dev-ssh.domain.world]
TASK [php-fpm-exporter : Copy Docker Compose file] ****
ok: [bm-mb-dev-ssh.domain.world]
TASK [php-fpm-exporter : Start Prometheus PHP-FPM exporter] ****
changed: [bm-mb-dev-ssh.domain.world]
PLAY RECAP ****
bm-mb-dev-ssh.domain.world : ok=17   changed=4    unreachable=0    failed=0
Provisioning done.

На хосте проверяем:

root@bm-backed-app-dev:/home/admin# curl -s localhost:9253/metrics | grep -v \#| grep fpm | head -n5
php_fpm_accepted_connections_total{socket_path="/var/run/php/php-fpm-dev-domain-meditation.com.sock"} 3
php_fpm_accepted_connections_total{socket_path="/var/run/php/php-fpm-dev.admin.domain-meditation.com.sock"} 3
php_fpm_accepted_connections_total{socket_path="/var/run/php/php-fpm-dev.admin.domain.com.sock"} 3
php_fpm_accepted_connections_total{socket_path="/var/run/php/php-fpm-dev.domain.com.sock"} 3
php_fpm_active_processes{socket_path="/var/run/php/php-fpm-dev-domain-meditation.com.sock"} 1

Готово.