refactor(nut): merge prometheus exporter into nut role
- exporter gated by nut_prometheus_exporter_enabled - env-file config (correct NUT_EXPORTER_* vars + --web.listen-address) - remove standalone nut_exporter role
This commit is contained in:
+24
-3
@@ -82,7 +82,28 @@ journalctl -u nut-monitor -u nut-server -u 'nut-driver@*' -f
|
|||||||
- udev rules shipped by the `nut` package grant USB device access to the `nut`
|
- udev rules shipped by the `nut` package grant USB device access to the `nut`
|
||||||
group only.
|
group only.
|
||||||
|
|
||||||
## Companion role
|
## Prometheus exporter
|
||||||
|
|
||||||
See [`nut_exporter`](../nut_exporter/README.md) to expose Prometheus metrics
|
Optionally exposes UPS metrics for Prometheus via `prometheus-nut-exporter`
|
||||||
based on the same upsd instance.
|
(AUR, Arch-only). Enable it:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
nut_prometheus_exporter_enabled: true
|
||||||
|
```
|
||||||
|
|
||||||
|
The exporter reuses `nut_monitor_password`, binds to
|
||||||
|
`{{ nut_prometheus_exporter_listen_address }}` (default `127.0.0.1:9199`) and
|
||||||
|
serves UPS metrics on `/ups_metrics`. Pair it with a Prometheus scrape job:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
prometheus_scrape_configs:
|
||||||
|
- job_name: 'nut'
|
||||||
|
metrics_path: /ups_metrics
|
||||||
|
static_configs:
|
||||||
|
- targets: ['127.0.0.1:9199']
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
systemctl status prometheus-nut-exporter
|
||||||
|
curl -s 'http://127.0.0.1:9199/ups_metrics' | head
|
||||||
|
```
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
# UPS definition
|
# UPS definition
|
||||||
# --------------
|
# --------------
|
||||||
# Logical name of the UPS as referenced everywhere (ups.conf section, upsmon
|
# Logical name of the UPS as referenced everywhere (ups.conf section, upsmon
|
||||||
# MONITOR line, nut_exporter ?ups= query parameter).
|
# MONITOR line, exporter ?ups= query parameter).
|
||||||
nut_ups_name: eaton
|
nut_ups_name: eaton
|
||||||
|
|
||||||
# Human-readable description (shown in upsc output).
|
# Human-readable description (shown in upsc output).
|
||||||
@@ -33,7 +33,7 @@ nut_ups_maxretry: 3
|
|||||||
nut_upsd_listen:
|
nut_upsd_listen:
|
||||||
- { addr: "127.0.0.1", port: 3493 }
|
- { addr: "127.0.0.1", port: 3493 }
|
||||||
|
|
||||||
# Local monitor user used by upsmon and nut_exporter. Password must be set.
|
# Local monitor user used by upsmon and the Prometheus exporter. Password must be set.
|
||||||
nut_monitor_user: monitor
|
nut_monitor_user: monitor
|
||||||
# nut_monitor_password: "" # Intentionally undefined - role will fail if not set
|
# nut_monitor_password: "" # Intentionally undefined - role will fail if not set
|
||||||
|
|
||||||
@@ -66,3 +66,10 @@ nut_notify_script_path: /usr/local/bin/ups-notify
|
|||||||
# ONLINE notification can report total outage duration. Lives under /run so it
|
# ONLINE notification can report total outage duration. Lives under /run so it
|
||||||
# is cleared on reboot (stale outage state is meaningless after a reboot).
|
# is cleared on reboot (stale outage state is meaningless after a reboot).
|
||||||
nut_outage_state_file: /run/ups-notify-outage
|
nut_outage_state_file: /run/ups-notify-outage
|
||||||
|
|
||||||
|
# Prometheus exporter (optional)
|
||||||
|
# ------------------------------
|
||||||
|
nut_prometheus_exporter_enabled: false
|
||||||
|
nut_prometheus_exporter_listen_address: "127.0.0.1:9199"
|
||||||
|
nut_prometheus_exporter_nut_server: "127.0.0.1:3493"
|
||||||
|
nut_prometheus_exporter_nut_user: "{{ nut_monitor_user }}"
|
||||||
|
|||||||
@@ -13,3 +13,12 @@
|
|||||||
ansible.builtin.systemd:
|
ansible.builtin.systemd:
|
||||||
name: nut-monitor.service
|
name: nut-monitor.service
|
||||||
state: restarted
|
state: restarted
|
||||||
|
|
||||||
|
- name: Reload systemd
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
daemon_reload: true
|
||||||
|
|
||||||
|
- name: Restart NUT exporter
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: "{{ nut_prometheus_exporter_service }}"
|
||||||
|
state: restarted
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
---
|
||||||
|
# Prometheus NUT exporter (optional, gated by nut_prometheus_exporter_enabled).
|
||||||
|
# Installs prometheus-nut-exporter (AUR) and points it at the local upsd via
|
||||||
|
# the unit's EnvironmentFile (/etc/conf.d/prometheus-nut-exporter).
|
||||||
|
|
||||||
|
- name: Install prometheus-nut-exporter (AUR via paru)
|
||||||
|
ansible.builtin.command: "paru -S --noconfirm --needed {{ nut_prometheus_exporter_package }}"
|
||||||
|
register: _nut_prometheus_exporter_install
|
||||||
|
changed_when: "'there is nothing to do' not in _nut_prometheus_exporter_install.stdout | lower"
|
||||||
|
when: ansible_facts['os_family'] == 'Archlinux'
|
||||||
|
|
||||||
|
- name: Remove legacy exporter systemd override
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "/etc/systemd/system/{{ nut_prometheus_exporter_service }}.service.d"
|
||||||
|
state: absent
|
||||||
|
notify: Reload systemd
|
||||||
|
|
||||||
|
- name: Deploy exporter environment file
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: nut-exporter-env.conf.j2
|
||||||
|
dest: "{{ nut_prometheus_exporter_env_file }}"
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: "0600"
|
||||||
|
notify: Restart NUT exporter
|
||||||
|
|
||||||
|
- name: Enable and start exporter
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: "{{ nut_prometheus_exporter_service }}"
|
||||||
|
enabled: true
|
||||||
|
state: started
|
||||||
|
daemon_reload: true
|
||||||
@@ -95,3 +95,7 @@
|
|||||||
enabled: true
|
enabled: true
|
||||||
state: started
|
state: started
|
||||||
loop: "{{ nut_services }}"
|
loop: "{{ nut_services }}"
|
||||||
|
|
||||||
|
- name: Deploy Prometheus NUT exporter
|
||||||
|
ansible.builtin.include_tasks: exporter.yml
|
||||||
|
when: nut_prometheus_exporter_enabled | bool
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
# Managed by Ansible - DO NOT EDIT MANUALLY
|
||||||
|
# EnvironmentFile for prometheus-nut-exporter (read by the systemd unit via
|
||||||
|
# $NUT_EXPORTER_ARGS). The password has no flag, so it is passed as an env var.
|
||||||
|
NUT_EXPORTER_ARGS="--web.listen-address={{ nut_prometheus_exporter_listen_address }} --nut.server={{ nut_prometheus_exporter_nut_server.split(':')[0] }} --nut.serverport={{ nut_prometheus_exporter_nut_server.split(':')[1] }} --nut.username={{ nut_prometheus_exporter_nut_user }}"
|
||||||
|
NUT_EXPORTER_PASSWORD="{{ nut_monitor_password }}"
|
||||||
@@ -7,3 +7,8 @@ nut_services:
|
|||||||
- nut-driver-enumerator.service
|
- nut-driver-enumerator.service
|
||||||
- nut-server.service
|
- nut-server.service
|
||||||
- nut-monitor.service
|
- nut-monitor.service
|
||||||
|
|
||||||
|
# Prometheus exporter (AUR)
|
||||||
|
nut_prometheus_exporter_package: prometheus-nut-exporter
|
||||||
|
nut_prometheus_exporter_service: prometheus-nut-exporter
|
||||||
|
nut_prometheus_exporter_env_file: /etc/conf.d/prometheus-nut-exporter
|
||||||
|
|||||||
@@ -1,60 +0,0 @@
|
|||||||
# nut_exporter — Prometheus exporter for NUT
|
|
||||||
|
|
||||||
Scrapes a local `upsd` and exposes UPS metrics for Prometheus.
|
|
||||||
|
|
||||||
## Supported distributions
|
|
||||||
|
|
||||||
- Arch Linux (AUR package `prometheus-nut-exporter`, installed via `paru`)
|
|
||||||
|
|
||||||
Debian/Ubuntu is not packaged upstream — add it on demand.
|
|
||||||
|
|
||||||
## Configuration
|
|
||||||
|
|
||||||
See [defaults/main.yml](defaults/main.yml).
|
|
||||||
|
|
||||||
Required:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
nut_exporter_nut_password: "<same as nut_monitor_password>"
|
|
||||||
```
|
|
||||||
|
|
||||||
Optional:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
nut_exporter_listen_address: "127.0.0.1:9199"
|
|
||||||
nut_exporter_nut_server: "127.0.0.1:3493"
|
|
||||||
nut_exporter_nut_user: monitor
|
|
||||||
```
|
|
||||||
|
|
||||||
## Pairing with Prometheus
|
|
||||||
|
|
||||||
Typical scrape config (target uses the multi-target pattern: the exporter
|
|
||||||
queries a remote upsd specified in the URL parameters):
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
prometheus_scrape_configs:
|
|
||||||
- job_name: 'nut'
|
|
||||||
metrics_path: /nut
|
|
||||||
static_configs:
|
|
||||||
- targets: ['eaton@localhost'] # ups@host syntax
|
|
||||||
relabel_configs:
|
|
||||||
- source_labels: [__address__]
|
|
||||||
target_label: __param_target
|
|
||||||
- source_labels: [__param_target]
|
|
||||||
target_label: instance
|
|
||||||
- target_label: __address__
|
|
||||||
replacement: 127.0.0.1:9199
|
|
||||||
```
|
|
||||||
|
|
||||||
## Operations
|
|
||||||
|
|
||||||
```bash
|
|
||||||
systemctl status prometheus-nut-exporter
|
|
||||||
curl -s 'http://127.0.0.1:9199/nut?target=localhost&ups=eaton' | head
|
|
||||||
journalctl -u prometheus-nut-exporter -f
|
|
||||||
```
|
|
||||||
|
|
||||||
## Dependencies
|
|
||||||
|
|
||||||
Requires the [`nut`](../nut/README.md) role (or any other running upsd) on the
|
|
||||||
same host.
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
---
|
|
||||||
# Prometheus NUT exporter configuration
|
|
||||||
|
|
||||||
# Address the exporter listens on.
|
|
||||||
nut_exporter_listen_address: "127.0.0.1:9199"
|
|
||||||
|
|
||||||
# upsd server to connect to (kept local — exporter sits next to upsd).
|
|
||||||
nut_exporter_nut_server: "127.0.0.1:3493"
|
|
||||||
|
|
||||||
# Credentials used to log into upsd. These should match the upsd user defined
|
|
||||||
# by the nut role (nut_monitor_user / nut_monitor_password).
|
|
||||||
nut_exporter_nut_user: "{{ nut_monitor_user | default('monitor') }}"
|
|
||||||
# nut_exporter_nut_password: "" # Inherits nut_monitor_password by default
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
---
|
|
||||||
- name: Reload systemd
|
|
||||||
ansible.builtin.systemd:
|
|
||||||
daemon_reload: true
|
|
||||||
|
|
||||||
- name: Restart nut_exporter
|
|
||||||
ansible.builtin.systemd:
|
|
||||||
name: "{{ nut_exporter_service }}"
|
|
||||||
state: restarted
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
---
|
|
||||||
dependencies: []
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
---
|
|
||||||
- name: Validate required configuration
|
|
||||||
ansible.builtin.assert:
|
|
||||||
that:
|
|
||||||
- nut_exporter_nut_password is defined
|
|
||||||
- nut_exporter_nut_password | length >= 12
|
|
||||||
fail_msg: |
|
|
||||||
nut_exporter_nut_password (>=12 chars) is required.
|
|
||||||
Usually set to the same value as nut_monitor_password.
|
|
||||||
|
|
||||||
- name: Load OS-specific variables
|
|
||||||
ansible.builtin.include_vars: "{{ item }}"
|
|
||||||
with_first_found:
|
|
||||||
- "{{ ansible_facts['os_family'] }}.yml"
|
|
||||||
|
|
||||||
- name: Install prometheus-nut-exporter (AUR via paru)
|
|
||||||
ansible.builtin.command: "paru -S --noconfirm --needed {{ nut_exporter_package }}"
|
|
||||||
register: nut_exporter_install
|
|
||||||
changed_when: "'there is nothing to do' not in nut_exporter_install.stdout | lower"
|
|
||||||
when: ansible_facts['os_family'] == 'Archlinux'
|
|
||||||
|
|
||||||
- name: Ensure systemd override directory exists
|
|
||||||
ansible.builtin.file:
|
|
||||||
path: "{{ nut_exporter_override_dir }}"
|
|
||||||
state: directory
|
|
||||||
owner: root
|
|
||||||
group: root
|
|
||||||
mode: "0755"
|
|
||||||
|
|
||||||
- name: Deploy systemd override (listen address + upsd credentials)
|
|
||||||
ansible.builtin.template:
|
|
||||||
src: override.conf.j2
|
|
||||||
dest: "{{ nut_exporter_override_dir }}/override.conf"
|
|
||||||
owner: root
|
|
||||||
group: root
|
|
||||||
mode: "0640"
|
|
||||||
notify:
|
|
||||||
- Reload systemd
|
|
||||||
- Restart nut_exporter
|
|
||||||
|
|
||||||
- name: Enable and start nut_exporter
|
|
||||||
ansible.builtin.systemd:
|
|
||||||
name: "{{ nut_exporter_service }}"
|
|
||||||
enabled: true
|
|
||||||
state: started
|
|
||||||
daemon_reload: true
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
# Managed by Ansible - DO NOT EDIT MANUALLY
|
|
||||||
# Override for prometheus-nut-exporter to inject listen address and upsd
|
|
||||||
# credentials. The exporter reads NUT_EXPORTER_* env vars at startup.
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Environment="HTTP_LISTEN_ADDRESS={{ nut_exporter_listen_address }}"
|
|
||||||
Environment="NUT_EXPORTER_SERVER={{ nut_exporter_nut_server.split(':')[0] }}"
|
|
||||||
Environment="NUT_EXPORTER_PORT={{ nut_exporter_nut_server.split(':')[1] }}"
|
|
||||||
Environment="NUT_EXPORTER_USERNAME={{ nut_exporter_nut_user }}"
|
|
||||||
Environment="NUT_EXPORTER_PASSWORD={{ nut_exporter_nut_password }}"
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
---
|
|
||||||
nut_exporter_package: prometheus-nut-exporter
|
|
||||||
nut_exporter_service: prometheus-nut-exporter.service
|
|
||||||
nut_exporter_user: nut-exporter
|
|
||||||
nut_exporter_group: nut-exporter
|
|
||||||
nut_exporter_override_dir: /etc/systemd/system/prometheus-nut-exporter.service.d
|
|
||||||
Reference in New Issue
Block a user