5月27日 17:40

Prometheus 故障排查怎么做?7 类常见问题逐个击破

Prometheus 线上跑着跑着突然 OOM 崩了,告警静悄悄没触发,采集数据大面积缺失——这些问题你可能都遇到过。下面按照实际排障频率,从最常见到最棘手,逐一拆解。

Prometheus 无法启动

启动失败通常是配置错误或资源冲突,按以下顺序排查:

第一步:检查配置文件语法

bash
promtool check config /etc/prometheus/prometheus.yml

promtool 是 Prometheus 自带的诊断工具,它会逐行解析配置并报出具体的行号和错误原因。常见的配置错误包括 YAML 缩进不一致、scrape_interval 写成了字符串而非 duration 格式、以及 relabel_configs 中引用了不存在的标签。

第二步:检查端口占用

bash
lsof -i :9090 ss -tlnp | grep 9090

9090 端口被其他进程占用是部署时的高频问题,尤其是在容器环境中未正确配置网络命名空间时。如果端口被占用,可以修改 --web.listen-address 参数指定其他端口。

第三步:查看服务日志

bash
journalctl -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 查询:

promql
up{job="your-job"}

up == 1 表示正常,up == 0 表示采集失败。结合 scrape_samples_scraped 可以判断是否采集到了数据但数据为空。

排查网络连通性

bash
curl -v http://target:port/metrics

重点关注:

  • 连接超时:防火墙规则或安全组未放通
  • 403/401:认证配置不匹配
  • 404:metrics 路径不是默认的 /metrics,需要在 job 配置中指定 metrics_path
  • SSL 错误:证书过期或自签名证书未在 Prometheus 侧配置 tls_config

检查认证配置

yaml
scrape_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 面板加载超时,这是数据量增长后的典型问题。

优化查询语句的原则

  1. 用标签过滤缩小范围,避免全量扫描:http_requests_total{job="api",method="GET"} 远优于 http_requests_total
  2. 控制时间范围,尤其是 rate()histogram_quantile() 这类聚合函数,范围越大计算量指数级增长
  3. 避免 oron 的复杂联合查询,拆分成多个简单查询分别执行

用 Recording Rules 预计算

将高频查询的中间结果提前算好,查询时直接读预计算结果:

yaml
groups: - 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.timeretention.size,以先达到的阈值为准。这在磁盘空间有限的环境中尤为重要。

过滤不必要的指标

在数据源头过滤掉不需要的指标,比事后查询时过滤高效得多:

yaml
scrape_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 持续增长且接近历史峰值时,就要提前扩容或裁剪指标了。

磁盘空间不足

磁盘问题通常和内存问题相伴出现——数据量大,内存压力大,磁盘也容易满。

检查数据目录大小

bash
du -sh /var/lib/prometheus/ du -sh /var/lib/prometheus/chunks_head/ ls -lhS /var/lib/prometheus/

chunks_head/ 是写入最频繁的目录,通常也是增长最快的。如果 wal/ 目录异常大,说明 Head Compaction 没有正常执行。

配置保留策略

yaml
storage: 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 备份再清理。

告警不触发

告警配置了却没触发,这是最危险的情况——你以为系统正常,其实只是监控系统本身出了问题。

检查告警规则语法

bash
promtool 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

容易被忽略的原因:路由配置中 matchmatch_re 写错导致告警被丢弃;静默规则覆盖了预期告警;inhibit_rules 抑制了低级别告警。

TSDB 损坏

TSDB 损坏通常发生在异常断电、磁盘故障或 OOM Kill 之后。

诊断 TSDB 状态

bash
promtool tsdb analyze /var/lib/prometheus/

输出包含:序列数、标签数、数据块数量。如果某个数据块目录为空或索引文件缺失,说明该块已损坏。

修复 TSDB

bash
promtool 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 中重命名或丢弃过长标签

日常运维检查清单

将以下检查项纳入日常巡检,可以在问题影响业务前提前发现:

  1. 监控 Prometheus 自身:用另一个 Prometheus 实例或 Thanos Sidecar 监控主实例的 up 指标和资源使用率
  2. 配置变更审计:每次修改配置前用 promtool check 验证,修改后确认 Target 状态正常
  3. 磁盘和内存容量规划:设置 process_resident_memory_bytes 和磁盘使用率的告警阈值在 80%
  4. 告警可用性验证:定期发送测试告警(amtool alert add)确认通知链路畅通
  5. 数据完整性校验:每周执行一次 promtool tsdb analyze,关注异常增长或衰减的序列数
  6. 备份验证:备份不仅要做,还要定期从备份恢复到测试环境,确认数据可用
标签:Prometheus