Prometheus+Grafana监控仪表盘搭建全攻略:从指标采集到告警通知

📅 发布时间:2026/9/29 1:41:51
Prometheus+Grafana监控仪表盘搭建全攻略:从指标采集到告警通知
先聊监控这件绕不开的事。做运维和开发的同学早晚都会面对同一个问题线上服务到底跑得怎么样CPU 是不是快满了内存有没有偷偷涨磁盘哪一天会写爆接口响应是不是开始变慢了。要是没有一套看得见的监控系统这些问题基本上全靠猜、靠用户反馈、靠大半夜被报警电话叫醒来发现。而 Prometheus 加 Grafana 这套组合是目前监控领域最主流、也最值得花时间搭起来的一套开源方案。Prometheus 负责采集和存储指标数据内置强大的 PromQL 查询语言和告警规则引擎Grafana 负责把数据画成直观的图表和可交互的仪表盘还能对接告警渠道。这两条工具链都是开源免费的组合在一起不需要花一分钱授权费就能搭出一个覆盖服务器、容器、数据库、中间件的监控平台。这篇文章就是围绕“Prometheus Grafana 搭建监控仪表盘”这个主题把从零到一的全过程捋一遍。我不会只丢一堆命令而是会把部署、配置、指标采集、仪表盘制作、告警接入到常见排坑都展开讲尽量把每一步“为什么这么做”背后的逻辑也说清楚。适合正在准备搭建监控的运维工程师、后端开发以及想把手头小项目监控起来的独立开发者。我从单机裸跑 Prometheus 开始一路玩到 Kubernetes 集群监控和 OpenTelemetry 指标接入中间踩过的坑不少。下面这些内容基本是我自己实操验证过、并且觉得值得写下来的经验。1. 先想清楚监控体系怎么设计再动手1.1 为什么这个时代绕不开 Prometheus 和 Grafana先回到一个基本问题监控系统的核心职责是什么无非三件事采集指标、存储指标、展示和告警。早期流行的 Zabbix 走的是“中心化采集”模型监控端主动去轮询设备和主机。这个模型的配置相当繁琐每加一台机器、一个监控项都要手动登记扩展性也一般。Prometheus 的设计思路完全反过来采用“拉取Pull”模型被监控对象只需要暴露一个 /metrics 接口Prometheus 服务端定期去抓取就行。这种设计的好处非常明显被监控对象职责单一不用关心告警和数据上报只要把运行状态暴露成指标即可。抓取频率、超时时间全部由服务端统一控制调参简单。天然适配 Kubernetes 这种动态变化的容器环境通过服务发现能自动找到新出现的 Pod。至于 Grafana它的角色更纯粹不负责采集和存储只专注做可视化。它支持几十种数据源包括 Prometheus、InfluxDB、MySQL、Elasticsearch、Loki 等所以一套 Grafana 里可以同时看时序指标、日志、业务库数据。这也是为什么绝大多数人都会把 Prometheus 和 Grafana 绑在一起用而不是用 Prometheus 自带的那个简陋图表界面。1.2 每层组件各管一段职责不要搞混一套完整的 Prometheus Grafana 监控体系从下到上大致分四层每一层的职责必须清晰否则排查问题时会一头雾水。层级组件职责数据采集Node Exporter、cAdvisor、mysqld_exporter、otel-collector 等把系统、容器、中间件、业务应用的运行状态转换成 Prometheus 格式指标存储与查询Prometheus Server定期拉取指标、本地落盘存储、执行 PromQL 查询、定期评估告警规则告警处理Alertmanager接收 Prometheus 推送的告警事件做分组、去重、路由发送到邮件、企业微信、钉钉、webhook可视化Grafana连接 Prometheus 数据源制作 Dashboard展示告警状态和变化趋势很多人会忽略数据采集这一层以为部署好 Prometheus 它就什么都能监控。其实 Prometheus 不会魔法般地知道你的机器有多少内存它需要靠 Exporter 去系统里把数据读出来。每类监控对象都有对应的 ExporterLinux 主机用 node_exporterMySQL 用 mysqld_exporterRedis 用 redis_exporter容器资源用 cAdvisor。业务自定义指标则需要自己在代码里埋点、暴露接口。如果是 Kubernetes 集群还有更高级的玩法通过 Prometheus Operator现在叫 kube-prometheus-stack把采集配置全部变成 CRD 对象动态发现 ServiceMonitor 和 PodMonitor自动采集集群里所有的标准指标。1.3 拉模型和推模型的取舍要提前想明白Prometheus 是标准的拉模型但实际业务里有些场景天然适合“推”。比如批处理任务、定时 Job跑完就退出Prometheus 还没来得及来拉进程已经没了指标自然采集不到。这类短生命周期任务的指标采集主流有两种解法。第一种是部署 Pushgateway任务结束时主动把指标推给一个长期运行的中间组件Prometheus 再从这个组件去拉。这种方式简单直接但 Pushgateway 本身是个单点而且如果多个任务往同一个指标名里推数据标签很容易互相污染指标只增不删用起来要非常小心。第二种是 OpenTelemetry Collector 作为数据网关业务侧通过 OTLP 协议把指标推给 CollectorCollector 再由 prometheus exporter 暴露一个 /metrics 端口让 Prometheus 来拉。网上很多人搜“Prometheus 是如何从 otel-collector 收取数据的”本质就是这个过程。Collector 在这条链路里起的是协议转换的作用Prometheus 看到的仍然是一个普通的 /metrics 端点。我的建议是短期临时用 Pushgateway 可以但如果团队有计划统一下一代可观测性体系直接一步到位用 OpenTelemetry 更明智后面的扩展空间大得多。2. 安装部署用 Docker Compose 三分钟跑通核心组件2.1 版本选择和镜像下载那些事部署方式我强烈建议用 Docker。Prometheus 和 Grafana 虽然也有二进制压缩包解压就能跑但后续升级、迁移、隔离依赖容器化都要省心太多。国内网络环境下拉取 Docker Hub 官方镜像经常超时这是很多人入门的第一个坎。除了配置 registry-mirrors 镜像加速地址之外更稳妥的做法是把常用镜像同步到公司内部的镜像仓库生产环境直接走内网拉取。千万不要在镜像下载这件事上死磕太久换加速地址、换网络都试过了还不行就直接下载官方 tar.gz 二进制包小规模实验环境完全够用。版本选择上Prometheus 建议选当前最新稳定版2.x 系列的配置 API 都是兼容的Grafana 选最新稳定版即可9.x 到 11.x 我都用过配置方式没有根本性变化。node_exporter 要注意架构匹配x86 的机器下 arm64 的包跑不起来。下面是我在测试环境使用的 docker-compose.yml把 Prometheus、Grafana、node_exporter 一次拉起三分钟就能看到数据version: 3.8 services: prometheus: image: prom/prometheus:v2.53.0 container_name: prometheus ports: - 9090:9090 volumes: - ./prometheus.yml:/etc/prometheus/prometheus.yml - prometheus-data:/prometheus command: - --config.file/etc/prometheus/prometheus.yml - --storage.tsdb.path/prometheus - --storage.tsdb.retention.time15d restart: unless-stopped node-exporter: image: prom/node-exporter:v1.8.2 container_name: node-exporter ports: - 9100:9100 restart: unless-stopped grafana: image: grafana/grafana:11.2.0 container_name: grafana ports: - 3000:3000 environment: - GF_SECURITY_ADMIN_PASSWORDadmin123 volumes: - grafana-data:/var/lib/grafana restart: unless-stopped volumes: prometheus-data: grafana-data:这里说一个容易忽略的参数--storage.tsdb.retention.time15d。Prometheus 默认只保留 15 天数据如果磁盘够大、想让历史趋势保留得更久可以调成 30d 或 90d。但要注意指标量大的时候磁盘占用增长非常快。经验上一个小规模测试环境几台机器 容器基础指标一天大概几百 MB上千台机器的大集群一天几十 GB 很正常。刚开始搭建不用追求长时间保留先把链路跑通后面再根据磁盘容量调整。2.2 prometheus.yml 核心配置逐段拆解Prometheus 的所有行为都围绕这个配置文件展开。下面是一份最常用的配置我逐段解释它在干什么global: scrape_interval: 15s evaluation_interval: 15s scrape_timeout: 10s rule_files: - rules/*.yml scrape_configs: - job_name: prometheus static_configs: - targets: [localhost:9090] - job_name: node-exporter static_configs: - targets: - 192.168.1.10:9100 - 192.168.1.11:9100 relabel_configs: - source_labels: [__address__] regex: (.*):9100 target_label: instance replacement: $1global里的三个参数是全局默认值。scrape_interval决定 Prometheus 每隔多久去拉一次指标15 秒是通用设置evaluation_interval决定告警规则每隔多久被评估一次如果设成 15 秒意味着一条告警从触发到被系统发现最长可能延迟 15 秒scrape_timeout是单个采集请求的超时时间一般要小于scrape_interval否则可能出现上一次抓取还没结束、下一次又开始了的情况。rule_files用来加载告警规则文件目录支持通配符推荐把规则按业务或告警等级拆成多个小文件方便维护。scrape_configs是采集配置。每个job_name代表一组监控目标最基础的用static_configs直接写 IP 和端口。注意relabel_configs这段小逻辑它的作用是把192.168.1.10:9100里的 IP 提取出来写到instance标签里。这样在 Grafana 图表和告警消息里看到的主机标识就是干净的 IP而不是始终带着:9100端口的一长串。这个习惯建议从最开始就养成否则后面所有面板和告警分组都会很难看。2.3 启动之后先验证抓取链路再碰 Grafana执行docker compose up -d之后不要急着打开 Grafana。先确认 Prometheus 真的把数据抓上来了。打开浏览器访问http://localhost:9090/targets正常情况下 Prometheus 和 node-exporter 两个采集目标都应该是 UP 状态。如果某个目标显示 DOWN不要慌用curl http://192.168.1.10:9100/metrics直接测一下基本上就能判断是防火墙没放行端口还是 exporter 本身没起来。再打开http://localhost:9090/graph输入一个最简单的查询up这个查询会返回所有监控目标的状态1 表示在线0 表示挂掉是判断 Prometheus 有没有在正常抓取的最快捷方式。然后试一个稍微实用点的node_memory_MemTotal_bytes / 1024 / 1024 / 1024如果结果能算出这台机器内存的 GB 数说明 node_exporter 的指标已经进入 Prometheus。到这里采集链路跑通了下一节才能真正发挥 Grafana 的威力。3. Grafana 接入数据源与仪表盘制作实战3.1 数据源连接填错 localhost是最容易踩的坑Grafana 默认账号是 admin/admin第一次登录会要求改密码。在 docker-compose 里预设了GF_SECURITY_ADMIN_PASSWORDadmin123就可以跳过首次改密环节。进入 Grafana 后添加数据源的路径是左侧菜单 Connections - Data sources - Add data source - 选择 Prometheus。真正容易翻车的是 HTTP URL 这一项。很多人在这里填http://localhost:9090然后发现怎么都连不上。原因很简单Grafana 如果跑在 Docker 容器里它看到的 localhost 是容器自身而不是宿主机。正确写法分几种情况Grafana 和 Prometheus 都在同一台宿主机上用 Docker 跑填http://host.docker.internal:9090macOS/Windows或http://宿主机IP:9090Linux。用 docker-compose 管理且两个容器在同一个自定义网络里直接填http://prometheus:9090用服务名通信这是最推荐的方式IP 变了也不受影响。两台不同的机器填http://Prometheus服务器IP:9090。我在正式环境里习惯把 Prometheus、Grafana、Alertmanager 放到同一个 docker-compose 项目里并显式声明一个自定义网络。这样组件之间都能用服务名互相访问不会因为宿主机 IP 变动导致监控链路断裂。填好 URL 后点击 Save test出现 “Successfully queried the Prometheus API” 的绿色提示就说明数据源配好了。3.2 两个社区精品仪表盘导入即用数据源接通后没必要从零开始画图社区里已经沉淀了很多高质量仪表盘。我最常用的有两块Node Exporter FullID: 1860最经典的主机监控面板CPU、内存、磁盘、网络、IO 全覆盖图表布局经过很多人验证第一次用很容易被它的完整度惊到。Node Exporter for Prometheus DashboardID: 8919看板信息更紧凑适合投到大屏上做展示。导入路径左侧 Dashboards - Import输入仪表盘 ID点击 Load选择刚才创建的 Prometheus 数据源Import 即可。导入后大概率直接就能看到数据。但也会遇到一个经典报错failed to upgrade legacy queries datasource ... was not found。这个报错的本质是仪表盘的 JSON 里引用了旧数据源的 UID而导入到当前 Grafana 实例后数据源的 UID 对不上。解决办法是进入仪表盘设置逐个检查面板的数据源是否都指向正确的 Prometheus或者直接编辑仪表盘的 JSON Model把datasource部分的uid改成当前数据源的 uid。理解了 UID 机制之后这个报错就再也不会困扰你了。还有一点老面板里引用的一些指标在新版本 node_exporter 中可能已经改名出现部分图表显示 No data 时用 Grafana 的 Explore 页面手动查一下指标名替换成新名字即可。3.3 手写一个 CPU 使用率面板搞懂 PromQL 核心导入模板固然快但想真正理解监控最好自己动手画一个面板。拿最简单的“系统 CPU 使用率”举例。新建 Dashboard - Add visualization数据源选 Prometheus在 Query 编辑器里写100 - (avg by (instance) (rate(node_cpu_seconds_total{modeidle}[5m])) * 100)这个查询的每个部分都要理解node_cpu_seconds_total是 CPU 各模式下的累计运行时间计数器类型modeidle过滤出空闲状态。rate(..., 5m)计算该计数器在过去 5 分钟内每秒的增长量换算过来就是空闲率。avg by (instance)按主机分组取平均因为一台机器通常有多颗 CPU 核心。100 - 空闲率剩下的就是 CPU 使用率。PromQL 初学者不需要背语法掌握rate、increase、sum by、avg by这几个核心函数就能覆盖绝大多数场景。rate处理计数器类型累计值如 CPU 时长、请求总数gauge 类型瞬时值如当前内存使用量直接用原始指标即可。一个是算增量一个是看瞬时这个区别是新手最容易搞混的地方。面板右侧的设置里Unit 选 Percent0-100Thresholds 标上告警色80% 黄色95% 红色。这样看板上一眼就能看出哪台机器 CPU 异常。类似的常用表达式也可以顺手记下内存使用率(1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100根分区磁盘使用率100 - ((node_filesystem_avail_bytes{mountpoint/} * 100) / node_filesystem_size_bytes{mountpoint/})需要强调一点node_exporter 只能看到操作系统层面的资源使用情况。如果你想监控业务指标比如接口 QPS、错误率、延迟分布就需要在应用代码里引入 Prometheus 客户端库自行暴露 /metrics 接口。Python 用 prometheus_clientJava 用 micrometerGo 用 client_golang都有非常成熟的支撑。4. 接上 Alertmanager让监控真正发挥价值4.1 告警规则文件的写法比想象中简单监控不能光看着还得在出事的时候通知到人。Prometheus 自身负责产生告警事件规则用 YAML 描述。我习惯在/etc/prometheus/rules/下建一个node_alerts.ymlgroups: - name: node_alerts rules: - alert: InstanceDown expr: up 0 for: 1m labels: severity: critical annotations: summary: Instance {{ $labels.instance }} down description: {{ $labels.job }} 任务下的实例 {{ $labels.instance }} 已经不可达超过 1 分钟 - alert: HighCpuUsage expr: 100 - (avg by (instance) (rate(node_cpu_seconds_total{modeidle}[5m])) * 100) 90 for: 5m labels: severity: warning annotations: summary: Instance {{ $labels.instance }} CPU 使用率过高 description: 当前 CPU 使用率已超过 90%持续 5 分钟几个值得注意的点expr是告警触发条件本质就是 PromQL 表达式。Prometheus 会按照evaluation_interval周期性地评估这些规则所以从指标越界到真正推送告警存在最多一个评估周期的延迟这是设计如此不是故障。for表示触发条件必须持续多久才真正产生告警。强烈建议任何告警都加一个for比如 CPU 短时间冲到 95% 可能只是某个定时任务瞬间占满持续 5 分钟才说明真的出问题了能有效过滤抖动。labels里的severity用来给告警分级方便 Alertmanager 对不同级别的告警走不同通知渠道。annotations是告警的正文内容支持$labels和$values模板变量可以把具体的实例名、当前数值带进去。写完规则后需要重载 Prometheus 配置curl -X POST http://localhost:9090/-/reload。注意如果容器以非 root 用户运行或者配置文件是只读挂载reload 会失败这个细节很容易忽略。4.2 Alertmanager 部署与路由参数逐项解读告警事件产生后Prometheus 不会直接发邮件而是推送给 Alertmanager由它决定发给谁、怎么发。先加一个服务alertmanager: image: prom/alertmanager:v0.27.0 container_name: alertmanager ports: - 9093:9093 volumes: - ./alertmanager.yml:/etc/alertmanager/alertmanager.yml restart: unless-stopped然后在 prometheus.yml 里加上关联配置alerting: alertmanagers: - static_configs: - targets: [alertmanager:9093]alertmanager.yml 的核心是路由和接收器global: smtp_smarthost: smtp.example.com:465 smtp_from: monitorexample.com smtp_auth_username: monitorexample.com smtp_auth_password: password smtp_require_tls: false route: group_by: [alertname] group_wait: 10s group_interval: 2m repeat_interval: 4h receiver: email-notify routes: - matchers: - severity critical receiver: email-notify-critical receivers: - name: email-notify email_configs: - to: teamexample.com send_resolved: true - name: email-notify-critical email_configs: - to: oncallexample.com send_resolved: true路由里的四个参数是理解 Alertmanager 的钥匙我详细说下group_by按什么维度把告警合并成组。按alertname分组的意思是同一种告警规则产生的多个实例告警会合并到一条通知里。否则整个机房 10 台机器同时掉线你会瞬间收到 10 条内容几乎一样的邮件体验非常糟糕。group_wait同一组内第一批告警的等待时间。设为 10 秒是说第一批告警到达后等 10 秒如果这段时间里有新告警进入同一组会合并成一条发出去。group_interval一组告警已经发过通知后再有新告警加入这一组至少要间隔多久才发第二轮。要是网络抖动导致 100 台机器陆续掉线这个参数决定了通知轰炸的节奏。repeat_interval同一条告警没有恢复时隔多久重新通知一次。设 4 小时比较合理过短会让人觉得天天被狼来了骚扰过长可能错过故障状态的恶化。send_resolved: true表示故障恢复后也要发一条“已恢复”通知。这个开关我建议一定打开否则团队其他人不知道问题是不是已经解决凌晨 3 点的告警可能一直到 10 点都还有人不敢动服务。除了邮件Alertmanager 还支持 webhook、企业微信、钉钉、Slack。webhook 最通用Alertmanager 会以 JSON 格式 POST 到指定 URL自己写几十行代码就能对接任意 IM 系统。我之前接企业微信机器人就是写一个小的转发服务把 Alertmanager 的 JSON 转成企业微信机器人支持的 markdown 格式再 POST 到 webhook 地址整个链路跑通之后告警能直接推到手机端比看邮件快得多。4.3 告警链路怎么验证以及误报控制配置全部完成后务必做一次完整的告警演练。最简单的方法把 node_exporter 容器停掉等 1 分钟左右打开 Alertmanager 的 Web UIhttp://localhost:9093如果没有意外能看到一条 InstanceDown 告警状态为 Active。如果没出现告警按下面的顺序排查Prometheus 的/rules页面看规则是否加载成功规则文件语法错误会在这里直接暴露。Prometheus 的/alerts页面看规则当前状态如果已经 fired说明推送到 Alertmanager 的环节可能有问题检查alerting配置段。Alertmanager 的/status页面看通知是否发送邮件发送失败最常见的原因是 SMTP 端口选错465 是隐式 TLS587 是 STARTTLS两者的 TLS 配置方式完全不同。在告警配置上我吃过几次亏分享三个经验告警规则不要一上来就追求大而全。先把四条最基本的配上实例存活、CPU 高、内存高、磁盘满。跑稳之后再逐步加业务告警。阈值要结合自己业务的基准线不要照搬网上随便抄的 90%。有些服务的 CPU 常年 5% 波动设 90% 就是废规则另一些数据库到 60% CPU 就已经开始性能恶化了设 90% 会错过最佳处理窗口。告警文案一定要写清楚“收到后该干嘛”。不要只写“CPU 高”在annotations里把建议的排查命令写进去比如top、pidstat、docker logs。凌晨三点收到告警时多一句话能少走很多弯路。5. 进阶方向Kubernetes 集群监控和 OpenTelemetry 接入5.1 玩 K8s 就别手动维护静态配置了如果你已经跑在 Kubernetes 上再手工维护 prometheus.yml 里的静态 target 列表不现实因为 Pod 的 IP 是动态的扩缩容随时发生。K8s 环境的监控业界标准方案是 kube-prometheus-stack一个 Helm Chart 打包了 Prometheus Operator、Alertmanager、Grafana 和各类通用 Exporter。核心概念是 CRDServiceMonitor 和 PodMonitor。你可以声明一个 ServiceMonitor 对象来描述“我想监控哪个 Service 的哪些指标”Prometheus Operator 会监听这些 CRD 的变更自动生成 Prometheus 的采集配置apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: name: example-app namespace: monitoring spec: selector: matchLabels: app: example-app endpoints: - port: metrics interval: 30s这套机制和静态配置完全不同创建或删除 ServiceMonitor采集目标就会自动增删完全不需要 reload 配置。对自动伸缩频繁的 Kubernetes 环境来说这是唯一合理的方案。安装方式很简单helm repo add prometheus-community https://prometheus-community.github.io/helm-charts helm repo update helm install kube-prometheus-stack prometheus-community/kube-prometheus-stack -n monitoring装完之后用kubectl -n monitoring port-forward svc/kube-prometheus-stack-grafana 3000:80临时访问 Grafana默认账号密码是 admin/prom-operator。集群节点的 CPU、内存、Pod 资源、API Server 状态这些核心指标Chart 里已经自带仪表盘不用重新配。上生产环境前有几个参数必须改一是存储持久化默认 emptyDir 重启就丢数据要挂到持久卷上二是资源 limits集群规模上来后 Prometheus 的内存占用会涨得很快提前估算并调整三是认证Grafana 默认管理员密码要立刻换掉通过 Ingress 对外暴露时建议加一层反向代理认证。5.2 Prometheus 与 OpenTelemetry Collector 的配合方式关于“Prometheus 是如何从 otel-collector 收取数据的”这个问题其实不复杂。OpenTelemetry Collector 在这里的角色是数据网关业务应用通过 OTLP 协议把指标推给 CollectorCollector 再通过 prometheus exporter 暴露一个 /metrics 端口最后 Prometheus 像抓普通 target 一样来拉取。关键配置片段receivers: otlp: protocols: grpc: endpoint: 0.0.0.0:4317 http: endpoint: 0.0.0.0:4318 processors: batch: exporters: prometheus: endpoint: 0.0.0.0:9091 namespace: app service: pipelines: metrics: receivers: [otlp] processors: [batch] exporters: [prometheus]Prometheus 侧再加一个 target- job_name: otel-collector static_configs: - targets: [otel-collector:9091]这个方案的精髓在于解耦。业务应用只关心怎么把 OTLP 数据发出去完全不需要知道 Prometheus 的存在Prometheus 也只看到一个标准的 /metrics 端点对上游是什么完全无感。将来就算要把指标同时发给多个监控后端也只是改 Collector 配置的事。相比 Pushgateway这种方案没有单点问题也没有“指标只增不删”的累积陷阱是更值得长期投入的方向。6. 高频问题和排查思路直接抄作业6.1 Grafana 数据源和仪表盘导入报错最经典的报错就是开头提到的failed to upgrade legacy queries datasource ... was not found一句话解释仪表盘的 JSON 里声明了一个旧数据源引用但导入到当前 Grafana 实例后数据源的 UID 对不上。通常发生在从老版本 Grafana 导出模板或者导入别人分享的旧面板时。处理顺序先确认数据源本身可用Configuration - Data sources点 PrometheusSave test。打开仪表盘 Settings - Variables检查所有模板变量的数据源是否都指向正确的 Prometheus。面板数量多时直接编辑仪表盘 JSONSettings - JSON Model搜索datasource把uid改成当前数据源的 uid。当前 uid 可以在数据源列表页看到是一串形如im7_otuvz的随机字符串。还没解决就删掉数据源重新添加让 Grafana 生成新的 uid再回到面板重新关联。理解了“Grafana 用随机 UID 引用数据源”这个机制以后遇到同类报错都能自己定位。6.2 指标抓取失败和存储膨胀Prometheus 采集失败的典型表现是 /targets 页面上显示 DOWN或者查询时看不到数据。排查顺序curl http://目标IP:端口/metrics直接访问确认 exporter 是不是活着。node_exporter 默认 9100cAdvisor 默认 8080mysqld_exporter 默认 9104端口别搞混。检查防火墙和云安全组。很多云服务器默认安全组只放行 80/443/229100 这类端口不显式放行的话外网永远抓不到。能访问但 Prometheus 一直报context deadline exceeded多半是网络延迟太高导致抓取超时可以在scrape_configs里单独调大scrape_timeout或者把 exporter 挪到离 Prometheus 更近的网络区域。检查时间同步。Prometheus 的采样和查询非常依赖时间戳被监控机和监控机之间时钟漂移过大会出现各种奇怪现象。生产环境必须配置 NTP。存储膨胀的排查方向采集了太多无用的指标、保留时间过长、标签基数失控。最后这一点最致命如果把请求 URL 直接作为 labelURL 千变万化Prometheus 内存直接爆掉。设计指标时务必控制标签值集合的规模不要在 label 里放高基数数据。6.3 Docker 镜像拉取失败的应对部署阶段最常见的拦路虎就是镜像拉不下来。我实测有效的办法有三个配置 registry-mirrors。编辑/etc/docker/daemon.json{ registry-mirrors: [https://你选择的加速地址] }然后systemctl restart docker。不同网络环境下各加速地址的可用性差异很大没有万能地址需要自己测试。同步到内部镜像仓库。如果公司有 Harbor 或者其它内网仓库把需要的外部镜像一次同步进去然后 pull 时指定内网地址。这是长期最稳定、最推荐的做法。等你被外部网络问题折磨过几次就会明白内部镜像仓库才是生产环境的正解。直接用二进制包。Prometheus、Grafana、node_exporter 都有官方 tar.gz 包解压就能跑完全不依赖容器网络。小规模实验环境够用。6.4 时区、时间线偏移等小坑Grafana 面板默认使用服务器时区服务器是 UTC 的话图表上的时间会整体偏 8 小时。在 Grafana 的 Default preferences 里把 timezone 设为 Asia/Shanghai问题立刻消失。计数器类型指标在进程重启后可能出现rate负值这不是配置错误是计数器重置导致的用increase()或者调整窗口可以平滑掉。Grafana 里接了多个数据源时每个面板都要确认数据源选择否则会出现“明明 Prometheus 里有指标面板却显示 No data”的怪象。7. 后续值得深耕的几个实战方向到这里一套能用的监控体系已经跑通了。再往后走根据你自己的情况有三条路可以选一条深入。第一条是把监控体系产品化。把告警规则、仪表盘配置、采集配置全部代码化放到 Git 仓库统一管理。新项目接入监控时拉取模板改几个变量就能自动生成一整套仪表盘和告警规则。这能极大减少重复劳动也让整个团队的监控水位保持一致。第二条是数据成本治理。Prometheus 指标数量增长非常快很多指标其实从来没人查询过。可以通过 recording rules 对高频查询做预聚合或者用 remote write 把冷数据转储到对象存储控制本地 TSDB 的容量。监控系统搭建起来只是开始持续运营才是长期课题。第三条是往业务指标走。基础设施监控做到位之后更有价值的其实是接口成功率、订单量、付款用户数这类业务指标。把这些从业务库或日志里算出来暴露成 Prometheus 指标和基础设施指标放进同一个 Grafana老板问数据的时候打开大屏就能讲清楚。这才是监控体系从“技术工具”走向“业务支撑”的分水岭。再分享一个我自己养成的小习惯每次新上一个服务都强制自己先回答三个问题才准上线。第一这个服务的核心指标是什么怎么量化“它正常在干活”第二它挂了会先影响谁那个人靠什么感知到第三如果指标出现异常我第一步去哪里查把这三个问题想明白了监控体系的架构就会自然浮出来剩下的只是照着方案填 Prometheus 配置而已。如果你正准备从零开始搭我的建议很简单先按这篇文章把单机版跑起来导入 Node Exporter Full 面板配上 CPU、内存、磁盘、存活四条告警用一个月。等你习惯了每天花五分钟看一眼仪表盘再慢慢往上加业务指标和自动扩展。监控这件事不怕起步小就怕一直停留在收藏了无数教程、但从未真正跑通过一次。