Prometheus 全栈监控 —— 配置参数完全参考手册
Prometheus 全栈监控 —— 配置参数完全参考手册
日期: 2026-05-30
版本: Prometheus 2.45.3 / Alertmanager 0.26.0 / Grafana 13.0.1 / webhook-dingtalk 2.1.0
环境: 华为云香港区 ECS x4 (Ubuntu 24.04.4 LTS)
目录
- 1. prometheus.yml —— 核心采集配置
- 2. alertmanager.yml —— 告警路由配置
- 3. node_alerts.yml —— 告警规则详解
- 4. webhook-dingtalk config.yml —— 钉钉集成配置
- 5. Systemd Unit —— 服务管理配置
- 6. Grafana Dashboard JSON —— 仪表盘结构详解
- 7. PromQL 表达式逐行解读
- 8. 参数速查总表
1. prometheus.yml —— 核心采集配置
文件路径: /etc/prometheus/prometheus.yml
Prometheus 的唯一核心配置文件。采用 YAML 格式,启动时加载,支持热重载(kill -HUP 或 systemctl reload)。
1.1 global 全局配置
global:
scrape_interval: 15s
evaluation_interval: 15s
external_labels:
cluster: 'hk-prod'
region: 'hongkong'
| 参数 | 类型 | 默认值 | 当前值 | 含义 |
|---|---|---|---|---|
scrape_interval |
duration | 1m |
15s |
全局采集间隔。Prometheus 每隔多久从 targets 拉取一次指标。所有 scrape_configs 中未单独指定的 job 继承此值。15s 是生产环境常用值——平衡时效性与存储压力。更小的值(如 5s)会增加 CPU 和磁盘开销。 |
evaluation_interval |
duration | 1m |
15s |
规则评估间隔。Prometheus 每隔多久检查一次告警规则和 recording rules。注意:规则中 for 的计时器依赖此值——如果设为 1m,那么 for: 2m 实际可能需要 2m-3m 才触发。15s 与 scrape_interval 对齐是最佳实践。 |
external_labels |
map | {} |
(可选) | 外部标签。附加到所有从本 Prometheus 发出的指标和告警上。联邦场景中用于区分不同 Prometheus 实例。告警也会携带这些标签。 |
设计决策 —— 为什么是 15s?
频率对比:
5s → 每天 17280 次抓取 × N 个 target → 存储压力大
15s → 每天 5760 次抓取 × N 个 target → 平衡点
30s → 每天 2880 次抓取 × N 个 target → 可能错过短时尖峰
1m → 每天 1440 次抓取 × N 个 target → 默认值但偏慢
对于 4 节点集群:15s 间隔下 CPU 开销 <1%,存储约 50MB/天,完全可接受。
1.2 alerting 告警端配置
alerting:
alertmanagers:
- static_configs:
- targets: ['localhost:9093']
| 参数 | 类型 | 含义 |
|---|---|---|
alerting |
block | 告警配置根节点。定义 Prometheus 向哪些 Alertmanager 实例发送告警。 |
alertmanagers |
array | Alertmanager 实例列表。支持多个 Alertmanager 组成 HA 集群。 |
static_configs |
array | 静态发现。直接指定 Alertmanager 地址。也可以用 dns_sd_configs、file_sd_configs 等动态发现。 |
targets |
array | Alertmanager 地址列表。这里只有一个本地实例 localhost:9093。格式为 host:port。 |
scheme |
string | 协议(未显式配置,默认 http)。可选 https。 |
path_prefix |
string | API 路径前缀(未配置,默认 /)。Alertmanager API 路径,默认无需修改。 |
timeout |
duration | 超时时间(未配置,默认 10s)。向 Alertmanager 发送告警的 HTTP 请求超时。 |
多实例 HA 示例(本次未使用,仅供参考):
alerting:
alertmanagers:
- static_configs:
- targets:
- 'alertmanager-1:9093'
- 'alertmanager-2:9093'
- 'alertmanager-3:9093'
注意: Alertmanager 本身通过 gossip 协议组成集群实现 HA,Prometheus 只需配置任意一台,告警会自动在集群内同步。但配置多台可以防止单点故障。
1.3 rule_files 规则文件引用
rule_files:
- /etc/prometheus/rules/*.yml
| 参数 | 含义 |
|---|---|
rule_files |
规则文件列表。支持 glob 通配符。Prometheus 启动时加载所有匹配的文件。 |
/etc/prometheus/rules/*.yml |
匹配模式。当前加载 /etc/prometheus/rules/ 目录下所有 .yml 文件。可以分散管理:按组件(node/kubernetes/app)分文件,每个文件独立维护。 |
最佳实践:
rule_files:
- /etc/prometheus/rules/node_alerts.yml # 节点级告警
- /etc/prometheus/rules/kubernetes_alerts.yml # K8s 告警
- /etc/prometheus/rules/app_alerts.yml # 应用告警
- /etc/prometheus/rules/recording_rules.yml # 预计算规则
规则文件加载失败的处理:Prometheus 启动时如果规则文件语法错误,整个进程会退出。务必在重载前用 promtool check rules 验证。
1.4 scrape_configs 采集目标配置
这是配置文件中最核心、最复杂的部分。每个 scrape_config 定义一个采集 job。
1.4.1 job_name
scrape_configs:
- job_name: 'prometheus'
- job_name: 'node'
| 参数 | 类型 | 含义 |
|---|---|---|
job_name |
string | Job 名称,必填。自动作为 label job="<name>" 附加到该 job 采集到的所有指标上。全局唯一,重复会导致指标混乱。命名惯例:小写字母 + 下划线。 |
job 标签是 Prometheus 最重要的标签之一——它定义了指标来源的业务语义。例如:
job="prometheus"→ Prometheus 自监控指标job="node"→ 所有服务器的系统指标
1.4.2 static_configs
- job_name: 'node'
static_configs:
- targets:
- '192.168.0.228:9100'
- '192.168.0.207:9100'
- '192.168.0.238:9100'
- '192.168.0.152:9100'
| 参数 | 类型 | 含义 |
|---|---|---|
static_configs |
array | 静态目标配置列表。每个元素是一个 target group。最简单的服务发现方式——手动列出所有 IP:Port。 |
targets |
array | 目标地址列表。格式 host:port。Prometheus 会向 http://host:port/metrics 发起 GET 请求拉取指标。 |
labels |
map | 附加标签(未使用,示例见下方)。为这个 target group 的所有指标添加额外 label。 |
为什么用内网 IP?
方案 A: targets: ['120.46.81.16:9100', '120.46.209.49:9100', ...] (公网 IP)
方案 B: targets: ['192.168.0.228:9100', '192.168.0.207:9100', ...] (内网 IP) ✅
选 B 的原因:
1. 华为云内网互通,无需消耗公网带宽
2. 内网延迟 <1ms vs 公网 ~10ms
3. 不依赖公网 IP 可达性(安全组变更不影响监控)
4. instance label 显示内网 IP,可通过 Grafana 直接识别节点
为 target group 添加标签:
static_configs:
- targets: ['192.168.0.228:9100']
labels:
env: 'production'
datacenter: 'hongkong'
role: 'master'
注意: 在 Prometheus 2.x 中,
labels必须在static_configs数组元素内部,不能放在job_name同级。放在外层会报错field labels not found。
1.4.3 honor_labels
honor_labels: false # 默认值,通常不写
| 值 | 含义 |
|---|---|
false(默认) |
如果采集到的指标已有 job 或 instance label,Prometheus 会用自己的值覆盖。确保标签一致性。 |
true |
保留目标端原始标签。用于 Pushgateway 或联邦场景——信任远端 Prometheus 的标签。 |
绝大多数场景保持默认 false。
1.4.4 scrape_interval / scrape_timeout
scrape_interval: 15s # 可选,覆盖 global
scrape_timeout: 10s # 可选
| 参数 | 类型 | 默认值 | 含义 |
|---|---|---|---|
scrape_interval |
duration | global.scrape_interval |
Job 级采集间隔。覆盖 global 配置。用于对特定 job 设置更频繁(如关键服务 5s)或更稀疏(如低频服务 60s)的采集。 |
scrape_timeout |
duration | 10s |
单次采集超时。Prometheus 等待 target 响应 /metrics 的超时时间。必须小于 scrape_interval,否则可能发生采集重叠。 |
超时与间隔的关系:
scrape_interval = 15s
scrape_timeout = 10s ← 必须 < 15s
时间线:
t=0 → 开始采集 target
t=10s → 如果无响应,终止请求(timeout)
t=15s → 开始下一次采集
1.4.5 metrics_path
metrics_path: '/metrics' # 默认值,通常不写
| 参数 | 默认值 | 含义 |
|---|---|---|
metrics_path |
/metrics |
指标暴露路径。Prometheus 向 http://<target>/metrics 发起 GET 请求。绝大多数 exporter 遵循 /metrics 约定,无需修改。 |
特殊场景:
# Spring Boot Actuator
metrics_path: '/actuator/prometheus'
# Istio sidecar
metrics_path: '/stats/prometheus'
1.4.6 scheme
scheme: 'http' # 默认值,可改为 'https'
| 值 | 含义 |
|---|---|
http |
通过 HTTP 明文采集 |
https |
通过 HTTPS/TLS 加密采集,需配合 tls_config 配置证书 |
1.4.7 relabel_configs
采集前标签重写。在 Prometheus 抓取指标之前对 target 的标签进行操作。功能强大,核心场景:
- 过滤 target(只保留特定标签的 target)
- 修改 target 标签(替换 IP 为 hostname)
- 添加/删除标签
# 示例:过滤只保留生产环境节点
relabel_configs:
- source_labels: [__meta_ec2_tag_environment]
regex: 'production'
action: keep
动作类型 (action):
| action | 说明 |
|---|---|
replace |
默认。将 source_labels 的值通过 regex 匹配后,写入 target_label。 |
keep |
丢弃不匹配 regex 的 target(白名单)。 |
drop |
丢弃匹配 regex 的 target(黑名单)。 |
labelmap |
将匹配 regex 的所有标签名映射到新标签名。常用于服务发现(将 __meta_* 转为普通标签)。 |
labeldrop |
删除匹配 regex 的标签名。 |
labelkeep |
只保留匹配 regex 的标签名。 |
hashmod |
对 source_labels 做哈希取模,常用于分片。 |
本次部署未使用 relabel_configs——静态配置 4 个 IP 已足够简单。当节点数量增长或引入服务发现时,relabel 是必须掌握的技能。
1.4.8 metric_relabel_configs
采集后指标标签重写。在指标存入 TSDB 之前对每条指标数据进行标签操作。
与 relabel_configs 的区别:
| 配置 | 作用时机 | 作用对象 | 典型用途 |
|---|---|---|---|
relabel_configs |
采集前 | Target 元数据标签 | 过滤节点、修改 instance |
metric_relabel_configs |
采集后 | 每条指标的时间序列标签 | 删除高基数标签、降低存储 |
经典用途 —— 删除高基数标签:
# 删除 node_network_info 中的 address 标签(MAC 地址等变化字段会产生高基数)
metric_relabel_configs:
- source_labels: [__name__]
regex: 'node_network_info'
action: drop
2. alertmanager.yml —— 告警路由配置
文件路径: /etc/prometheus/alertmanager.yml
Alertmanager 的核心职责:接收 → 分组 → 抑制 → 静默 → 路由 → 发送。
2.1 global 全局配置
global:
resolve_timeout: 5m
| 参数 | 类型 | 默认值 | 当前值 | 含义 |
|---|---|---|---|---|
resolve_timeout |
duration | 5m |
5m |
告警恢复超时。一条 Firing 告警停止触发后,Alertmanager 等待此时间后发送 “Resolved” 通知。设置为 0 会立即发送恢复通知。5m 的缓冲避免短时抖动反复发送 Resolved/Firing。 |
smtp_smarthost |
string | - | (未配置) | SMTP 服务器。用于邮件告警。格式 host:port。 |
smtp_from |
string | - | (未配置) | 发件人地址。 |
smtp_auth_username |
string | - | (未配置) | SMTP 认证用户名。 |
smtp_auth_password |
string | - | (未配置) | SMTP 认证密码。 |
smtp_require_tls |
bool | true |
(未配置) | 是否要求 TLS。 |
slack_api_url |
string | - | (未配置) | Slack Webhook URL。 |
http_config |
block | - | (未配置) | 全局 HTTP 客户端配置(代理、TLS 等)。 |
本次仅使用钉钉 Webhook,未配置邮件/Slack,故
global中只有resolve_timeout。
2.2 route 路由树
Alertmanager 的核心——路由树。每条告警从根 route 开始,按匹配规则向下分发到对应的 receiver。
route:
receiver: 'default'
group_by: ['alertname', 'instance']
group_wait: 30s
group_interval: 5m
repeat_interval: 4h
routes:
- receiver: 'dingtalk'
continue: true
- matchers:
- severity="critical"
receiver: 'dingtalk'
group_wait: 10s
repeat_interval: 1h
2.2.1 receiver
| 参数 | 含义 |
|---|---|
receiver |
默认接收器。不匹配任何子路由的告警发送到此 receiver。这里是 default——发送到钉钉 webhook。 |
2.2.2 group_by
| 参数 | 含义 |
|---|---|
group_by |
分组标签列表。具有相同标签值的告警被聚合为一条通知。['alertname', 'instance'] 表示:相同告警名 + 相同节点的告警合并发送。 |
分组效果对比:
group_by: ['alertname']
→ 同一条告警的所有实例合并: "4 个节点 CPU > 80%"
→ 优点:一条消息看到全局;缺点:不知道具体哪些节点
group_by: ['alertname', 'instance']
→ 每条告警按节点分开: "node-1 CPU > 80%", "node-2 CPU > 80%"
→ 优点:精确知道哪个节点;缺点:消息条数多
group_by: ['...'] (省略所有)
→ 所有告警聚合为一条:一条消息包含全部信息
→ 优点:最少打扰;缺点:难以快速定位
当前设计: ['alertname', 'instance'] 折中方案——按节点 + 告警类型分开,钉钉群里能快速识别 “哪个节点、什么告警”。
2.2.3 group_wait
| 参数 | 含义 |
|---|---|
group_wait |
首次聚合等待时间(默认 30s)。收到第一条告警后等待此时间,收集同组内其他告警,然后一起发送。 |
时序:
t=0 → InstanceDown{node-1} 触发
t=5s → InstanceDown{node-2} 触发(同组)
t=30s → group_wait 结束 → 发送: "node-1, node-2 离线"
为什么要等? 集群网络抖动时,多个节点可能同时不可达。等待 30s 将多条相同类型的告警打包为一条消息,避免钉钉群被刷屏。
2.2.4 group_interval
| 参数 | 含义 |
|---|---|
group_interval |
同组后续告警最小间隔(默认 5m)。首次通知后,该组如果有新告警加入,至少间隔此时间才发送新通知。 |
时序:
t=0 → InstanceDown{node-1} 触发 → 30s group_wait → 发送
t=1m → InstanceDown{node-2} 加入同组 → 等 group_interval
t=5m → group_interval 到期 → 发送: "node-1 (持续), node-2 (新增)"
2.2.5 repeat_interval
| 参数 | 含义 |
|---|---|
repeat_interval |
重复告警间隔(默认 4h)。告警持续未恢复,每隔多久重新发送一次通知。避免告警风暴——如果设置为 0,每条告警每次评估周期都会发送。 |
默认 4h 的设计:
- 报警后 0h: 发送第一次
- 报警后 4h: 如果还没恢复,重发提醒
- 报警后 8h: 再次重发
- ...
Critical 级别设为 1h: 严重告警每小时催一次,确保不遗漏。
2.2.6 routes 子路由
子路由是路由树的下一级。每条告警从根 route 开始,按顺序匹配子路由。
routes:
- receiver: 'dingtalk'
continue: true # ← 继续向下匹配
- matchers:
- severity="critical"
receiver: 'dingtalk'
group_wait: 10s # critical 告警快速聚合
repeat_interval: 1h # critical 每小时重发
匹配顺序:
告警到达
→ 根 route: 默认 receiver='default'
→ 子路由 1: receiver='dingtalk', continue=true → 匹配(无 matchers = 匹配所有)
→ 子路由 2: severity="critical" → 只有 critical 才匹配
2.2.7 matchers vs match / match_re
Alertmanager 0.22+ 引入了新的 matchers 语法,替代旧版 match / match_re。
| 旧语法 (0.21-) | 新语法 (0.22+) | 说明 |
|---|---|---|
match: {severity: critical} |
matchers: [severity="critical"] |
精确匹配 |
match_re: {severity: ^crit.*} |
matchers: [severity=~"^crit.*"] |
正则匹配 |
| - | matchers: [severity!="warning"] |
不等匹配 |
| - | matchers: [severity!~"^info"] |
不匹配正则 |
本次使用新语法(Alertmanager 0.26.0 支持):
matchers:
- severity="critical" # 精确等于 critical
2.2.8 continue
| 参数 | 默认值 | 含义 |
|---|---|---|
continue |
false |
是否继续向下匹配子路由。false:匹配后停止;true:匹配后继续,一条告警可发给多个 receiver。 |
当前配置:第一个子路由 continue: true,第二个匹配 critical。所以:
- 所有告警 → 发 dingtalk(子路由1,continue=true 不停止)
- critical 告警 → 再发一次 dingtalk(子路由2,使用更短的 group_wait/repeat_interval)
这实际上是一种 trick:critical 告警通过两条路由发送,第二条用更激进的参数。更优雅的做法是用不同 receiver 区分配置。
2.3 receivers 接收器配置
receivers:
- name: 'default'
webhook_configs:
- url: 'http://localhost:8060/dingtalk/dingtalk/send'
send_resolved: true
- name: 'dingtalk'
webhook_configs:
- url: 'http://localhost:8060/dingtalk/dingtalk/send'
send_resolved: true
2.3.1 webhook_configs
| 参数 | 类型 | 含义 |
|---|---|---|
url |
string | Webhook 目标 URL。Alertmanager 向此 URL 发送 HTTP POST,body 为 JSON 格式的告警数据。 |
send_resolved |
bool | 是否发送恢复通知。true 表示告警恢复后也发送一条通知。强烈建议开启——否则不知道告警已自动恢复。 |
http_config |
block | HTTP 客户端配置(代理、TLS、Basic Auth 等)。 |
max_alerts |
int | 单次 POST 最多包含的告警数(默认 0 = 不限制)。 |
Alertmanager 发出的 Webhook JSON 格式:
{
"version": "4",
"groupKey": "{}/{alertname=\"HighCPUUsage\"}:{instance=\"192.168.0.228:9100\"}",
"status": "firing",
"receiver": "dingtalk",
"groupLabels": {"alertname": "HighCPUUsage", "instance": "192.168.0.228:9100"},
"commonLabels": {"job": "node", "severity": "warning"},
"commonAnnotations": {"summary": "CPU > 80% on ...", "description": "CPU usage is 92% ..."},
"externalURL": "http://localhost:9093",
"alerts": [
{
"status": "firing",
"labels": {...},
"annotations": {...},
"startsAt": "2026-05-30T12:00:00Z",
"endsAt": "0001-01-01T00:00:00Z",
"generatorURL": "http://localhost:9090/graph?..."
}
]
}
这个 JSON 被
prometheus-webhook-dingtalk接收后,提取关键字段,渲染为 markdown 格式,加上 HMAC 签名,再 POST 到钉钉 API。
2.3.2 email_configs
# 本次未使用,仅作参考
receivers:
- name: 'email-admin'
email_configs:
- to: 'admin@example.com'
from: 'alertmanager@example.com'
smarthost: 'smtp.example.com:587'
auth_username: 'alertmanager'
auth_password: 'xxx'
headers:
subject: '[{{ .Status | toUpper }}] {{ .GroupLabels.alertname }}'
| 参数 | 含义 |
|---|---|
to |
收件人 |
from |
发件人 |
smarthost |
SMTP 服务器 |
auth_username / auth_password |
认证凭据 |
require_tls |
是否强制 TLS |
html |
邮件正文模板(支持 Go template) |
headers |
自定义邮件头(如 Subject) |
2.3.3 pagerduty_configs / opsgenie_configs / wechat_configs
Alertmanager 原生支持多种通知渠道。config 格式类同 webhook,具体参数见官方文档。
2.4 inhibit_rules 告警抑制
inhibit_rules:
- source_matchers:
- severity="critical"
target_matchers:
- severity="warning"
equal:
- alertname
- instance
| 参数 | 含义 |
|---|---|
source_matchers |
源告警匹配。满足此条件的告警会抑制 target 告警。 |
target_matchers |
目标告警匹配。被抑制的目标。 |
equal |
等价标签。source 和 target 必须具有相同值的标签列表。 |
当前规则解读:
当且仅当:
1. source 是 severity="critical" 的告警
2. target 是 severity="warning" 的告警
3. 两者具有相同的 alertname 和 instance
→ 结果: warning 告警被抑制,不发送
示例:
HighCPUUsage{severity="critical", instance="node-3"} ← firing
HighCPUUsage{severity="warning", instance="node-3"} ← 被抑制(不发送)
HighCPUUsage{severity="warning", instance="node-1"} ← 正常发送(instance 不同)
为什么要抑制? 同一个节点 CPU 既是 critical 又是 warning,钉钉群里两条消息是噪音——critical 已经足够表达严重性。
3. node_alerts.yml —— 告警规则详解
文件路径: /etc/prometheus/rules/node_alerts.yml
3.1 规则文件结构
groups:
- name: <group_name> # 规则组名(用于 UI 显示和组织)
interval: <duration> # 可选,覆盖 global.evaluation_interval
rules:
- alert: <alert_name> # 告警名称(唯一标识)
expr: <promql_expression> # 触发表达式
for: <duration> # 持续时间阈值
labels: <map> # 附加标签
annotations: <map> # 附加注释
| 字段 | 类型 | 必填 | 含义 |
|---|---|---|---|
groups |
array | 是 | 规则组列表。每个 group 按 interval 并行评估。 |
groups[].name |
string | 是 | 组名,在 Prometheus UI 中用于分组展示。 |
groups[].rules |
array | 是 | 该组包含的告警/记录规则列表。 |
rules[].alert |
string | 是 | 告警名称。一条 alert 就是一条时间序列,值:0=正常,1=Firing。 |
rules[].expr |
PromQL | 是 | 触发表达式。返回非空即触发。必须返回 instant vector。 |
rules[].for |
duration | 否 | 持续时长。表达式持续为真 for 时间后才进入 Firing。不写则立即触发。 |
rules[].labels |
map | 否 | 附加到告警上的标签。可用于 Alertmanager 路由匹配。 |
rules[].annotations |
map | 否 | 附加注释。区别于 labels:annotations 不参与路由,仅用于展示和模板中引用。 |
labels vs annotations:
| 属性 | labels | annotations |
|---|---|---|
| 用途 | 标识和路由 | 描述和展示 |
| 参与路由 | ✅ 是(Alertmanager matchers 匹配) |
❌ 否 |
| 模板可用 | ✅ $labels.xxx |
✅ $annotations.xxx |
| 示例 | severity: critical |
summary: "CPU > 80%" |
3.2 InstanceDown 节点离线告警
- alert: InstanceDown
expr: up{job="node"} == 0
for: 2m
labels:
severity: critical
annotations:
summary: "Node {{ $labels.instance }} is DOWN"
description: "Node {{ $labels.instance }} has been down for more than 2 minutes"
表达式逐字段解读:
| 部分 | 含义 |
|---|---|
up |
Prometheus 内置指标。值为 1(采集成功)或 0(采集失败)。每个 target 一条。 |
{job="node"} |
标签选择器。只选择 job="node" 的 up 指标(排除 Prometheus 自监控)。 |
== 0 |
过滤。只保留值为 0 的序列(即采集失败的节点)。 |
for: 2m |
缓冲时间。节点离线需要持续 2 分钟才触发。防止网络瞬时抖动误报。 |
为什么不 for: 0s?
网络抖动场景:
t=0 → scrape 超时,up=0
t=15s → scrape 成功,up=1 (瞬时恢复)
for: 0s → 发送 InstanceDown + InstanceResolved 两条消息 → 噪音
for: 2m → 等待 2 分钟,scrape 已恢复 → 不发送 → 干净
Go template 变量:
| 模板变量 | 来源 | 含义 |
|---|---|---|
{{ $labels.instance }} |
指标 label | 节点标识,如 192.168.0.228:9100 |
{{ $value }} |
表达式值 | 当前触发值,如 0 |
3.3 HighCPUUsage CPU 高使用率告警
- alert: HighCPUUsage
expr: 100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle",job="node"}[5m])) * 100) > 80
for: 5m
labels:
severity: warning
annotations:
summary: "CPU > 80% on {{ $labels.instance }}"
description: "CPU usage is {{ $value }}% on {{ $labels.instance }}"
表达式逐层拆解:
完整表达式:
100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle",job="node"}[5m])) * 100) > 80
逐层:
┌──────────────────────────────────────────────────────────────┐
│ 第1层: node_cpu_seconds_total │
│ Node Exporter 的 CPU 时间累计指标(counter 类型) │
│ mode="idle" — 只取 idle(空闲)模式的时间 │
│ job="node" — 限定 node job │
├──────────────────────────────────────────────────────────────┤
│ 第2层: rate(...[5m]) │
│ 对 5 分钟窗口内的 counter 增量求每秒速率 │
│ 输出: 每秒 idle CPU 时间的比例(如 0.95 表示 95% 空闲) │
├──────────────────────────────────────────────────────────────┤
│ 第3层: avg by(instance) (...) │
│ 按 instance 分组取平均 │
│ 输出: 每个节点的平均 idle 速率(每个 node 一个值) │
├──────────────────────────────────────────────────────────────┤
│ 第4层: * 100 │
│ 转为百分比(0.95 → 95) │
├──────────────────────────────────────────────────────────────┤
│ 第5层: 100 - ... │
│ 反算使用率(100 - idle% = usage%) │
├──────────────────────────────────────────────────────────────┤
│ 第6层: > 80 │
│ 过滤:只保留使用率 > 80% 的序列 │
│ 返回值 < 80 的序列被去除,不触发告警 │
└──────────────────────────────────────────────────────────────┘
为什么用 rate() 而不是直接算?
node_cpu_seconds_total 是 counter 类型——只增不减的累计值。直接用当前值减历史值:
- 可能受 counter 重置(重启)影响出现负数
- 需要手动管理时间窗口
rate() 函数:
- 自动处理 counter 重置(检测到下降时假设发生了重置)
- 计算区间内的每秒平均增长率
- 配合
[5m]窗口平滑短时尖峰
for: 5m 的设计意图:
短时尖峰 vs 持续高负载:
t=0 编译代码,CPU 飙升 100%
t=1m 编译完成,CPU 降回 5%
→ 不触发(没有持续 5 分钟)
t=0 死循环进程,CPU 100%
t=5m 仍未恢复
→ 触发 HighCPUUsage
3.4 HighMemoryUsage 内存高使用率告警
- alert: HighMemoryUsage
expr: (1 - (node_memory_MemAvailable_bytes{job="node"} / node_memory_MemTotal_bytes{job="node"})) * 100 > 85
for: 5m
labels:
severity: warning
annotations:
summary: "Memory > 85% on {{ $labels.instance }}"
description: "Memory usage is {{ $value }}% on {{ $labels.instance }}"
表达式逐层拆解:
(1 - (MemAvailable / MemTotal)) * 100 > 85
┌──────────────────────────────────────────────────┐
│ MemAvailable / MemTotal │
│ 可用内存占总量的比例(如 0.2 = 20% 可用) │
├──────────────────────────────────────────────────┤
│ 1 - (比例) │
│ 已使用比例(1 - 0.2 = 0.8 = 80% 使用) │
├──────────────────────────────────────────────────┤
│ * 100 │
│ 转为百分数(80%) │
├──────────────────────────────────────────────────┤
│ > 85 │
│ 阈值过滤 │
└──────────────────────────────────────────────────┘
为什么用 MemAvailable 而不是 MemFree?
| 指标 | 含义 | 包含内容 |
|---|---|---|
node_memory_MemFree_bytes |
完全未使用的物理内存 | 仅 free memory |
node_memory_MemAvailable_bytes |
内核估算的"实际可用"内存 | free + 可回收的 buffer/cache |
free -h 输出:
total used free shared buff/cache available
Mem: 3.3Gi 400Mi 2.1Gi 0.0Ki 800Mi 2.9Gi
↑ ↑
MemFree (2.1Gi) MemAvailable (2.9Gi)
MemFree 模式 → 显示使用了 36%(含 buffer/cache)
MemAvailable 模式 → 显示使用了 12%(真实使用)
与 free -h 的对应关系: Prometheus 的 MemAvailable = Linux /proc/meminfo 的 MemAvailable = free -h 的 available 列。三者完全一致。
3.5 DiskSpaceLow 磁盘空间不足告警
- alert: DiskSpaceLow
expr: (node_filesystem_avail_bytes{mountpoint="/",fstype!="rootfs",job="node"} / node_filesystem_size_bytes{mountpoint="/",fstype!="rootfs",job="node"}) * 100 < 10
for: 2m
labels:
severity: critical
annotations:
summary: "Disk < 10% on {{ $labels.instance }}"
description: "Disk available is {{ $value }}% on {{ $labels.instance }}"
表达式逐层拆解:
(Avail / Total) * 100 < 10
┌──────────────────────────────────────────────────┐
│ mountpoint="/" │
│ 只监控根分区(排除 /boot、/var 等) │
├──────────────────────────────────────────────────┤
│ fstype!="rootfs" │
│ 排除 rootfs 伪文件系统 │
│ 实际设备: /dev/vda1 (华为云 40GB 系统盘) │
├──────────────────────────────────────────────────┤
│ Avail / Total │
│ 可用空间占总空间的比例(如 0.05 = 5% 可用) │
├──────────────────────────────────────────────────┤
│ * 100 │
│ 转为百分数 │
├──────────────────────────────────────────────────┤
│ < 10 │
│ 可用空间 < 10% 时触发 │
│ 等价于使用率 > 90% │
└──────────────────────────────────────────────────┘
为什么 for: 2m 而不是 5m? 磁盘空间不足比 CPU 高负载更紧急——CPU 会自己降下来,磁盘满了会直接导致服务写失败。2 分钟的缓冲已经足够过滤瞬时波动。
4. webhook-dingtalk config.yml —— 钉钉集成配置
文件路径: /opt/prometheus-webhook-dingtalk/config.yml
targets:
dingtalk:
url: "https://oapi.dingtalk.com/robot/send?access_token=090fba13440082ce1aab6f43a2cc47a7b9866521ddf94c7e9502ac100b87280c"
secret: "SEC7acf1b961d10d3f476f2e9a793148482d75b627b61913c44833b49cc8c35e3a2"
| 参数 | 类型 | 必填 | 含义 |
|---|---|---|---|
targets |
map | 是 | 目标定义。键名(如 dingtalk)将在 webhook URL 路径中使用:/<target_name>/send。 |
targets.<name>.url |
string | 是 | 钉钉机器人 Webhook 地址。从钉钉群 → 群设置 → 智能群助手 → 添加机器人 → 自定义 → 获取。含 access_token 参数。 |
targets.<name>.secret |
string | 是(加签模式) | 加签密钥。在钉钉机器人设置页面的"安全设置"中选择"加签"获得。用于 HMAC-SHA256 算法生成签名,钉钉服务端验证消息来源。 |
targets.<name>.message |
string | 否 | 自定义消息模板。使用 Go template 语法渲染告警内容。不配置则使用内置模板。 |
Webhook URL 路径规则 (v2.1.0):
启动日志:
ts=... level=info msg="Listening on address :8060"
ts=... level=info msg="using default template"
ts=... level=info msg="path=/dingtalk/send method=POST handler=dingtalk"
路由格式: /<target_name>/send
target_name = "dingtalk" → /dingtalk/dingtalk/send
target_name = "webhook" → /webhook/webhook/send
踩坑记录: v2.1.0 的路径是
/dingtalk/dingtalk/send(target name 重复两次),不是旧版的/dingtalk/webhook/dingtalk。写错路径导致 Alertmanager 收到 404。
HMAC 签名原理:
1. 取当前时间戳(毫秒)
2. secret + "\n" + timestamp → HMAC-SHA256 加密 → Base64 编码
3. POST 请求带 header:
Content-Type: application/json
4. POST body:
{
"msgtype": "markdown",
"markdown": {
"title": "[Firing] HighCPUUsage",
"text": "### ⚠️ CPU > 80%\n..."
},
"timestamp": "1717060800000",
"sign": "<Base64-HMAC-SHA256>"
}
安全设置选项对比:
| 安全方式 | 配置复杂度 | 安全性 | 说明 |
|---|---|---|---|
| 自定义关键词 | 低 | 低 | 消息必须含指定关键词 |
| 加签(HMAC) | 中 | 高 | 本次使用,防伪造 |
| IP 白名单 | 中 | 中 | 限制来源 IP |
5. Systemd Unit —— 服务管理配置
5.1 prometheus-webhook-dingtalk.service
文件路径: /etc/systemd/system/prometheus-webhook-dingtalk.service
[Unit]
Description=Prometheus Webhook DingTalk
Documentation=https://github.com/timonwong/prometheus-webhook-dingtalk
After=network.target
[Service]
Type=simple
User=root
ExecStart=/opt/prometheus-webhook-dingtalk/prometheus-webhook-dingtalk \
--config.file=/opt/prometheus-webhook-dingtalk/config.yml \
--web.listen-address=:8060
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
| 参数 | 区块 | 含义 |
|---|---|---|
Description |
[Unit] | 服务描述。systemctl status 时显示。 |
Documentation |
[Unit] | 文档链接。指向项目 GitHub 仓库。 |
After |
[Unit] | 启动顺序。在此目标之后启动。network.target 确保网络就绪。 |
Type |
[Service] | 启动类型。simple:默认,systemd 认为 ExecStart 启动的进程就是主进程。适用于不会 fork 的前台进程。 |
User |
[Service] | 运行用户。root:以 root 权限运行。生产环境建议改为专用用户。 |
ExecStart |
[Service] | 启动命令。\ 换行符仅为可读性,实际是单行命令。 |
--config.file |
(程序参数) | 指定配置文件路径。 |
--web.listen-address |
(程序参数) | 监听地址和端口。:8060 表示监听所有接口的 8060 端口。 |
Restart |
[Service] | 重启策略。always:无论退出码如何,总是重启。 |
RestartSec |
[Service] | 重启延迟。5 秒后重启,防止频繁崩溃循环。 |
WantedBy |
[Install] | 安装目标。multi-user.target:多用户模式(正常运行级别)。systemctl enable 后在此目标下创建符号链接。 |
5.2 Systemd 指令参考
| 指令 | 区块 | 可选值 | 说明 |
|---|---|---|---|
Type |
[Service] | simple / forking / oneshot / notify |
进程启动类型 |
Restart |
[Service] | no / always / on-failure / on-abnormal |
重启策略 |
RestartSec |
[Service] | 秒数 | 重启前等待时间 |
User / Group |
[Service] | 用户名 / 组名 | 运行身份 |
WorkingDirectory |
[Service] | 路径 | 工作目录 |
Environment |
[Service] | KEY=VALUE |
环境变量 |
StandardOutput |
[Service] | journal / null / file:path |
标准输出重定向 |
StandardError |
[Service] | 同上 | 标准错误重定向 |
LimitNOFILE |
[Service] | 数字 | 文件描述符上限 |
After / Before |
[Unit] | 目标名 | 启动顺序约束 |
Requires / Wants |
[Unit] | 目标名 | 启动依赖 |
WantedBy |
[Install] | 目标名 | enable 时的安装目标 |
APT 安装的服务(已自动配置):
Ubuntu APT 安装的 Prometheus、Alertmanager、Node Exporter、Grafana 的 systemd unit 由包管理器自动生成,无需手写:
prometheus.serviceprometheus-alertmanager.serviceprometheus-node-exporter.servicegrafana-server.service
只有手动安装的 prometheus-webhook-dingtalk 需要自行编写 unit 文件。
6. Grafana Dashboard JSON —— 仪表盘结构详解
文件路径: D:\tools\grafana_dashboard_node_exporter.json
6.1 顶层属性
{
"dashboard": {
"title": "服务器监控仪表盘",
"uid": "node-exporter-full",
"editable": true,
"schemaVersion": 39,
"version": 1,
"timezone": "browser",
"refresh": "30s",
"time": { "from": "now-1h", "to": "now" },
"tags": ["node-exporter", "prometheus"],
"panels": [...],
"templating": { "list": [] }
},
"overwrite": true,
"folderUid": "",
"message": "服务器监控仪表盘 - 包含CPU/内存/磁盘/网络/负载"
}
| 参数 | 类型 | 含义 |
|---|---|---|
dashboard.title |
string | 仪表盘标题。显示在 Grafana UI 顶部和面包屑导航。 |
dashboard.uid |
string | 唯一标识符。用于 API 访问和 URL 直链:/d/<uid>。必须唯一,重复导入会覆盖旧版。 |
dashboard.editable |
bool | 是否可编辑。true 允许通过 UI 修改面板。 |
dashboard.schemaVersion |
int | Schema 版本号。Grafana 各版本 JSON 格式不兼容。v13 使用 39。如果用 v39 导入 v38 的旧格式,Grafana 会自动迁移。 |
dashboard.version |
int | 仪表盘版本号。每次保存自动 +1。 |
dashboard.timezone |
string | 时区。"browser":使用用户浏览器时区;"utc":统一 UTC。 |
dashboard.refresh |
string | 自动刷新间隔。"30s":每 30 秒刷新数据。可选:"5s"、"1m"、"5m" 等。空字符串 = 不自动刷新。 |
dashboard.time.from |
string | 默认时间范围的起点。"now-1h":最近 1 小时。"now-6h"、"now-7d" 等。 |
dashboard.time.to |
string | 默认时间范围的终点。"now":当前时刻。 |
dashboard.tags |
array | 标签。用于 Grafana 搜索和分类。 |
dashboard.templating.list |
array | 模板变量列表。本次为空——无变量。K8s 场景通常定义 $namespace、$pod 等变量。 |
overwrite |
bool | 导入策略。true:如果已存在同 UID 仪表盘,覆盖它。 |
folderUid |
string | 所属文件夹 UID。空 = 根目录(General)。 |
message |
string | 版本变更说明。保存时显示在版本历史中。 |
6.2 row 面板
{
"id": 1,
"type": "row",
"title": "节点概览",
"collapsed": false,
"gridPos": { "h": 1, "w": 24, "x": 0, "y": 0 }
}
| 参数 | 含义 |
|---|---|
type: "row" |
面板类型:行。纯布局元素,不包含数据查询。用于对面板分组和折叠。 |
collapsed: false |
是否折叠。false = 展开显示子面板;true = 折叠仅显示行标题。 |
gridPos.h: 1 |
行高。row 的高度固定为 1(不占用数据空间)。 |
6.3 stat 面板
以"在线节点数"面板为例:
{
"id": 2,
"type": "stat",
"title": "在线节点数",
"gridPos": { "h": 4, "w": 6, "x": 0, "y": 1 },
"targets": [
{
"expr": "count(up{job=\"node\"} == 1)",
"refId": "A",
"format": "time_series",
"instant": true
}
],
"options": {
"reduceOptions": { "values": false, "calcs": ["lastNotNull"] },
"textMode": "value",
"colorMode": "background",
"graphMode": "none"
},
"fieldConfig": {
"defaults": {
"color": { "mode": "thresholds" },
"thresholds": {
"mode": "absolute",
"steps": [
{ "color": "red", "value": null },
{ "color": "green", "value": 4 }
]
},
"mappings": [],
"unit": "short"
}
}
}
| 参数 | 可选值 | 含义 |
|---|---|---|
type |
"stat" |
Single Stat 面板。显示单个大数字。 |
targets[].expr |
PromQL | 查询表达式。count(up{job="node"} == 1) = 在线节点数。 |
targets[].instant |
bool | 即时查询。true 只取最新值;false 取时间范围数据(用于 sparkline)。 |
targets[].refId |
string | 引用 ID。A/B/C… 用于多查询场景区分。 |
targets[].format |
string | 数据格式。"time_series" 是标准格式。 |
options.reduceOptions.calcs |
array | 聚合计算。["lastNotNull"]:取最后一个非空值。还可选:mean、max、min、sum。 |
options.reduceOptions.values |
bool | 是否显示每个系列的值。false:聚合为单个值。 |
options.textMode |
string | 文本显示模式。"value":只显示数字;"value_and_name":值+系列名;"name":只显示名称。 |
options.colorMode |
string | 颜色模式。"background":填充背景色;"value":仅文字着色;"none":不着色。 |
options.graphMode |
string | 迷你图模式。"none":不显示 sparkline;"area":面积图。 |
fieldConfig.defaults.unit |
string | 单位。"short":自动缩写(K/M/G);"percent":百分比;"s":秒;"Mbps":兆比特每秒。 |
fieldConfig.defaults.color.mode |
string | 着色策略。"thresholds":按阈值着色;"palette-classic":按系列分配颜色;"fixed":固定颜色。 |
fieldConfig.defaults.thresholds.mode |
string | 阈值模式。"absolute":绝对值;"percentage":百分比(0-1 范围)。 |
fieldConfig.defaults.thresholds.steps |
array | 阈值阶梯。每个 step 定义 color + value。value: null = 无穷小。 |
阈值 steps 解读(在线节点数):
"steps": [
{ "color": "red", "value": null }, // value < 4 → 红色(有节点离线)
{ "color": "green", "value": 4 } // value >= 4 → 绿色(全部在线)
]
阈值 steps 解读(告警数量):
"steps": [
{ "color": "green", "value": null }, // value < 1 → 绿色(无告警)
{ "color": "yellow", "value": 1 }, // value 1-2 → 黄色(少量告警)
{ "color": "red", "value": 3 } // value >= 3 → 红色(多个告警)
]
6.4 timeseries 面板
以"CPU 使用率"面板为例:
{
"id": 7,
"type": "timeseries",
"title": "CPU 使用率 (%)",
"gridPos": { "h": 10, "w": 16, "x": 0, "y": 6 },
"targets": [
{
"expr": "100 - (avg by(instance) (rate(node_cpu_seconds_total{mode=\"idle\",job=\"node\"}[5m])) * 100)",
"legendFormat": "{{ instance }}",
"refId": "A"
}
],
"options": {
"legend": {
"displayMode": "table",
"placement": "right",
"calcs": ["mean", "max", "lastNotNull"]
},
"tooltip": { "mode": "multi" }
},
"fieldConfig": {
"defaults": {
"unit": "percent",
"min": 0,
"max": 100,
"color": { "mode": "palette-classic" },
"thresholds": {
"mode": "absolute",
"steps": [
{ "color": "green", "value": null },
{ "color": "yellow", "value": 60 },
{ "color": "red", "value": 80 }
]
}
}
}
}
| 参数 | 可选值 | 含义 |
|---|---|---|
type |
"timeseries" |
时间序列面板。折线图/面积图。Grafana 8+ 的新面板类型,替代旧的 graph。 |
targets[].legendFormat |
string | 图例格式。"{{ instance }}" 显示 instance label 的值。可用任何 label name。 |
options.legend.displayMode |
"list" / "table" / "hidden" |
图例展示模式。"table":表格样式(带统计列);"list":简单列表。 |
options.legend.placement |
"bottom" / "right" |
图例位置。 |
options.legend.calcs |
array | 图例统计计算。["mean", "max", "lastNotNull"]:平均值、最大值、最新值。 |
options.tooltip.mode |
"single" / "multi" / "hidden" |
提示框模式。"multi":显示 X 轴该点的所有系列值。 |
fieldConfig.defaults.min / max |
number | Y 轴范围。0 到 100:固定 0-100%。不设则 auto-scale。 |
fieldConfig.defaults.unit |
string | 单位。"percent":显示为 0-100%。 |
thresholds 与折线图: timeseries 面板的 thresholds 作用于背景区域——绿色/黄色/红色分带显示在图表背景上,直观区分正常/警告/危险区。
6.5 gauge 面板
{
"id": 8,
"type": "gauge",
"title": "CPU 使用率 (当前)",
"gridPos": { "h": 10, "w": 8, "x": 16, "y": 6 },
"targets": [
{
"expr": "100 - (avg by(instance) (rate(node_cpu_seconds_total{mode=\"idle\",job=\"node\"}[5m])) * 100)",
"legendFormat": "{{ instance }}",
"refId": "A",
"instant": true
}
],
"options": {
"reduceOptions": { "values": true, "calcs": ["lastNotNull"] },
"text": {},
"showThresholdLabels": true,
"showThresholdMarkers": true
},
"fieldConfig": {
"defaults": {
"unit": "percent",
"min": 0,
"max": 100,
"color": { "mode": "thresholds" },
"thresholds": {
"mode": "absolute",
"steps": [
{ "color": "green", "value": null },
{ "color": "yellow", "value": 60 },
{ "color": "red", "value": 80 }
]
}
}
}
}
| 参数 | 含义 |
|---|---|
type: "gauge" |
仪表盘面板。半圆形/圆形仪表,类似汽车时速表。 |
options.reduceOptions.values: true |
显示每个系列的值。true 为每个节点显示一个独立的仪表。 |
options.showThresholdLabels |
显示阈值标签。在仪表边缘标注 60、80 阈值。 |
options.showThresholdMarkers |
显示阈值标记。在仪表弧线上用颜色标记阈值位置。 |
6.6 thresholds 阈值配置
阈值的配置方式在 stat/timeseries/gauge 面板中完全一致:
"thresholds": {
"mode": "absolute", // "absolute" = 绝对值, "percentage" = 0-1 百分比
"steps": [
{ "color": "green", "value": null }, // -∞ 到 60
{ "color": "yellow", "value": 60 }, // 60 到 80
{ "color": "red", "value": 80 } // 80 到 +∞
]
}
阈值计算逻辑:
- 将
value排序(null 视为 -∞) - 从左到右匹配:值 < 第一个 value → 第一个颜色;值 < 第二个 value → 第二个颜色…
- 最后一个 step 的 color 用于所有 >= 该 value 的值
本次部署的阈值设计:
| 指标 | 绿色(正常) | 黄色(警告) | 红色(危险) | 对齐的告警规则 |
|---|---|---|---|---|
| CPU | 0-60% | 60-80% | 80-100% | HighCPUUsage > 80% |
| 内存 | 0-70% | 70-85% | 85-100% | HighMemoryUsage > 85% |
| 磁盘 | 0-70% | 70-85% | 85-100% | DiskSpaceLow < 10% |
| 在线节点 | = 4 | - | < 4 | InstanceDown |
| 告警数 | = 0 | 1-2 | ≥ 3 | - |
设计原则: Grafana 阈值与 Alertmanager 告警阈值完全对应。在 Grafana 看到黄色时,说明正在接近告警阈值;看到红色时对应告警已经或即将触发。
6.7 gridPos 网格布局
Grafana 使用 24 列栅格系统布局面板。每个面板通过 gridPos 定义位置和大小:
"gridPos": { "h": 4, "w": 6, "x": 0, "y": 1 }
| 参数 | 含义 |
|---|---|
x |
列起始位置(0-23)。24 列总宽。 |
y |
行起始位置(0-N)。面板顶部所在行。 |
w |
面板宽度(列数)。24 = 全宽。 |
h |
面板高度(行数)。row 类型固定为 1。 |
布局可视化:
0 6 12 18 24
行 0 ┌────────────────────────────────────────┐ ← Row "节点概览"
│ │ │ │ │
行 1 │ 在线节点 │ 告警数量 │ 采集目标 │ Prom运行 │ (y=1, h=4)
│ w=6 │ w=6 │ w=6 │ w=6 │
│ │ │ │ │
行 5 ├────────────────────────────────────────┤ ← Row "CPU 监控"
│ │ │ │
行 6 │ CPU 折线图 │ Gauge │ │ (y=6, h=10)
│ w=16 │ w=8 │ │
│ │ │ │
7. PromQL 表达式逐行解读
7.1 CPU 使用率
100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle",job="node"}[5m])) * 100)
| 步骤 | 函数/操作符 | 输入 | 输出 | 说明 |
|---|---|---|---|---|
| 1 | {mode="idle",job="node"} |
所有 CPU 指标 | idle CPU 秒数 | 标签过滤。只取 idle 模式和 node job。 |
| 2 | rate(...[5m]) |
累计 counter | 每秒 idle 速率 | 速率计算。5 分钟窗口的每秒增量。自动处理 counter 重置。 |
| 3 | avg by(instance) (...) |
每个 CPU 核的数据 | 每个节点的平均值 | 按节点聚合。多核 CPU 取平均。 |
| 4 | * 100 |
小数 | 百分比 | 单位转换。0.95 → 95(idle%)。 |
| 5 | 100 - ... |
idle% | usage% | 反算使用率。100 - 95 = 5%(实际使用)。 |
为什么用 avg by(instance) 而不是直接 avg?
avg(...) → 所有节点所有 CPU 核的平均值(一个值)
avg by(instance) → 每个节点一个平均值(4 个值)
我们想看的是"每个节点的 CPU",不是"整个集群的 CPU"。
7.2 内存使用率
(1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) * 100
| 步骤 | 操作 | 说明 |
|---|---|---|
| 1 | MemAvailable / MemTotal |
可用比例。如 2.9GB / 3.3GB = 0.88。 |
| 2 | 1 - ... |
使用比例。1 - 0.88 = 0.12。 |
| 3 | * 100 |
转百分比。12%。 |
| 4 | {job="node"} |
标签过滤(隐式,通过 job label 自动匹配)。 |
MemAvailable vs MemFree 的 Linux 内核视角:
/proc/meminfo 包含:
MemTotal: 总物理内存
MemFree: 完全空闲内存
Buffers: 块设备缓冲区
Cached: 页缓存
SReclaimable: 可回收的内核 slab
MemAvailable = MemFree + 可回收的 Buffers/Cached/SReclaimable
≈ 内核估算的"现在可分配的最大连续内存"
7.3 磁盘使用率
(1 - (
node_filesystem_avail_bytes{mountpoint="/",fstype!="rootfs"} /
node_filesystem_size_bytes{mountpoint="/",fstype!="rootfs"}
)) * 100
| 步骤 | 操作 | 说明 |
|---|---|---|
| 1 | mountpoint="/" |
过滤挂载点。只监控根分区。不监控 /boot、/var 等。 |
| 2 | fstype!="rootfs" |
排除伪文件系统。rootfs 是 initramfs 阶段的虚拟设备,不是真实磁盘。 |
| 3 | Avail / Size |
可用比例。 |
| 4 | 1 - ... |
使用比例。 |
| 5 | * 100 |
转百分比。 |
为什么排除 rootfs?
$ df -h
Filesystem Size Used Avail Use% Mounted on
/dev/vda1 40G 6.6G 33G 17% /
node_filesystem_* 指标会同时暴露 /dev/vda1(真实设备)和 rootfs(伪设备)的数据。两者挂载点都是 /。不加 fstype!="rootfs" 会产生重复序列,导致 Grafana 显示两条线。
7.4 网络速率
rate(node_network_receive_bytes_total{job="node",device!="lo"}[5m]) * 8 / 1000000
| 步骤 | 操作 | 说明 |
|---|---|---|
| 1 | device!="lo" |
排除回环接口。lo 是 127.0.0.1 的本地通信,不反映真实网络流量。 |
| 2 | rate(...[5m]) |
每秒字节数(bytes/s)。 |
| 3 | * 8 |
bytes → bits。1 byte = 8 bits。 |
| 4 | / 1000000 |
bits → Megabits。1 Mbps = 1,000,000 bits/s。 |
单位转换链: bytes/s → *8 → bits/s → /1,000,000 → Mbps
7.5 节点在线数 / 告警数 / 运行时间
# 在线节点数
count(up{job="node"} == 1)
# 活跃告警数
count(ALERTS{alertstate="firing"})
# Prometheus 运行时间 (秒)
time() - process_start_time_seconds{job="prometheus"}
# 节点运行时间 (秒)
time() - node_boot_time_seconds{job="node"}
| 表达式 | 函数 | 说明 |
|---|---|---|
count(up == 1) |
count() |
计数聚合。统计值为 1 的 up 序列数 = 在线节点数。 |
count(ALERTS{alertstate="firing"}) |
count() |
告警计数。ALERTS 是 Prometheus 内置的虚拟指标,每条 Firing 告警对应一条序列。 |
time() - process_start_time_seconds |
time() |
当前 Unix 时间戳。减去 Prometheus 进程启动时间 = 运行时长。 |
time() - node_boot_time_seconds |
time() |
节点 uptime。当前时间减去系统启动时间。 |
8. 参数速查总表
8.1 Prometheus 核心参数
| 配置文件 | 参数 | 当前值 | 作用 |
|---|---|---|---|
| prometheus.yml | global.scrape_interval |
15s |
全局指标采集间隔 |
| prometheus.yml | global.evaluation_interval |
15s |
告警规则评估间隔 |
| prometheus.yml | alerting.alertmanagers[].targets |
localhost:9093 |
Alertmanager 地址 |
| prometheus.yml | rule_files |
/etc/prometheus/rules/*.yml |
告警规则文件 glob |
| prometheus.yml | scrape_configs[].job_name |
prometheus / node |
Job 标识 |
| prometheus.yml | static_configs[].targets |
192.168.0.x:9100 |
采集目标地址 |
8.2 Alertmanager 核心参数
| 配置文件 | 参数 | 当前值 | 作用 |
|---|---|---|---|
| alertmanager.yml | global.resolve_timeout |
5m |
恢复通知延迟 |
| alertmanager.yml | route.receiver |
default |
默认接收器 |
| alertmanager.yml | route.group_by |
[alertname, instance] |
告警分组标签 |
| alertmanager.yml | route.group_wait |
30s |
首次聚合等待 |
| alertmanager.yml | route.group_interval |
5m |
后续告警最小间隔 |
| alertmanager.yml | route.repeat_interval |
4h |
重复告警间隔 |
| alertmanager.yml | receivers[].webhook_configs[].url |
localhost:8060/dingtalk/dingtalk/send |
Webhook 目标 |
| alertmanager.yml | receivers[].webhook_configs[].send_resolved |
true |
发送恢复通知 |
| alertmanager.yml | inhibit_rules[].source_matchers |
severity="critical" |
抑制源 |
| alertmanager.yml | inhibit_rules[].target_matchers |
severity="warning" |
抑制目标 |
| alertmanager.yml | inhibit_rules[].equal |
[alertname, instance] |
抑制等价标签 |
8.3 告警规则核心参数
| 配置文件 | 参数 | InstanceDown | HighCPUUsage | HighMemoryUsage | DiskSpaceLow |
|---|---|---|---|---|---|
| node_alerts.yml | for |
2m |
5m |
5m |
2m |
| node_alerts.yml | severity |
critical |
warning |
warning |
critical |
| node_alerts.yml | 阈值 | up==0 |
>80% |
>85% |
<10% |
8.4 webhook-dingtalk 核心参数
| 配置文件 | 参数 | 值 | 作用 |
|---|---|---|---|
| config.yml | targets.dingtalk.url |
https://oapi.dingtalk.com/robot/send?access_token=xxx |
钉钉 webhook 地址 |
| config.yml | targets.dingtalk.secret |
SECxxx |
HMAC-SHA256 加签密钥 |
| config.yml | web.listen-address |
:8060 |
监听地址 |
8.5 Grafana Dashboard 核心参数
| 参数 | 当前值 | 作用 |
|---|---|---|
dashboard.uid |
node-exporter-full |
仪表盘唯一 ID |
dashboard.refresh |
30s |
自动刷新间隔 |
dashboard.time.from |
now-1h |
默认显示 1 小时数据 |
dashboard.schemaVersion |
39 |
Grafana v13 兼容 |
| 面板数 | 22 |
6 Row + 16 数据面板 |
| 阈值模式 | absolute |
绝对值阈值 |
| 图例模式 | table (right) |
表格图例在右侧 |
附录:配置文件快速定位
| 文件 | 路径 | 所属组件 |
|---|---|---|
| prometheus.yml | /etc/prometheus/prometheus.yml |
Prometheus |
| alertmanager.yml | /etc/prometheus/alertmanager.yml |
Alertmanager |
| node_alerts.yml | /etc/prometheus/rules/node_alerts.yml |
Prometheus Rules |
| config.yml | /opt/prometheus-webhook-dingtalk/config.yml |
DingTalk Webhook |
| webhook-dingtalk.service | /etc/systemd/system/prometheus-webhook-dingtalk.service |
Systemd |
| grafana_dashboard.json | D:\tools\grafana_dashboard_node_exporter.json |
Grafana Dashboard |
版本记录:
- 2026-05-30 v1.0: 初始版本,覆盖 Prometheus 2.45.3 / Alertmanager 0.26.0 / Grafana 13.0.1 全部配置参数
- 含 6 个配置文件逐字段解释、7 组 PromQL 表达式拆解、参数速查总表
- 签发: @WorkBuddy
更多推荐


所有评论(0)