BIND’s statistics channel is the primary source of truth for its operational health, but getting that data into Prometheus for long-term storage and analysis requires a specific adapter.
Here’s how we’ll get BIND metrics into Prometheus, step-by-step:
First, we need to enable the statistics channel in BIND. This is done in the named.conf file, usually located in /etc/bind/ or /etc/named/. You’ll need to add or modify the statistics-channel stanza.
options {
directory "/var/cache/bind";
// ... other options ...
statistics-channel {
inet 127.0.0.1 port 8053 allow { 127.0.0.1; };
clients { 127.0.0.1; };
// The format is crucial for Prometheus. 'json' is the most common and easiest to parse.
format "json";
};
// ... other options ...
};
inet 127.0.0.1 port 8053: This binds the statistics channel to localhost on port 8053. You can choose any unused port, but 8053 is a common convention.allow { 127.0.0.1; }: This restricts access to the statistics channel to localhost. For production, you might want to allow specific IPs of your monitoring servers if they are not on the same host.format "json": This tells BIND to output its statistics in JSON format, which is easily consumable by Prometheus exporters.
After modifying named.conf, you must reload or restart BIND for the changes to take effect. The command varies by distribution:
- Debian/Ubuntu:
sudo systemctl reload bind9orsudo systemctl restart bind9 - RHEL/CentOS/Fedora:
sudo systemctl reload namedorsudo systemctl restart named
Now, we can verify that the statistics channel is working. Use curl to fetch the data:
curl http://127.0.0.1:8053
You should see a JSON output containing various BIND statistics. If you get a connection refused error, double-check your named.conf syntax, the port number, and ensure BIND reloaded successfully.
Next, we need a Prometheus exporter that can scrape this BIND statistics channel and expose the metrics in Prometheus’s exposition format. The bind_exporter is a popular choice. You can typically install it from your distribution’s package manager or compile it from source.
On Debian/Ubuntu, you might find it as prometheus-bind-exporter or you might need to build it. For example, if building from source:
# Download and build
wget https://github.com/ Prometheus-community/bind_exporter/archive/refs/tags/v0.3.0.tar.gz
tar -xzf v0.3.0.tar.gz
cd bind_exporter-0.3.0
go build -o bind_exporter .
# Move to a suitable location
sudo mv bind_exporter /usr/local/bin/
Once installed, you’ll configure bind_exporter to connect to BIND’s statistics channel. The default configuration often points to http://localhost:8053, but you can override this with command-line flags.
The exporter needs to know BIND’s statistics URL. Run the exporter with the appropriate flag:
# If BIND is on the same host and port 8053
/usr/local/bin/bind_exporter --bind.statistics-uri http://localhost:8053
# If BIND is on a different host or port
# /usr/local/bin/bind_exporter --bind.statistics-uri http://your-bind-host:8053
It’s best to run this exporter as a service. You can create a systemd service file (e.g., /etc/systemd/system/bind_exporter.service):
[Unit]
Description=Prometheus BIND Exporter
Wants=network-online.target
After=network-online.target
[Service]
User=prometheus
Group=prometheus
Type=simple
ExecStart=/usr/local/bin/bind_exporter --bind.statistics-uri http://localhost:8053
[Install]
WantedBy=multi-user.target
Note: Ensure the prometheus user and group exist and have appropriate permissions, or adjust the User and Group directives.
After creating the service file, enable and start it:
sudo systemctl daemon-reload
sudo systemctl enable bind_exporter
sudo systemctl start bind_exporter
sudo systemctl status bind_exporter
Finally, configure your Prometheus server to scrape the bind_exporter. Add a new job to your prometheus.yml configuration file:
scrape_configs:
- job_name: 'bind'
static_configs:
- targets: ['localhost:9119'] # Default port for bind_exporter
If bind_exporter is running on a different host, use its IP address instead of localhost.
Reload your Prometheus configuration:
curl -X POST http://localhost:9090/-/reload
Now, navigate to your Prometheus UI, go to "Status" -> "Targets," and you should see the bind job with your bind_exporter instance. The state should be "UP."
The most surprising true thing about BIND’s statistics is that the JSON format, while convenient for machines, is actually a relatively recent addition and not universally enabled by default in older BIND versions. For a long time, users had to parse the older, less structured text-based statistics output, which was significantly more brittle.
Let’s see bind_exporter in action. Imagine BIND is serving DNS requests and experiencing some cache misses. The bind_exporter is running and scraping BIND’s statistics channel. Prometheus is configured to scrape the exporter.
Here’s a snippet of what the exporter might expose, and how Prometheus would represent it:
-
BIND’s JSON Stats (partial):
{ "name-server": "bind9", "version": "9.18.18-0ubuntu0.22.04.1-Ubuntu", "uptime": 1234567, "datetime": "2023-10-27T10:00:00Z", "requests": { "total": 500000, "rate": 100, "xfr": 10, "update": 5 }, "queries-in": { "total": 499990, "rate": 99, "udp": 499900, "tcp": 90 }, "response-NXDOMAIN": 5000, "response-NOERROR": 490000 // ... many more stats } -
Prometheus Metrics (as exposed by
bind_exporter):# HELP bind_isc_requests_total Total number of requests received by the server. # TYPE bind_isc_requests_total counter bind_isc_requests_total{instance="localhost:9119",job="bind",type="total"} 500000 # HELP bind_isc_queries_in_total Total number of queries received by the server. # TYPE bind_isc_queries_in_total counter bind_isc_queries_in_total{instance="localhost:9119",job="bind",type="udp"} 499900 bind_isc_queries_in_total{instance="localhost:9119",job="bind",type="tcp"} 90 # HELP bind_isc_response_nxdomain_total Number of NXDOMAIN responses sent. # TYPE bind_isc_response_nxdomain_total counter bind_isc_response_nxdomain_total{instance="localhost:9119",job="bind"} 5000 # HELP bind_isc_uptime_seconds Uptime of the BIND server in seconds. # TYPE bind_isc_uptime_seconds gauge bind_isc_uptime_seconds{instance="localhost:9119",job="bind"} 1234567
In Prometheus, you can now query these metrics. For example, to see the rate of queries per second:
rate(bind_isc_queries_in_total[1m])
Or to monitor the number of NXDOMAIN responses:
bind_isc_response_nxdomain_total
The bind_exporter maps BIND’s JSON statistics to Prometheus-friendly metric names. It handles the parsing and conversion. Key levers you control are the statistics-channel configuration in BIND (port, IP, access) and the bind_exporter’s target URI, along with Prometheus’s scrape configuration.
A subtle but important detail is how bind_exporter handles different versions of BIND and their statistics output. While the JSON format is preferred, older versions might expose slightly different structures. The exporter is designed to be robust, but if you encounter unexpected metrics or missing data, checking the BIND version and its exact JSON output is a good first step. Some statistics might also be conditional on BIND features being enabled (e.g., DNSSEC stats only appear if DNSSEC is configured).
The next step after successfully exporting BIND metrics is to set up meaningful alerts and dashboards in Grafana based on these metrics.