适合读者:刚接触 Prometheus,能看懂简单 YAML 和 HTTP 请求的初级运维人员。本文使用独立的本机练习实例,不修改已有监控系统;预期现象用于教学说明。

1. 看到 up=0,先确认它表达了什么
在 Prometheus 中,一个被抓取的服务端点称为 instance,一组同类目标通常归入一个 job。每次抓取会产生 up 等状态指标。
up=1 表示最近一次抓取成功;up=0 表示抓取失败。这个指标反映的是 Prometheus 到目标指标端点的抓取结果,不能直接证明某个网站的完整业务功能正常,也不能单凭 0 断言整台服务器宕机。定义见 Jobs and instances 官方说明。
还有第三种情况:查询结果为空。它可能意味着目标没有进入当前配置、标签条件不匹配、服务发现过滤了目标,或旧时间序列已失效。空结果和 0 需要分别处理。
2. 从 Targets 页开始,比先改告警规则直接
先打开当前 Prometheus 的 Targets 页面,通常为 /targets,找到出问题的目标,记录:
- 最终抓取 URL:协议、主机、端口、路径。
- 当前状态、最近抓取时间、最近错误。
- 最终的
job、instance等标签。 - 目标是否确实出现在当前生效配置中。
例如,配置预期访问 /metrics,实际 URL 却是 /;或者 exporter 开在 9100,目标写成 9101。这些都应先改抓取配置或目标服务,再讨论告警。
如果 Targets 里根本没有该目标,要转向“配置是否加载、服务发现和 relabel 是否保留了它”。下面的网络排查以目标已经存在为前提。
3. 按错误类型缩小范围
| 最近错误或现象 | 检查方向 |
|---|---|
connection refused |
地址、端口、监听及显式拒绝策略 |
context deadline exceeded |
网络路径、服务是否卡住、抓取超时设置 |
HTTP 404 |
metrics_path 或反向代理路由 |
HTTP 401/403 |
抓取身份、令牌、访问策略 |
| TLS 证书错误 | scheme、域名、证书链、信任配置 |
| 文本解析或 Content-Type 错误 | 是否返回合规指标,而非 HTML 页面 |
从 Prometheus 所在的机器或对应容器网络环境访问最终 URL:
curl --connect-timeout 3 --max-time 5 -i \
http://127.0.0.1:19100/metrics
这个地址对应后文实验。实际排查需要换成 Targets 中的最终 URL,并匹配它使用的认证和 TLS 条件。你在自己电脑上能访问,并不能证明 Prometheus 所在环境也能访问。
如果 Prometheus 运行在容器里,127.0.0.1 指向容器自身。exporter 在宿主机或另一个容器时,应使用该网络中可达的正确地址。
4. 实验准备:一个输出固定指标的小服务
本实验需要 Python 3,以及已经安装到 PATH 的 prometheus 和 promtool。二进制安装方式可参考 官方 First steps。练习端口使用 19090、19100,不与现有实例共用数据目录。
prometheus --version
promtool --version
mkdir -p "$HOME/prometheus-scrape-lab"
cd "$HOME/prometheus-scrape-lab"
使用编辑器保存 metrics-demo.py:
from http.server import BaseHTTPRequestHandler, HTTPServer
METRICS = (
"# HELP ops_demo_ready Readiness value for the learning demo.\n"
"# TYPE ops_demo_ready gauge\n"
"ops_demo_ready 1\n"
).encode("utf-8")
class Handler(BaseHTTPRequestHandler):
def do_GET(self):
if self.path != "/metrics":
self.send_error(404)
return
self.send_response(200)
self.send_header("Content-Type", "text/plain; version=0.0.4; charset=utf-8")
self.send_header("Content-Length", str(len(METRICS)))
self.end_headers()
self.wfile.write(METRICS)
HTTPServer(("127.0.0.1", 19100), Handler).serve_forever()
终端 A 运行它,并保持前台:
python3 "$HOME/prometheus-scrape-lab/metrics-demo.py"
这个服务只输出一个固定 gauge,用于练习抓取链路;它不是主机性能 exporter。指标的 Content-Type 和文本格式应符合 Prometheus 支持的 exposition formats。
5. 故意写错目标端口,观察 up=0
使用编辑器保存 ~/prometheus-scrape-lab/prometheus.yml:
global:
scrape_interval: 5s
scrape_timeout: 3s
scrape_configs:
- job_name: ops-demo
metrics_path: /metrics
static_configs:
- targets: ['127.0.0.1:19101']
注意目标写成了 19101,而小服务实际监听 19100。确认 19101 没有其他服务,再检查配置:
promtool check config "$HOME/prometheus-scrape-lab/prometheus.yml"
预期配置检查可以通过,因为“端口写成另一个合法数字”并不是 YAML 或配置语义错误。promtool check config 不会替你证明该端点可连接并成功抓取。检查命令的用途见 promtool 文档。
终端 B 启动单独的 Prometheus:
prometheus \
--config.file="$HOME/prometheus-scrape-lab/prometheus.yml" \
--storage.tsdb.path="$HOME/prometheus-scrape-lab/data" \
--web.listen-address=127.0.0.1:19090
在本机访问 http://127.0.0.1:19090/targets。等待至少一次抓取后,预期看到目标失败,以及拒绝连接等错误。如果 19101 恰好有其他服务,现象可能不同,应以实际响应为准。
在查询界面输入下面的 PromQL,或通过查询 API 观察:
up{job="ops-demo", instance="127.0.0.1:19101"}
curl --max-time 5 --get \
--data-urlencode 'query=up{job="ops-demo",instance="127.0.0.1:19101"}' \
http://127.0.0.1:19090/api/v1/query
预期该时间序列的值为 0。这里已经有完整证据:目标配置存在,但最终抓取端口与服务监听端口不同。
6. 修正一处配置,再验证两个指标
把目标列表改成实际端口:
global:
scrape_interval: 5s
scrape_timeout: 3s
scrape_configs:
- job_name: ops-demo
metrics_path: /metrics
static_configs:
- targets: ['127.0.0.1:19100']
先检查配置,再在终端 B 按 Ctrl+C 停止练习实例,使用原命令和同一个练习数据目录重新启动。这里只重启自己的实验实例;真实监控服务应使用既有的配置发布与重载流程。Prometheus 的重载机制和参数见 配置文档。
等待数次抓取后,确认 Targets 中最终 URL 的端口是 19100,最近错误消失,再查询:
up{job="ops-demo", instance="127.0.0.1:19100"}
ops_demo_ready{job="ops-demo", instance="127.0.0.1:19100"}
预期两者均为 1。前者证明抓取成功,后者证明预期的示例业务指标已被采集。
端口变化也改变了 instance 标签,因此这是新的时间序列;旧的失败目标还会出现在历史图中,之后按失效机制退出当前查询。不要把历史失败点误认为修复没有生效。
7. 怎样把抓取故障变成告警
链路确认无误后,可以考虑单独的规则示例:
groups:
- name: scrape-availability
rules:
- alert: OpsDemoScrapeFailed
expr: up{job="ops-demo"} == 0
for: 5m
labels:
severity: warning
annotations:
summary: '抓取失败:{{ $labels.instance }}'
description: 'ops-demo 的该目标已连续 5 分钟抓取失败,请检查 Targets 最近错误。'
规则文件需要通过 rule_files 被 Prometheus 加载才会参与求值;可先用 promtool check rules 文件名 检查。for: 5m 表示同一个告警实例持续满足条件一段时间后进入 firing,不是每五分钟才检查一次。规则机制见 Alerting rules 官方说明。
这个表达式只捕获仍有 up 序列且值为 0 的目标。目标从配置或服务发现中消失,最终可能没有该序列,需要结合资产清单和缺失检测另行设计。Prometheus 告警进入 firing 后,还需正确配置 Alertmanager 等通知链路,才会发送到人。
8. 给下一次值班留下能直接使用的步骤
先在 Targets 确认目标存在,再读最近错误;从 Prometheus 的实际运行环境测试相同 URL;按端口、路径、认证、TLS、响应格式定位;修复后同时验证 up 和预期指标。
实验结束后,在两个前台终端分别按 Ctrl+C 停止小服务和练习 Prometheus。保留练习数据不会影响现有实例,也不需要清空监控数据来验证抓取是否恢复。