Mediante la monitorización de PowerDNS con PMM2 seremos capaces de detectar problemas en nuestros DNS, caídas de servicio, errores, timeouts, paquetes corruptos e incluso problemas de carga en los servidores.
Siguiendo con el artículo anterior vamos a configurar el exporter para PowerDNS, el exporter solo soporta PowerDNS-4.1.13(26/05/2020), si instalamos 4.2.1 solo veremos tres métricas:
powerdns_authoritative_exporter_json_parse_failures 0
powerdns_authoritative_exporter_total_scrapes 1
powerdns_authoritative_up 0
Consultamos las versiones disponibles:
Available versions: 4.1.13^t ~4.2.0^t [m]4.2.1^t [m]~4.2.1-r1^t [m]~4.2.2^t [m]~4.3.0^t {botan debug doc geoip ldap libressl lua lua-records luajit mydns mysql opendbx postgres protobuf remote sodium sqlite systemd test tinydns tools}
Downgradeamos hasta que actualicen el exporter:
echo “>=net-dns/pdns-4.2.1” > /etc/portage/package.mask/pdns
Compilamos e instalamos la versión indicada:
Para que el exporter pueda consultar los datos hay que habilitar la API de PowerDNS.
MASTER:
cat >/etc/powerdns/pdns.conf «EOL
launch=gmysql
gmysql-host=127.0.0.1
gmysql-dbname=pdns
gmysql-user=pdns
gmysql-password=PASSWORD
setgid=pdns
setuid=pdns
local-address=MASTER_IP
master=yes
default-soa-name=ns1.alfaexploit.com.
allow-axfr-ips=SLAVE_IP
also-notify=SLAVE_IP
api=yes
api-key=PDNS_KEY
webserver=yes
webserver-address=127.0.0.1
webserver-allow-from=127.0.0.1/32
EOL
SLAVE:
cat >/etc/powerdns/pdns.conf «EOL
launch=gmysql
gmysql-host=127.0.0.1
gmysql-dbname=pdns
gmysql-user=pdns
gmysql-password=PASSWORD
setgid=pdns
setuid=pdns
local-address=SLAVE_IP
slave=yes
default-soa-name=ns1.alfaexploit.com.
allow-notify-from=MASTER_IP/32
api=yes
api-key=PDNS_KEY
webserver=yes
webserver-address=127.0.0.1
webserver-allow-from=127.0.0.1/32
EOL
Reiniciamos PowerDNS:
Comprobamos que la API funcione:
{
"config_url": "/api/v1/servers/localhost/config{/config_setting}",
"daemon_type": "authoritative",
"id": "localhost",
"type": "Server",
"url": "/api/v1/servers/localhost",
"version": "4.1.13",
"zones_url": "/api/v1/servers/localhost/zones{/zone}"
}
El exporter está escrito en Go así que instalamos el compilador de Go:
Nos bajamos el exporter:
https://github.com/ledgr/powerdns_exporter
export GOPATH=/root/go
vi .bashrc
export GOPATH=/root/go
export GOPATH=$(go env GOPATH)
Lo copiamos a un path mas apropiado:
Arrancamos el exporter indicando la api-url como indica su documentación y bindeándolo a la loopback ya que vamos a meter un Nginx para que pida credenciales:
https://github.com/ledgr/powerdns_exporter
Demonizamos el exporter y lo arrancamos:
chmod 700 /etc/local.d/pdnsExporter.start
/etc/local.d/pdnsExporter.start
Compilamos e instalamos Nginx:
Realizamos una copia del fichero de configuración de Nginx:
Dejamos la siguiente:
user nginx nginx;
worker_processes 1;
error_log /var/log/nginx/error_log info;
events {
worker_connections 1024;
use epoll;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main
'$remote_addr - $remote_user [$time_local] '
'"$request" $status $bytes_sent '
'"$http_referer" "$http_user_agent" '
'"$gzip_ratio"';
client_header_timeout 10m;
client_body_timeout 10m;
send_timeout 10m;
connection_pool_size 256;
client_header_buffer_size 1k;
large_client_header_buffers 4 2k;
request_pool_size 4k;
gzip off;
output_buffers 1 32k;
postpone_output 1460;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 75 20;
ignore_invalid_headers on;
index index.html;
server {
listen SERVER_IP:9120;
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:9120;
}
}
}
Con esta configuración si la petición procede de PMM se servirán las métricas, en caso contrario serán necesarias las credenciales.
Generamos el fichero de autenticación:
htpasswd -c /etc/nginx/.htpasswd admin
Arrancamos Nginx:
rc-update add nginx default
Comprobamos que podamos acceder con las credenciales:
Comprobamos que desde PMM podamos acceder sin credenciales:
Añadimos el scrape a Prometheus:
scrape_configs:
- job_name: PowerDNS
scrape_interval: 1m
scrape_timeout: 10s
metrics_path: /metrics
scheme: http
static_configs:
- targets:
- kr0mtest:9120
- kr0mtest2:9120
Recargamos la configuración:
Podemos ver los exporters en targets:
Por desgracia no hay ningún dashboard de Grafana, si queremos uno tendremos que crear los paneles con las querys pertinentes.
Las métricas mostradas por el exporter solo suben, por lo tanto para detectar problemas debemos calcular un delta de los datos:
groups:
- name: pdnsRules
rules:
- alert: PowerDNSExporterDown
expr: sum(up{job="PowerDNS"} == 0) by (instance)
for: 5m
labels:
severity: critical
- alert: PowerDNSBackendOverload
expr: delta(powerdns_authoritative_exceptions_total{error="backend_overload"}[5m]) > 5
for: 5m
labels:
severity: critical
- alert: PowerDNSCorruptPackets
expr: delta(powerdns_authoritative_exceptions_total{error="corrupt_packets"}[5m]) > 5
for: 5m
labels:
severity: critical
- alert: PowerDNSRcvBufferErrors
expr: delta(powerdns_authoritative_exceptions_total{error="recvbuf_errors"}[5m]) > 5
for: 5m
labels:
severity: critical
- alert: PowerDNSServerDown
expr: delta(powerdns_authoritative_exceptions_total{error="servfail"}[5m]) > 5
for: 5m
labels:
severity: critical
- alert: PowerDNSSndBufferErrors
expr: delta(powerdns_authoritative_exceptions_total{error="sndbuf_errors"}[5m]) > 5
for: 5m
labels:
severity: critical
- alert: PowerDNSTimeoutErrors
expr: delta(powerdns_authoritative_exceptions_total{error="timeout"}[5m]) > 5
for: 5m
labels:
severity: critical
- alert: PowerDNSUdpInputErrors
expr: delta(powerdns_authoritative_exceptions_total{error="udo_in_errors"}[5m]) > 5
for: 5m
labels:
severity: critical
- alert: PowerDNSDown
expr: delta(powerdns_authoritative_exporter_json_parse_failures[5m]) > 0
for: 1m
labels:
severity: critical
Si paramos un PowerDNS veremos la alerta:
Si hemos seguido la guía sobre
Alertmanager
veremos en Telegram alertas como esta: