feat(unbound): add prometheus exporter, dashboard, fix socket buffer sysctl
This commit is contained in:
@@ -1,3 +1,28 @@
|
||||
# Metrics (Prometheus)
|
||||
|
||||
Set `unbound_exporter_enabled: true` in inventory/host_vars. This enables
|
||||
`remote-control` (no TLS, loopback only) and deploys `prometheus-unbound-exporter`
|
||||
(Arch Linux only), which scrapes `unbound-control stats_noreset` on
|
||||
`127.0.0.1:9167`.
|
||||
|
||||
Verify:
|
||||
|
||||
```sh
|
||||
curl -s 127.0.0.1:9167/metrics | grep '^unbound_up'
|
||||
```
|
||||
|
||||
Add a scrape job in `prometheus_scrape_configs`:
|
||||
|
||||
```yaml
|
||||
- job_name: 'unbound'
|
||||
static_configs:
|
||||
- targets: ['localhost:9167']
|
||||
```
|
||||
|
||||
Key QoS metrics: cache hit ratio (`unbound_cache_hit_rate` or
|
||||
`num.cachehits`/`num.cachemiss`), recursion latency (`num.query.time.avg/median`),
|
||||
requestlist backlog, and `num.answer.rcode.SERVFAIL` failure rate.
|
||||
|
||||
# Testing
|
||||
|
||||
## DNS leaks
|
||||
|
||||
@@ -25,3 +25,9 @@ unbound_firewall_allowed_sources:
|
||||
unbound_custom_lan_records:
|
||||
"example.lan":
|
||||
v4: 192.168.1.2
|
||||
|
||||
# Prometheus exporter (optional, via prometheus-unbound-exporter).
|
||||
# Scrapes unbound-control stats_noreset over the local control interface.
|
||||
# Arch Linux only — the exporter is not packaged in Debian/Ubuntu.
|
||||
unbound_exporter_enabled: false
|
||||
unbound_exporter_listen_address: "127.0.0.1:9167"
|
||||
|
||||
@@ -14,3 +14,8 @@
|
||||
- name: Reload AppArmor profile
|
||||
ansible.builtin.command: apparmor_parser -r {{ unbound_apparmor_profile_path }}
|
||||
when: ansible_facts.apparmor.status == "enabled"
|
||||
|
||||
- name: Restart unbound exporter
|
||||
ansible.builtin.systemd:
|
||||
name: "{{ unbound_exporter_service }}"
|
||||
state: restarted
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
---
|
||||
# Prometheus unbound exporter (optional, gated by unbound_exporter_enabled).
|
||||
# Scrapes unbound-control stats_noreset over the local control interface.
|
||||
|
||||
- name: Assert exporter is supported (Arch Linux only)
|
||||
ansible.builtin.assert:
|
||||
that: ansible_facts['os_family'] == 'Archlinux'
|
||||
fail_msg: |
|
||||
The unbound exporter (prometheus-unbound-exporter) is only packaged for
|
||||
Arch Linux. It is not available in Debian/Ubuntu repositories.
|
||||
success_msg: "Unbound exporter supported"
|
||||
|
||||
- name: Load OS-specific exporter variables
|
||||
ansible.builtin.include_vars: archlinux.yml
|
||||
|
||||
- name: Install prometheus-unbound-exporter
|
||||
ansible.builtin.package:
|
||||
name: "{{ unbound_exporter_package }}"
|
||||
state: present
|
||||
|
||||
- name: Deploy exporter environment file
|
||||
ansible.builtin.template:
|
||||
src: exporter-env.conf.j2
|
||||
dest: "{{ unbound_exporter_args_file }}"
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0644"
|
||||
notify: Restart unbound exporter
|
||||
|
||||
- name: Enable and start prometheus-unbound-exporter
|
||||
ansible.builtin.systemd:
|
||||
name: "{{ unbound_exporter_service }}"
|
||||
enabled: true
|
||||
state: started
|
||||
daemon_reload: true
|
||||
@@ -137,13 +137,20 @@
|
||||
group: root
|
||||
mode: "0644"
|
||||
|
||||
# Match so-rcvbuf/so-sndbuf (4m) in unbound.conf. rmem_max was 1 MiB and
|
||||
# wmem_max was left at its ~208 KiB default, silently capping unbound's
|
||||
# requested 4 MiB buffers (the kernel halves SO_RCVBUF/SO_SNDBUF requests
|
||||
# against these sysctls before doubling them).
|
||||
- name: Configure sysctl for unbound socket buffers
|
||||
ansible.posix.sysctl:
|
||||
name: net.core.rmem_max
|
||||
value: "1048576"
|
||||
name: "{{ item.name }}"
|
||||
value: "{{ item.value }}"
|
||||
state: present
|
||||
sysctl_set: true
|
||||
reload: true
|
||||
loop:
|
||||
- { name: net.core.rmem_max, value: "4194304" }
|
||||
- { name: net.core.wmem_max, value: "4194304" }
|
||||
|
||||
- name: Install unbound config
|
||||
ansible.builtin.template:
|
||||
@@ -184,3 +191,7 @@
|
||||
delay: 2
|
||||
register: ufw_result
|
||||
until: ufw_result is succeeded
|
||||
|
||||
- name: Deploy Prometheus unbound exporter
|
||||
ansible.builtin.include_tasks: exporter.yml
|
||||
when: unbound_exporter_enabled | bool
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
# Managed by Ansible - DO NOT EDIT MANUALLY
|
||||
# Empty cert flags (-unbound.ca= etc.) make the exporter speak plain-text to
|
||||
# unbound's control interface (control-use-cert: no).
|
||||
{{ unbound_exporter_args_var }}="-web.listen-address={{ unbound_exporter_listen_address }} -unbound.ca= -unbound.cert= -unbound.key= -unbound.host tcp://127.0.0.1:8953"
|
||||
@@ -130,5 +130,18 @@ server:
|
||||
# Enable DNSSEC
|
||||
auto-trust-anchor-file: "{{ unbound_anchor_root_key }}"
|
||||
|
||||
# Statistics for monitoring (unbound-control stats / prometheus exporter)
|
||||
statistics-interval: 0
|
||||
statistics-cumulative: yes
|
||||
extended-statistics: yes
|
||||
|
||||
# Remote control for unbound-control and the prometheus exporter.
|
||||
# control-use-cert: no — unbound only accepts plain control connections from
|
||||
# loopback in this mode, so no TLS certs need to be generated.
|
||||
remote-control:
|
||||
control-enable: yes
|
||||
control-interface: 127.0.0.1
|
||||
control-use-cert: no
|
||||
|
||||
include: "{{ unbound_custom_lan_config_path }}"
|
||||
include: "{{ unbound_custom_vpn_config_path }}"
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
# Prometheus exporter
|
||||
unbound_exporter_package: prometheus-unbound-exporter
|
||||
unbound_exporter_service: prometheus-unbound-exporter
|
||||
unbound_exporter_args_file: /etc/conf.d/prometheus-unbound-exporter
|
||||
unbound_exporter_args_var: UNBOUND_EXPORTER_ARGS
|
||||
Reference in New Issue
Block a user