Administrator
Administrator
发布于 2026-10-29 / 0 阅读
0
0

Prometheus 的 up=0 怎么查:从 Targets 到一次可验证的抓取修复

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

Prometheus 抓取排查:目标存在、请求地址、连接、响应格式、查询验证

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。保留练习数据不会影响现有实例,也不需要清空监控数据来验证抓取是否恢复。


评论