feat(monitoring): add nginx, postgres, valkey prometheus exporters

- nginx: nginx-prometheus-exporter gated by nginx_exporter_enabled,
  deploys loopback-only stub_status (8090), exporter on 9113
- postgres: postgres_exporter gated by postgres_exporter_enabled,
  creates postgres_exporter role with pg_monitor, exporter on 9187
- valkey: redis_exporter gated by valkey_exporter_enabled, adds
  read-only ACL user to users.acl, exporter on 9121

Each exporter follows the nut pattern (tasks/exporter.yml included from
main.yml, OS vars, 0600 secret env files, password asserts).
This commit is contained in:
Clément Désiles
2026-09-06 09:37:36 +02:00
parent 6f1f7f88f0
commit aa78e238aa
26 changed files with 304 additions and 0 deletions
+21
View File
@@ -85,6 +85,27 @@ sudo -u postgres psql -c "SHOW shared_buffers;"
sudo -u postgres psql -c "SHOW effective_cache_size;"
```
## Prometheus exporter
Optionally exposes PostgreSQL metrics (connections, cache hit ratio, deadlocks)
via `postgres_exporter`. Enable it:
```yaml
postgres_exporter_enabled: true
postgres_exporter_password: "<min 12 chars>" # keep URL-safe
```
The role creates a `postgres_exporter` monitoring role with the built-in
`pg_monitor` role (no superuser). The exporter binds to `127.0.0.1:9187`;
pair it with a scrape job:
```yaml
prometheus_scrape_configs:
- job_name: 'postgres'
static_configs:
- targets: ['127.0.0.1:9187']
```
## References
- [PostgreSQL Documentation](https://www.postgresql.org/docs/current/)
+10
View File
@@ -49,3 +49,13 @@ postgres_log_truncate_on_rotation: "off" # Overwrite old log files with same nam
postgres_logrotate_rotate: 14 # Keep 14 days of logs
postgres_logrotate_frequency: daily # daily|weekly|monthly
postgres_logrotate_compress: true # Compress rotated logs
# Prometheus exporter (optional, via postgres_exporter)
# Creates its own minimal monitoring role (pg_monitor, no superuser).
postgres_exporter_enabled: false
postgres_exporter_listen_address: "127.0.0.1:9187"
postgres_exporter_user: postgres_exporter
# postgres_exporter_password: "" # Intentionally undefined - required when enabled
postgres_exporter_pg_host: "127.0.0.1"
postgres_exporter_pg_port: "{{ postgres_port }}"
postgres_exporter_pg_dbname: postgres
+5
View File
@@ -8,3 +8,8 @@
ansible.builtin.systemd:
name: "{{ postgres_service_name }}"
state: reloaded
- name: Restart postgres exporter
ansible.builtin.systemd:
name: "{{ postgres_exporter_service }}"
state: restarted
+54
View File
@@ -0,0 +1,54 @@
---
# Prometheus postgres exporter (optional, gated by postgres_exporter_enabled).
# Creates a minimal monitoring role (pg_monitor) and runs postgres_exporter
# against the local instance.
- name: Validate exporter password is set
ansible.builtin.assert:
that:
- postgres_exporter_password is defined
- postgres_exporter_password | length >= 12
fail_msg: |
postgres_exporter_password is required (min 12 chars) when
postgres_exporter_enabled is true.
See roles/postgres/defaults/main.yml for configuration instructions.
success_msg: "Exporter password validation passed"
- name: Install postgres_exporter
ansible.builtin.package:
name: "{{ postgres_exporter_package }}"
state: present
- name: Create postgres_exporter monitoring role
community.postgresql.postgresql_user:
name: "{{ postgres_exporter_user }}"
password: "{{ postgres_exporter_password }}"
role_attr_flags: NOSUPERUSER,NOCREATEDB,NOCREATEROLE
state: present
become: false
become_user: "{{ postgres_admin_user }}"
- name: Grant pg_monitor to postgres_exporter
community.postgresql.postgresql_membership:
group: pg_monitor
target_roles:
- "{{ postgres_exporter_user }}"
state: present
become: false
become_user: "{{ postgres_admin_user }}"
- name: Deploy exporter environment file
ansible.builtin.template:
src: exporter-env.conf.j2
dest: "{{ postgres_exporter_args_file }}"
owner: root
group: root
mode: "0600"
notify: Restart postgres exporter
- name: Enable and start postgres exporter
ansible.builtin.systemd:
name: "{{ postgres_exporter_service }}"
enabled: true
state: started
daemon_reload: true
+4
View File
@@ -99,3 +99,7 @@
state: present
become: false
become_user: "{{ postgres_admin_user }}"
- name: Deploy Prometheus postgres exporter
ansible.builtin.include_tasks: exporter.yml
when: postgres_exporter_enabled | bool
@@ -0,0 +1,3 @@
# Managed by Ansible - DO NOT EDIT MANUALLY
{{ postgres_exporter_args_var }}="--web.listen-address={{ postgres_exporter_listen_address }}"
DATA_SOURCE_NAME="postgresql://{{ postgres_exporter_user }}:{{ postgres_exporter_password }}@{{ postgres_exporter_pg_host }}:{{ postgres_exporter_pg_port }}/{{ postgres_exporter_pg_dbname }}?sslmode=disable"
+6
View File
@@ -11,3 +11,9 @@ postgres_service_name: postgresql
postgres_config_path: "{{ postgres_data_dir }}/postgresql.conf"
postgres_config_dir: "{{ postgres_data_dir }}/conf.d"
postgres_hba_path: "{{ postgres_data_dir }}/pg_hba.conf"
# Prometheus exporter
postgres_exporter_package: prometheus-postgres-exporter
postgres_exporter_service: prometheus-postgres-exporter
postgres_exporter_args_file: /etc/conf.d/prometheus-postgres-exporter
postgres_exporter_args_var: POSTGRES_EXPORTER_ARGS
+6
View File
@@ -8,3 +8,9 @@ postgres_service_name: postgresql
postgres_config_path: /etc/postgresql/current/main/postgresql.conf
postgres_config_dir: /etc/postgresql/current/main/conf.d
postgres_hba_path: /etc/postgresql/current/main/pg_hba.conf
# Prometheus exporter
postgres_exporter_package: prometheus-postgres-exporter
postgres_exporter_service: prometheus-postgres-exporter
postgres_exporter_args_file: /etc/default/prometheus-postgres-exporter
postgres_exporter_args_var: ARGS