适用场景
本文适用于 Prometheus 已经配置了 scrape_configs,但在 Targets 页面看到目标实例显示 DOWN,或者 PromQL 查询 up{job="xxx"} == 0 的场景。常见对象包括 node_exporter、应用自暴露的 /metrics、Kubernetes ServiceMonitor、Nginx/Redis/MySQL exporter 等。
这类问题的核心不是“指标是否正常”,而是 Prometheus 到目标端点的抓取链路是否打通。排查时要按链路拆开看:服务发现是否发现目标、网络是否可达、HTTP 响应是否正确、鉴权和 TLS 是否匹配、抓取超时和指标体积是否合理。
现象描述
典型现象包括:
- Prometheus Web UI 的
Status -> Targets中实例状态为DOWN。 - 查询
up{job="node"}返回0。 - Alerts 中出现
InstanceDown、TargetDown或自定义抓取失败告警。 - Grafana 面板突然断点,很多指标显示
No data。 - Prometheus 日志中出现
context deadline exceeded、connection refused、server returned HTTP status 401、x509: certificate signed by unknown authority等错误。
up 是 Prometheus 每次抓取自动生成的指标:
up{job="node", instance="10.0.1.12:9100"}
返回值含义:
1:本轮抓取成功。0:目标被发现了,但本轮抓取失败。- 没有序列:目标没有被发现,或者标签条件写错。
因此,先确认是 up=0 还是根本没有 up 序列,这一步能避免把服务发现问题误判成网络问题。
可能原因
常见原因可以分成几类:
- 目标进程未启动,端口没有监听。
- Prometheus 到目标端口的网络不通,例如安全组、防火墙、NetworkPolicy、路由问题。
metrics_path、scheme、端口或服务发现标签配置错误。- 目标端返回非 2xx 状态码,例如 401、403、404、500。
- TLS 证书、SNI、CA、客户端证书配置不匹配。
- 指标接口太慢或指标量太大,超过
scrape_timeout。 - exporter 本身卡住,例如采集磁盘、数据库、外部 API 时阻塞。
- Kubernetes 场景中 Service、Endpoints、Pod label、ServiceMonitor selector 不匹配。
排查思路
1. 先看 Targets 页面给出的错误
Prometheus 的 Targets 页面通常会直接给出最近一次错误,优先看以下字段:
State:目标状态,UP或DOWN。Endpoint:Prometheus 实际抓取的 URL。Last Scrape:最近抓取时间。Scrape Duration:本次抓取耗时。Error:失败原因。
也可以通过 PromQL 快速列出失败目标:
up == 0
如果只想看某个 job:
up{job="node"} == 0
如果目标没有任何 up 序列,说明它可能没有被 Prometheus 发现。此时应转去检查 scrape_configs、服务发现、ServiceMonitor 或 relabel 规则。
2. 在 Prometheus 机器上验证端口连通
不要只在自己的电脑上 curl 目标地址,要在 Prometheus 所在机器或 Pod 内验证,因为网络路径不同。
Linux 主机部署时:
nc -vz 10.0.1.12 9100
curl -v --max-time 5 http://10.0.1.12:9100/metrics
Kubernetes 部署时:
kubectl -n monitoring exec -it deploy/prometheus-server -- sh
进入容器后再测试:
wget -S -O- --timeout=5 http://node-exporter.monitoring.svc:9100/metrics
重点看三类结果:
connection refused:IP 可达但端口没有监听,优先查目标进程。connection timed out:网络链路不通,优先查防火墙、安全组、NetworkPolicy、路由。- HTTP 返回 401、403、404、500:网络已通,继续查路径、鉴权或目标服务。
3. 检查目标端口是否监听
在目标机器上执行:
ss -lntp | grep ':9100'
systemctl status node_exporter --no-pager
journalctl -u node_exporter -n 80 --no-pager
关键字段:
LISTEN后面的本地地址如果是127.0.0.1:9100,说明只监听本机,远端 Prometheus 无法访问。0.0.0.0:9100或指定内网 IP 通常才适合被 Prometheus 抓取。journalctl中如果有权限错误、collector 初始化失败、端口占用,需要先修复 exporter。
如果进程只监听本机地址,应调整启动参数。例如 node_exporter:
--web.listen-address=:9100
修改 systemd 后需要重载并重启:
systemctl daemon-reload
systemctl restart node_exporter
systemctl status node_exporter --no-pager
4. 核对 Prometheus 抓取配置
静态配置示例:
scrape_configs:
- job_name: node
scrape_interval: 30s
scrape_timeout: 10s
metrics_path: /metrics
scheme: http
static_configs:
- targets:
- 10.0.1.12:9100
- 10.0.1.13:9100
检查点:
targets必须包含端口,不能只写 IP。metrics_path要和应用实际暴露路径一致。scheme要区分http和https。scrape_timeout必须小于或等于scrape_interval。- 修改配置后要 reload Prometheus,而不是只改文件。
校验配置文件:
promtool check config /etc/prometheus/prometheus.yml
重载配置:
curl -X POST http://127.0.0.1:9090/-/reload
如果没有开启 lifecycle API,则需要重启 Prometheus:
systemctl restart prometheus
5. 处理 HTTP 状态码错误
如果 Targets 页面显示 server returned HTTP status 404,通常是路径错误:
curl -i http://10.0.1.12:8080/metrics
curl -i http://10.0.1.12:8080/actuator/prometheus
很多 Spring Boot 应用的 Prometheus 指标路径是:
/actuator/prometheus
对应配置应写成:
scrape_configs:
- job_name: spring-app
metrics_path: /actuator/prometheus
static_configs:
- targets:
- 10.0.2.21:8080
如果返回 401 或 403,说明目标端需要鉴权。Basic Auth 示例:
scrape_configs:
- job_name: secure-app
metrics_path: /metrics
static_configs:
- targets:
- 10.0.2.22:8080
basic_auth:
username: prometheus
password_file: /etc/prometheus/secrets/metrics_password
不要把密码直接写进 Git 仓库。生产环境建议使用 password_file、Kubernetes Secret 或配置管理系统下发。
6. 处理 TLS 证书错误
如果错误里有 x509,说明 TLS 校验失败。先确认目标证书:
openssl s_client -connect metrics.example.com:443 -servername metrics.example.com </dev/null
Prometheus 配置可以指定 CA:
scrape_configs:
- job_name: https-app
scheme: https
static_configs:
- targets:
- metrics.example.com:443
tls_config:
ca_file: /etc/prometheus/certs/ca.pem
server_name: metrics.example.com
临时排查可以使用:
tls_config:
insecure_skip_verify: true
但这只能作为短期验证手段,不建议长期使用。正式修复应补齐可信 CA、正确的证书链和匹配的 SNI。
7. 判断是否抓取超时
如果错误是 context deadline exceeded,先看抓取耗时和样本数量:
scrape_duration_seconds{job="app"}
scrape_samples_scraped{job="app"}
也可以看最近失败原因:
scrape_timeout_seconds{job="app"}
处理思路:
- 如果接口偶尔慢,检查应用或 exporter 是否在抓取时访问慢资源。
- 如果指标量突然增大,检查是否出现高基数标签,例如
user_id、request_id、订单号。 - 如果确实需要更长时间,适当提高
scrape_timeout和scrape_interval,但不要把超时简单拉到很大。
示例配置:
scrape_configs:
- job_name: heavy-exporter
scrape_interval: 60s
scrape_timeout: 20s
static_configs:
- targets:
- 10.0.3.30:9200
如果 scrape_samples_scraped 持续异常增长,应优先减少指标基数,而不是只增加 Prometheus 资源。
Kubernetes 场景定位示例
假设 ServiceMonitor 创建后,Prometheus 没有抓到目标。
先看 Service 是否有 Endpoints:
kubectl -n app get svc my-app
kubectl -n app get endpoints my-app -o wide
如果 Endpoints 为空,说明 Service selector 没有匹配到 Pod:
kubectl -n app get svc my-app -o yaml
kubectl -n app get pod --show-labels
检查 ServiceMonitor selector:
kubectl -n monitoring get servicemonitor my-app -o yaml
重点看:
spec.selector.matchLabels是否匹配 Service 标签。spec.namespaceSelector是否包含业务命名空间。spec.endpoints[].port是否写的是 Service port 的名称,而不是端口数字。
Service 示例:
apiVersion: v1
kind: Service
metadata:
name: my-app
namespace: app
labels:
app: my-app
spec:
selector:
app: my-app
ports:
- name: metrics
port: 8080
targetPort: 8080
ServiceMonitor 示例:
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: my-app
namespace: monitoring
spec:
namespaceSelector:
matchNames:
- app
selector:
matchLabels:
app: my-app
endpoints:
- port: metrics
path: /metrics
interval: 30s
这里的 port: metrics 必须对应 Service 里的端口名称 name: metrics。
修复方案
根据错误类型选择修复动作:
- 端口未监听:启动 exporter 或修复 systemd 配置。
- 只监听
127.0.0.1:改为监听内网地址或0.0.0.0。 - 网络超时:放通安全组、防火墙、NetworkPolicy 或修复路由。
- 404:修正
metrics_path。 - 401/403:配置 Basic Auth、Bearer Token 或目标端白名单。
- TLS 报错:补齐 CA、证书链、SNI 或客户端证书。
- 抓取超时:优化 exporter、降低指标基数,必要时调整抓取间隔和超时。
- Kubernetes 未发现目标:修正 Service selector、ServiceMonitor selector、命名空间选择器和端口名称。
修复后用三步确认:
up{job="目标job"}
scrape_duration_seconds{job="目标job"}
scrape_samples_scraped{job="目标job"}
确认 up 变成 1,抓取耗时低于 scrape_timeout,样本数量稳定,没有明显突增。
预防措施
- 为所有关键 job 配置
up == 0告警,并设置合理的for时间,避免短暂重启造成误报。 - 对
scrape_duration_seconds / scrape_timeout_seconds配置接近超时告警,提前发现抓取变慢。 - 对
scrape_samples_scraped建立基线,发现指标量异常增长及时处理。 - 应用发布时把
/metrics纳入健康检查清单,确认路径、鉴权和 TLS 配置。 - Kubernetes 中统一 Service 端口命名,例如固定使用
metrics,减少 ServiceMonitor 配置错误。 - 不要在指标标签里放用户 ID、请求 ID、订单号等高基数字段。
- Prometheus 配置变更前执行
promtool check config,避免配置错误导致整段抓取失效。
总结
up=0 的排查要先判断目标是否被发现,再沿着 Prometheus 到目标端点的链路逐层确认。Targets 页面里的错误信息通常已经指出方向:拒绝连接查进程和监听地址,超时查网络链路,404 查路径,401/403 查鉴权,x509 查证书,deadline exceeded 查耗时和指标量。
处理这类问题不要一开始就改告警规则或扩大超时时间。正确做法是先恢复抓取链路,再评估是否需要优化 exporter、收敛指标基数、调整抓取周期和补充预防性告警。
Discussion
评论