Prometheus 故障排查怎么做?7 类常见问题逐个击破
Prometheus 线上跑着跑着突然 OOM 崩了,告警静悄悄没触发,采集数据大面积缺失——这些问题你可能都遇到过。下面按照实际排障频率,从最常见到最棘手,逐一拆解。
Prometheus 无法启动
启动失败通常是配置错误或资源冲突,按以下顺序排查:
第一步:检查配置文件语法
bashpromtool check config /etc/prometheus/prometheus.yml
promtool 是 Prometheus 自带的诊断工具,它会逐行解析配置并报出具体的行号和错误原因。常见的配置错误包括 YAML 缩进不一致、scrape_interval 写成了字符串而非 duration 格式、以及 relabel_configs 中引用了不存在的标签。
第二步:检查端口占用
bashlsof -i :9090 ss -tlnp | grep 9090
9090 端口被其他进程占用是部署时的高频问题,尤其是在容器环境中未正确配置网络命名空间时。如果端口被占用,可以修改 --web.listen-address 参数指定其他端口。
第三步:查看服务日志
bashjournalctl -u prometheus -f --no-pager -n 200
日志中常见的关键错误信息:
cannot load TSDB:TSDB 数据目录损坏或权限不足cannot create directory:数据目录权限问题,检查 Prometheus 进程的运行用户是否对数据目录有写权限cannot initialize notification queue:Alertmanager 地址不可达
数据采集失败(Target Down)
采集失败是日常运维中最频繁遇到的问题,核心排查思路是确认"Prometheus 能否访问到 Target 的 /metrics 端点"。
确认 Target 状态
在 Prometheus Web UI 的 /targets 页面可以看到每个 Target 的健康状态和最后错误信息。也可以用 PromQL 查询:
promqlup{job="your-job"}
up == 1 表示正常,up == 0 表示采集失败。结合 scrape_samples_scraped 可以判断是否采集到了数据但数据为空。
排查网络连通性
bashcurl -v http://target:port/metrics
重点关注:
- 连接超时:防火墙规则或安全组未放通
- 403/401:认证配置不匹配
- 404:metrics 路径不是默认的 /metrics,需要在 job 配置中指定
metrics_path - SSL 错误:证书过期或自签名证书未在 Prometheus 侧配置
tls_config
检查认证配置
yamlscrape_configs: - job_name: 'secure-app' basic_auth: username: admin password: <secret> tls_config: ca_file: /etc/prometheus/certs/ca.crt insecure_skip_verify: false bearer_token: <secret>
认证问题容易被忽略的细节:Bearer Token 过期后不会自动刷新,需要配合密钥管理工具轮转;insecure_skip_verify: true 虽然能解决证书校验失败,但不要在生产环境使用。
查询性能慢
复杂查询把 Prometheus UI 卡死,或者 Grafana 面板加载超时,这是数据量增长后的典型问题。
优化查询语句的原则
- 用标签过滤缩小范围,避免全量扫描:
http_requests_total{job="api",method="GET"}远优于http_requests_total - 控制时间范围,尤其是
rate()和histogram_quantile()这类聚合函数,范围越大计算量指数级增长 - 避免
or和on的复杂联合查询,拆分成多个简单查询分别执行
用 Recording Rules 预计算
将高频查询的中间结果提前算好,查询时直接读预计算结果:
yamlgroups: - name: api_performance interval: 30s rules: - record: job:http_requests:rate5m expr: sum by (job) (rate(http_requests_total[5m])) - record: job:http_requests:availability expr: | sum by (job) (rate(http_requests_total{code=~"2.."}[5m])) / sum by (job) (rate(http_requests_total[5m]))
关键点:interval 要和查询的时间窗口匹配,太短浪费算力,太长数据延迟大。
监控查询自身的性能
promql# 查询耗时分布 histogram_quantile(0.9, rate(prometheus_engine_query_duration_seconds_bucket[5m])) # 规则评估耗时 topk(10, prometheus_rule_evaluation_seconds)
如果发现某条规则评估耗时持续偏高,说明这条规则的表达式需要优化或者拆分。
内存使用过高
Prometheus 内存占用与活跃时间序列数量直接相关。一条经验值:每百万活跃序列大约需要 3-4 GB 内存。
调整数据保留时间
yaml# 启动参数方式 --storage.tsdb.retention.time=15d # 配置文件方式(Prometheus 2.40+) storage: tsdb: retention.time: 15d retention.size: 50GB
同时设置 retention.time 和 retention.size,以先达到的阈值为准。这在磁盘空间有限的环境中尤为重要。
过滤不必要的指标
在数据源头过滤掉不需要的指标,比事后查询时过滤高效得多:
yamlscrape_configs: - job_name: 'app' metric_relabel_configs: - source_labels: [__name__] regex: 'go_.*' action: drop - source_labels: [__name__] regex: 'http_requests_.*' action: keep
action: drop 在前,action: keep 在后——先排除无用指标,再保留需要的,减少处理量。还可以用 labeldrop 去掉高基数标签来降低序列数。
监控内存指标
promql# 进程实际内存占用 process_resident_memory_bytes # 活跃时间序列数——内存的核心驱动因素 prometheus_tsdb_head_series # Head GC 耗时,频繁 GC 说明内存压力大 rate(prometheus_tsdb_head_gc_duration_seconds_sum[5m])
当 prometheus_tsdb_head_series 持续增长且接近历史峰值时,就要提前扩容或裁剪指标了。
磁盘空间不足
磁盘问题通常和内存问题相伴出现——数据量大,内存压力大,磁盘也容易满。
检查数据目录大小
bashdu -sh /var/lib/prometheus/ du -sh /var/lib/prometheus/chunks_head/ ls -lhS /var/lib/prometheus/
chunks_head/ 是写入最频繁的目录,通常也是增长最快的。如果 wal/ 目录异常大,说明 Head Compaction 没有正常执行。
配置保留策略
yamlstorage: tsdb: retention.time: 15d retention.size: 50GB
当磁盘使用率超过 80% 时 Prometheus 会进入"节流模式",拒绝写入新数据。所以保留策略要留出安全余量。
清理指定时间段的旧数据
bash# 查看数据块信息 ls -la /var/lib/prometheus/ # 删除指定时间范围的数据块 promtool tsdb delete-blocks /var/lib/prometheus/ --min-time=1704067200000 --max-time=1704153600000
注意:delete-blocks 操作不可逆,执行前务必确认时间范围。生产环境建议先用 snapshot 备份再清理。
告警不触发
告警配置了却没触发,这是最危险的情况——你以为系统正常,其实只是监控系统本身出了问题。
检查告警规则语法
bashpromtool check rules /etc/prometheus/rules/*.yml
常见错误:for 持续时间设置过长(比如 for: 24h),导致短暂故障恢复后告警未触发;expr 中的标签选择器与实际指标标签不匹配。
检查告警状态
promql# 告警是否进入 Pending 或 Firing 状态 ALERTS{alertname="your-alert"} # 告警触发次数 ALERTS_FOR_STATE{alertname="your-alert"}
在 Prometheus UI 的 /alerts 页面可以直接看到每条规则的状态。如果状态一直是 Inactive,说明表达式条件从未满足;如果是 Pending 但不进入 Firing,检查 for 持续时间是否过长。
检查 Alertmanager 连接
promql# 告警通知队列积压 prometheus_notifications_queue_length # 告警发送失败次数 rate(prometheus_notifications_errors_total[5m]) # Alertmanager 连接状态 prometheus_notifications_alertmanagers_discovered
如果队列积压持续增长,说明 Alertmanager 处理速度跟不上,可能需要增加 Alertmanager 实例或检查下游通知渠道。
Alertmanager 侧排查
bash# 查看 Alertmanager 日志 journalctl -u alertmanager -f # 检查静默规则 amtool silence query --alertmanager.url=http://localhost:9093 # 检查路由配置 amtool config routes --alertmanager.url=http://localhost:9093
容易被忽略的原因:路由配置中 match 或 match_re 写错导致告警被丢弃;静默规则覆盖了预期告警;inhibit_rules 抑制了低级别告警。
TSDB 损坏
TSDB 损坏通常发生在异常断电、磁盘故障或 OOM Kill 之后。
诊断 TSDB 状态
bashpromtool tsdb analyze /var/lib/prometheus/
输出包含:序列数、标签数、数据块数量。如果某个数据块目录为空或索引文件缺失,说明该块已损坏。
修复 TSDB
bashpromtool tsdb repair /var/lib/prometheus/
repair 会尝试恢复损坏的索引和元数据文件,但不会恢复已丢失的原始数据。执行前建议先备份。
备份与恢复
bash# 创建快照(需要开启 --web.enable-admin-api) curl -XPOST http://localhost:9090/api/v1/admin/tsdb/snapshot # 备份到远程 rsync -avz /var/lib/prometheus/snapshots/ /backup/prometheus/ # 恢复数据——直接替换数据目录 systemctl stop prometheus rm -rf /var/lib/prometheus/ cp -r /backup/prometheus/latest/ /var/lib/prometheus/ chown -R prometheus:prometheus /var/lib/prometheus/ systemctl start prometheus
预防措施
bash# 定期检查 TSDB 完整性(加入 cron) 0 3 * * * promtool tsdb analyze /var/lib/prometheus/ >> /var/log/tsdb-health.log 2>&1
常见错误信息速查
| 错误信息 | 原因 | 处理方式 |
|---|---|---|
context deadline exceeded | 查询超过 query.timeout 限制 | 优化查询语句或增大超时时间 |
out of order sample | 同一序列中出现了时间戳更早的样本 | 检查是否有多个实例用相同标签写入同一条序列 |
duplicate series | 多个 Target 暴露了完全相同标签的序列 | 在 metric_relabel_configs 中添加唯一标识标签 |
too many samples | 单次采集的样本数超过 sample_limit | 增大 sample_limit 或过滤低价值指标 |
storage capacity exceeded | 磁盘空间不足 | 调整保留策略或扩容磁盘 |
label name too long | 标签名超过限制 | 在 metric_relabel_configs 中重命名或丢弃过长标签 |
日常运维检查清单
将以下检查项纳入日常巡检,可以在问题影响业务前提前发现:
- 监控 Prometheus 自身:用另一个 Prometheus 实例或 Thanos Sidecar 监控主实例的
up指标和资源使用率 - 配置变更审计:每次修改配置前用
promtool check验证,修改后确认 Target 状态正常 - 磁盘和内存容量规划:设置
process_resident_memory_bytes和磁盘使用率的告警阈值在 80% - 告警可用性验证:定期发送测试告警(
amtool alert add)确认通知链路畅通 - 数据完整性校验:每周执行一次
promtool tsdb analyze,关注异常增长或衰减的序列数 - 备份验证:备份不仅要做,还要定期从备份恢复到测试环境,确认数据可用