构建内容
一个小型实例,通过私有隧道抓取你拥有的其他每台机器,并在有问题即将发生时向你发送邮件。节点指标、站点间的黑盒探测、带合理阈值的安全规则,以及一个将通知分组而不是在凌晨三点向你发送四百封邮件的 Alertmanager 配置。
此构建中没有仪表盘。仪表盘很美观,但并不是监控;没人看的图表从未叫醒过任何人。如果需要,你可以稍后在相同数据之上添加一个。
开始前
- 选一台 R-4 作为监控机。以十五秒间隔监控一百个节点,每分钟产生几十万个样本,这台机器能轻松处理。
- 把它放在你的资产群之外的地方。任何与所监控对象共用一栋楼的监控机,在你最需要它喊叫的那一天,恰恰会保持安静。如果你的服务器群位于欧洲,多伦多或新加坡是合理的选择。
- 通过 WireGuard 指南 与每个监控节点建立隧道。导出器会暴露大量关于机器的信息,不应该出现在公共接口附近。
1. 在每个监控节点上
apt update && apt install -y prometheus-node-exporter
mkdir -p /etc/systemd/system/prometheus-node-exporter.service.d
cat > /etc/systemd/system/prometheus-node-exporter.service.d/bind.conf <<EOF
[Service]
Environment=ARGS=--web.listen-address=10.7.0.11:9100 --collector.systemd --collector.processes
EOF
systemctl daemon-reload && systemctl restart prometheus-node-exporter
ss -ltn | grep 9100替换为每个节点自己的隧道地址。绑定到隧道而不是所有接口,意味着防火墙是第二道防线,而不是唯一防线。
2. 在监控机上
apt install -y prometheus prometheus-alertmanager prometheus-blackbox-exporter写入 /etc/prometheus/prometheus.yml:
global:
scrape_interval: 15s
evaluation_interval: 15s
external_labels:
fleet: main
alerting:
alertmanagers:
- static_configs:
- targets: ['127.0.0.1:9093']
rule_files:
- /etc/prometheus/rules/*.yml
scrape_configs:
- job_name: nodes
file_sd_configs:
- files: ['/etc/prometheus/targets/*.yml']
- job_name: probe_https
metrics_path: /probe
params:
module: [http_2xx]
static_configs:
- targets:
- https://app.example.com/health
- https://cloud.example.com/status.php
relabel_configs:
- source_labels: [__address__]
target_label: __param_target
- source_labels: [__param_target]
target_label: instance
- target_label: __address__
replacement: 127.0.0.1:9115基于文件的发现优于静态列表,值得增加一个额外目录。添加一个节点只需一个文件,而且该文件可以由任何配置你机器的工具写入。/etc/prometheus/targets/ams.yml:
- targets: ['10.7.0.11:9100']
labels: { site: AMS-01, role: web }
- targets: ['10.7.0.12:9100']
labels: { site: AMS-01, role: db }这些标签使后面的告警更易读。一条说 db in AMS-01 的告警是可操作的;一条说 10.7.0.12 的告警让你去查电子表格。
3. 值得拥有的规则
/etc/prometheus/rules/fleet.yml:
groups:
- name: fleet
rules:
- alert: NodeDown
expr: up{job="nodes"} == 0
for: 3m
labels: { severity: page }
annotations:
summary: "{{ $labels.instance }} in {{ $labels.site }} stopped answering"
- alert: DiskFillingUp
expr: predict_linear(node_filesystem_avail_bytes{fstype=~"ext4|xfs|zfs|btrfs"}[6h], 4*3600) < 0
for: 30m
labels: { severity: page }
annotations:
summary: "{{ $labels.instance }} fills {{ $labels.mountpoint }} within four hours"
- alert: MemoryPressure
expr: node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes < 0.10
for: 15m
labels: { severity: warn }
- alert: IOWaitHigh
expr: avg by (instance) (rate(node_cpu_seconds_total{mode="iowait"}[5m])) > 0.25
for: 20m
labels: { severity: warn }
- alert: CertificateExpiring
expr: probe_ssl_earliest_cert_expiry - time() < 10*86400
labels: { severity: warn }
- alert: ProbeFailing
expr: probe_success == 0
for: 5m
labels: { severity: page }predict_linear 是这条构建的核心规则。对剩余空间的阈值告诉你磁盘已满;而将六小时的趋势向前外推,告诉你它将在下午四点左右满,这是你仍然可以冷静解决的问题。基于固定百分比的磁盘告警,要么在小容量卷上太过嘈杂,要么在大容量卷上毫无用处。
4. Alertmanager
route:
receiver: mail
group_by: [alertname, site]
group_wait: 45s
group_interval: 5m
repeat_interval: 12h
routes:
- matchers: [severity="warn"]
repeat_interval: 72h
inhibit_rules:
- source_matchers: [alertname="NodeDown"]
target_matchers: [severity="warn"]
equal: [instance]
receivers:
- name: mail
email_configs:
- to: [email protected]
from: [email protected]
smarthost: mail.example.com:587
auth_username: [email protected]
auth_password: "<the mailbox password>"抑制规则是收到一条消息和四十条消息的区别。当一个节点宕机时,关于该节点的所有警告都被抑制,因为你已经知道:节点宕机了。
按 alertname 和 site 分组意味着整个站点停电时只产生一封邮件列出每台机器,而不是每台机器一封邮件。那台邮件服务器是 邮件指南 中的那台,而依赖于你也在监控的基础设施作为告警路径,是一个已知的权衡;另一个指向某个 webhook 的接收器是廉价的保险。
systemctl enable --now prometheus prometheus-alertmanager prometheus-blackbox-exporter保留期值得刻意设置。一百个节点九十天的数据是几十 GB:
echo 'ARGS="--storage.tsdb.retention.time=90d --storage.tsdb.retention.size=40GB"' > /etc/default/prometheus
systemctl restart prometheus验证
先检查语法,因为规则文件中的拼写错误会在加载时静默失败,而你会在事件发生时才察觉:
promtool check config /etc/prometheus/prometheus.yml
promtool check rules /etc/prometheus/rules/fleet.yml然后确认每个目标都被抓取:
curl -s http://127.0.0.1:9090/api/v1/targets | grep -o "\"health\":\"[a-z]*\"" | sort | uniq -c每个目标都应报告 up。如果有一个报告 down,要么是防火墙规则问题,要么是导出器绑定了错误的地址。
现在,唯一能证明整个链路有效性的测试是故意破坏一些东西。在某个受监控节点上:
systemctl stop prometheus-node-exporter三分钟后,告警应转为 pending,然后 firing。观察它的变化:
curl -s http://127.0.0.1:9090/api/v1/alerts | head -c 400
amtool --alertmanager.url=http://127.0.0.1:9093 alert query触发后大约一分钟内,邮件到达。如果告警触发但没有邮件,问题在 smarthost 凭据,journalctl -u prometheus-alertmanager 会直接指出。重新启动导出器,并确认你也收到恢复通知,因为一个从不告诉你事情已好转的告警系统会让你学会忽略它。
systemctl start prometheus-node-exporter之后
在站点之间添加黑盒探针,从每个站点到其他站点,你会得到自己网络资产的延迟矩阵,在故障期间比任何状态页面都有用得多。我们的在 status,而 looking glass 在路由看起来不对时回答了问题的另一半。