Prometheus and node_exporter Setup
A disk at 80 percent is a ticket; a disk at 100 percent is an outage. I got fed up with finding out about the second kind from users, so Prometheus is now what I use for monitoring. It pulls metrics over HTTP from small exporters on each host and stores them as time series. node_exporter covers the host basics: CPU, memory, disk, network, filesystems.
I'm using Prometheus 2.11 and node_exporter 0.18 from the release tarballs on Ubuntu 18.04, both as systemd services under unprivileged users. CentOS 7 is the same with useradd and firewall-cmd. You need a Prometheus host with a few gigabytes free for the database, and port 9100 reachable on each monitored host.
node_exporter on each monitored host
cd /tmp
curl -LO https://github.com/prometheus/node_exporter/releases/download/v0.18.1/node_exporter-0.18.1.linux-amd64.tar.gz
tar xzf node_exporter-0.18.1.linux-amd64.tar.gz
sudo cp node_exporter-0.18.1.linux-amd64/node_exporter /usr/local/bin/
sudo useradd --system --no-create-home --shell /usr/sbin/nologin node_exporter
Create the unit file /etc/systemd/system/node_exporter.service:
[Unit]
Description=Prometheus Node Exporter
After=network-online.target
Wants=network-online.target
[Service]
User=node_exporter
Group=node_exporter
ExecStart=/usr/local/bin/node_exporter \
--collector.systemd \
--collector.filesystem.ignored-mount-points="^/(sys|proc|dev|run|var/lib/docker/.+)($|/)"
Restart=on-failure
[Install]
WantedBy=multi-user.target
The systemd collector adds unit states, which is handy for alerting on failed services. The mount point filter keeps Docker's overlay mounts from producing hundreds of pointless filesystem series.
sudo systemctl daemon-reload
sudo systemctl enable --now node_exporter
curl -s http://localhost:9100/metrics | head
sudo ufw allow from 10.0.0.10 to any port 9100 proto tcp
Restrict port 9100 to the Prometheus server's address; the metrics are not secret, but there is no reason to publish them.
Prometheus itself
On the monitoring host:
cd /tmp
curl -LO https://github.com/prometheus/prometheus/releases/download/v2.11.1/prometheus-2.11.1.linux-amd64.tar.gz
tar xzf prometheus-2.11.1.linux-amd64.tar.gz
cd prometheus-2.11.1.linux-amd64
sudo useradd --system --no-create-home --shell /usr/sbin/nologin prometheus
sudo mkdir -p /etc/prometheus /var/lib/prometheus
sudo cp prometheus promtool /usr/local/bin/
sudo cp -r consoles console_libraries /etc/prometheus/
sudo chown -R prometheus:prometheus /etc/prometheus /var/lib/prometheus
Configuration
sudo nano /etc/prometheus/prometheus.yml
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
- job_name: 'node'
static_configs:
- targets:
- 'web01.example.com:9100'
- 'db01.example.com:9100'
labels:
env: production
I always run promtool before starting anything; YAML indentation errors are the usual cause of a dead Prometheus:
sudo chown prometheus:prometheus /etc/prometheus/prometheus.yml
promtool check config /etc/prometheus/prometheus.yml
Running it as a service
/etc/systemd/system/prometheus.service:
[Unit]
Description=Prometheus
After=network-online.target
Wants=network-online.target
[Service]
User=prometheus
Group=prometheus
ExecStart=/usr/local/bin/prometheus \
--config.file=/etc/prometheus/prometheus.yml \
--storage.tsdb.path=/var/lib/prometheus \
--storage.tsdb.retention.time=30d \
--web.console.templates=/etc/prometheus/consoles \
--web.console.libraries=/etc/prometheus/console_libraries \
--web.listen-address=127.0.0.1:9090
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure
[Install]
WantedBy=multi-user.target
I bind the web UI to localhost and reach it through an SSH tunnel or an nginx proxy with authentication; Prometheus has no built-in auth. Thirty days of retention at a 15-second interval for a handful of hosts is a few gigabytes.
sudo systemctl daemon-reload
sudo systemctl enable --now prometheus
First look
ssh -L 9090:127.0.0.1:9090 monitor.example.com
Open http://localhost:9090/targets in a browser. Every target should show UP. Then run a query on the Graph page to make sure data is arriving:
100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)
That is CPU utilization per host. Another useful one, free space on the root filesystem in percent:
node_filesystem_avail_bytes{mountpoint="/"} / node_filesystem_size_bytes{mountpoint="/"} * 100
Trouble spots
- Target shows
DOWNwithcontext deadline exceeded. Prometheus cannot reach port 9100: a firewall rule, or node_exporter bound to a different address.curl http://web01.example.com:9100/metricsfrom the Prometheus host tells you which. err="opening storage failed: lock DB directory: resource temporarily unavailable". Another Prometheus process is already using/var/lib/prometheus, or a previous one did not exit cleanly.systemctl status prometheusand remove the stalelockfile only if you are sure nothing is running.level=error ... msg="Error loading config" ... yaml: unmarshal errors. Indentation inprometheus.yml.promtool check configpoints at the line.node_systemd_*metrics missing. The--collector.systemdflag was not passed, or the user cannot talk to D-Bus. Checkjournalctl -u node_exporterforcouldn't get dbus connection.
Alertmanager and Grafana are next for me. Even before that, a month of per-host history changes how you troubleshoot.