我做监控这一行也有年头了从最早的Zabbix、Nagios一路用过来到后来PrometheusGrafana这套组合逐渐成了标配。说实话这套东西能火起来不是没道理的Prometheus负责采集和存储时序数据Grafana负责把数据变成看得懂的图表两者配合默契几乎成了云原生监控的代名词。如果你正在为线上服务的CPU、内存、磁盘、网络发愁或者想知道业务请求量、错误率、延迟这些核心指标怎么可视化又或者想搭建一套带告警通知的完整监控体系这篇文章就是为你准备的。我自己在多个项目里都部署过这套监控栈从单机版到集群版都踩过不少坑。这篇文章会把整个搭建过程、关键配置、常见坑位一次讲清楚让刚接触监控的新手能快速上手也让有一定基础的朋友能查漏补缺。内容会覆盖架构设计、Prometheus部署、指标采集、Grafana界面配置、告警接入这几个核心环节每个部分都有实操命令和配置示例。1. 整体设计与思路拆解1.1 为什么是PrometheusGrafana这套组合很多人问我监控方案那么多为什么要选这个组合我的回答通常是因为它把“采集存储”和“可视化”这两件事拆开了各干各的互不干扰。Prometheus是开源的时间序列数据库它的核心能力是抓取指标Pull模型、存储数据、执行告警规则。Grafana则是纯粹的可视化平台它本身不采集数据而是通过数据源插件从Prometheus、InfluxDB、MySQL等地方读取数据然后绘制成图表。这种分层设计的好处非常明显你想换存储后端不影响可视化你想换可视化工具也不影响数据采集。实际上Grafana能接的数据源非常多Prometheus只是其中一种但这种组合因为查询语言PromQL的强大和图表生态的完善成了最流行的搭配。另一个关键优势是社区生态。Prometheus官方和第三方贡献了大量exporter比如采集Linux主机指标的node_exporter、采集MySQL指标的mysqld_exporter、采集Nginx指标的nginx_exporter还有采集容器指标的cadvisor基本你能想到的中间件都有现成的采集器。这意味着你不需要从头写采集逻辑部署对对应的exporter配置好抓取任务数据就有了。1.2 监控架构的最小闭环长什么样一套完整可用的监控系统最少需要四个环节指标采集、数据存储、可视化展示、告警通知。Prometheus本身承担了采集、存储、告警规则评估这三件事。Exporter暴露HTTP接口把系统或应用的指标以特定格式Prometheus文本格式输出Prometheus定期去这些接口拉取数据存进自己的时序数据库。配置告警规则后Prometheus会持续评估规则条件一旦触发就推送给Alertmanager由它负责去重、分组、静默最终通过邮件、企业微信、钉钉、Webhook等方式发通知。Grafana在链条中的位置是读取Prometheus存储的数据把它变成仪表盘同时它也能展示告警状态甚至集成告警。在实际部署中我通常把Prometheus和Grafana放在同一台机器上用Docker Compose统一管理这样部署简单运维也省心。Exporter则根据监控目标分散部署监控哪台机器就在哪台机器上跑对应的exporter。这套架构虽然听起来朴素但线上跑了两三年都没出过大问题可见它的稳定性是经过验证的。1.3 部署方式选型Docker Compose vs 二进制安装关于部署方式我见过不少争论。二进制安装的好处是资源占用少、排障直接适合对性能要求极高的场景而Docker Compose的优点是环境一致性好、升级回滚方便、依赖隔离干净。我个人的习惯是如果是生产环境且机器资源紧张用二进制安装如果只是想快速验证、或者已经有Docker环境用Compose。文章接下来的操作我会默认使用Docker Compose方式因为这样能快速把整套环境拉起来而且配置文件的挂载方式也方便我们反复修改测试。如果你用的是二进制方式逻辑是一样的只是启动命令不同配置文件的写法完全通用。2. Prometheus部署与核心配置2.1 使用Docker Compose快速拉起Prometheus先准备一个工作目录比如/opt/monitoring里面放docker-compose.yml和配置文件目录。Compose文件里我会同时定义Prometheus、Grafana、Alertmanager三个服务一次性把初版监控栈搭起来。version: 3.8 services: prometheus: image: prom/prometheus:v2.53.0 container_name: prometheus restart: always volumes: - ./prometheus.yml:/etc/prometheus/prometheus.yml - ./rules/:/etc/prometheus/rules/ - prometheus_data:/prometheus ports: - 9090:9090 command: - --config.file/etc/prometheus/prometheus.yml - --storage.tsdb.path/prometheus - --storage.tsdb.retention.time15d - --web.enable-lifecycle grafana: image: grafana/grafana:11.1.0 container_name: grafana restart: always volumes: - grafana_data:/var/lib/grafana ports: - 3000:3000 depends_on: - prometheus alertmanager: image: prom/alertmanager:v0.27.0 container_name: alertmanager restart: always volumes: - ./alertmanager.yml:/etc/alertmanager/alertmanager.yml - alertmanager_data:/alertmanager ports: - 9093:9093 volumes: prometheus_data: grafana_data: alertmanager_data:这里面有几个参数值得说清楚。--storage.tsdb.retention.time15d控制数据保留时间Prometheus默认保留15天如果磁盘紧张可以调短如果业务需要历史趋势分析可以调长但要注意磁盘占用会随之增加。--web.enable-lifecycle这个开关很重要它允许我们通过发送POST /-/reload请求热加载配置不需要重启Prometheus进程在频繁调整抓取任务时特别方便。depends_on只是控制容器启动顺序不保证Prometheus服务完全就绪所以Grafana首次启动时如果连不上数据源不一定是配置错了可能只是Prometheus还没准备好等几秒再试就好。2.2 prometheus.yml配置文件的深刻理解Prometheus的配置文件是整套监控系统的中枢神经。很多人随便抄一份配置就用了结果后面加采集目标时一头雾水。我建议花十分钟把核心字段搞清楚后面会省很多事。global: scrape_interval: 15s evaluation_interval: 15s external_labels: monitor: my-monitor rule_files: - /etc/prometheus/rules/*.yml scrape_configs: - job_name: prometheus static_configs: - targets: [localhost:9090] - job_name: node static_configs: - targets: [192.168.1.101:9100, 192.168.1.102:9100]scrape_interval是全局抓取间隔默认1分钟我习惯设为15秒这样监控数据更及时但相应的存储压力和网络开销也会变大。evaluation_interval是告警规则评估周期它和告警的触发时效直接相关评估越频繁告警越及时但CPU消耗也会增加。external_labels是外部标签在多个Prometheus实例对接统一Alertmanager时用来区分告警来源。单机场景可能感觉不到它的作用但集群部署时一定要提前规划好。scrape_configs是一组抓取任务每个job_name代表一类采集目标。targets里可以写多个地址Prometheus会并行抓取。如果你增加了一台新机器只需要在对应的job里加上IP:端口然后热加载配置就能生效不需要重启。2.3 指标抓取的底层逻辑与常见参数Prometheus抓取指标用的是Pull模型这和传统监控系统的Push模型思路正好相反。简单说Prometheus主动去每个目标暴露的HTTP接口拉取数据。这种设计的好处是采集端不用关心目标机器的网络位置只要Prometheus能访问到就行目标机器也不需要安装额外的agent去推送数据只要提供一个HTTP接口就够了。每个采集目标的HTTP接口会返回一批文本格式的指标每行形如node_cpu_seconds_total{cpu0,modeidle} 83123。Prometheus拉取后解析、打上时间戳存入TSDB。注意指标名后面的花括号里是标签label标签是Prometheus数据模型中极其重要的概念。同一指标名配合不同标签组合就能区分不同维度查询和聚合都靠它。抓取时有两个常用参数honor_labels处理标签冲突默认情况下如果采集目标返回的标签和Prometheus自身配置的标签冲突会以服务端配置为准relabel_configs则是在抓取前后对目标做标签改写、过滤、重命名等操作灵活度非常高但也容易把人绕晕新手暂时不用深究知道有这个东西即可。3. 指标采集Exporter的选择与配置3.1 核心系统指标采集node_exporter实战如果你要监控Linux服务器的CPU、内存、磁盘、网络等基础指标node_exporter是不可绕过的组件。它运行在被监控的机器上暴露一个9100端口把系统层面的指标全部转成Prometheus格式。下载和启动非常简单下面是以二进制方式运行的示例wget https://github.com/prometheus/node_exporter/releases/download/v1.8.2/node_exporter-1.8.2.linux-amd64.tar.gz tar xvf node_exporter-1.8.2.linux-amd64.tar.gz cd node_exporter-1.8.2.linux-amd64 ./node_exporter --web.listen-address:9100启动后访问http://IP:9100/metrics就能看到一大片指标。里面最具代表性的几个node_cpu_seconds_total是CPU累计使用时间按模式和核分开统计node_memory_MemTotal_bytes、node_memory_MemAvailable_bytes是内存总量和可用量node_filesystem_avail_bytes是磁盘可用空间node_network_receive_bytes_total是网卡累计接收字节数。看到这里你会发现exporter收集的是累计值和瞬时值而不是直接的“使用率”使用率需要用PromQL计算出来。比如CPU使用率通常是100 - (avg by (instance) (rate(node_cpu_seconds_total{modeidle}[5m])) * 100)这个公式的含义是取过去5分钟内idle状态的平均速率算出空闲比例再用100减。内存使用率则是(1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100。虽然看起来有点绕但理解了“原始指标需要加工才能变成业务指标”这一点PromQL就不会感到无从下手。3.2 Docker容器监控cadvisor与exporter组合现在的应用大多跑在Docker容器里单纯看宿主机指标不够还需要看容器级别的CPU、内存、网络。cadvisor就是专门做这件事的。docker run -d \ --namecadvisor \ --restartalways \ -p 8080:8080 \ --volume/:/rootfs:ro \ --volume/var/run:/var/run:ro \ --volume/sys:/sys:ro \ --volume/var/lib/docker/:/var/lib/docker:ro \ --volume/dev/disk/:/dev/disk:ro \ --privileged \ --device/dev/kmsg \ gcr.io/cadvisor/cadvisor:v0.49.1cadvisor暴露8080端口后在Prometheus的scrape_configs里加一个job指向它就能采集容器指标。常见的容器指标有container_cpu_usage_seconds_total、container_memory_usage_bytes、container_network_receive_bytes_total。配合container_label_com_docker_compose_service这个标签可以按容器服务名聚合。这也是Docker Compose部署场景下很实用的一个维度。有一点要提醒cadvisor的镜像在gcr.io上国内拉取可能会比较慢。我看到很多人卡在这一步其实用docker.io的替代镜像或者配置镜像加速器就能解决。因为网络环境各有不同具体加速方案这里就不多说了但思路是不要死磕一个镜像源。3.3 应用与中间件监控MySQL、Nginx、Redis等只要中间件官方或社区提供了exporter监控就不是难事套路基本都是三步部署exporter → 验证metrics接口 → 添加Prometheus抓取任务。以MySQL为例运行mysqld_exporter时需要指定数据库连接信息通过环境变量或配置文件传入。它会采集连接数、慢查询数、缓冲池命中率、复制状态等关键指标。Nginx的话需要编译时开启stub_status模块或者使用nginx-module-vtsexporter才能拿到连接数、请求数、活跃连接等数据。Redis的redis_exporter不仅能采集基础命令统计还能拿到键空间命中率、内存碎片率等高级指标。这些中间件exporter的社区选择很多我个人的选型原则是优先用官方出品的其次用star数高、维护活跃的第三方。用到生产环境前一定要先看它的/metrics输出是否正常确保抓回来的数据和你预期一致再挂到Prometheus上避免“有数据但数据是错的”这种尴尬情况。3.4 网络设备与黑盒监控探针式采集有朋友会问“Prometheus能监控交换机吗”答案是肯定的但方式跟上面讲的Exporter不太一样。网络设备通常不支持安装Exporter而是通过SNMP协议暴露指标。Prometheus用snmp_exporter来做这件事它负责把SNMP请求转换成Prometheus格式。配置过程稍复杂一些需要提前确定交换机的SNMP OID和团体名有时候还要根据设备型号定制采集模块。另外一类场景是黑盒监控不关心目标内部状态只关心它能不能访问。blackbox_exporter支持HTTP、HTTPS、TCP、ICMP这些探测方式比如你想知道某个网站首屏响应时间、某个TCP端口是否通、某台设备能否ping通都可以用它。配置方式是在Prometheus抓取blackbox_exporter时通过参数传递探测目标这种“探针式”监控在实际运维中非常实用尤其是配合告警规则能第一时间发现服务不可用。4. Grafana界面基础配置与可视化实战4.1 Grafana数据源接入踩过最大的坑首次访问Grafana默认地址是http://IP:3000初始账号密码是admin/admin登录后系统会强制要求修改密码。这个第一步很简单但接下来配置数据源时我见过太多人在这一步卡住。进入“Connections → Data sources → Add data source”选择Prometheus然后填写URL。这里有一个绝大多数新手都会犯的错URL里填的是localhost:9090或者127.0.0.1:9090结果Grafana一直连不上。原因是Grafana和Prometheus如果都跑在Docker容器里Grafana容器里的localhost指向的是它自己根本不是Prometheus。正确的填法是如果两个服务在同一台宿主机上在Grafana容器里用host.docker.internal:9090访问宿主机端口或者直接用宿主机内网IP。如果Prometheus也在容器里并且和Grafana在同一个Compose网络内可以直接填服务名http://prometheus:9090。填完URL后点击“Save Test”看到绿色的“Success”提示就通了。我每次配置完成后都会习惯性再去检查一遍这个细节因为它是后续一切可视化操作的前提。4.2 图表面板怎么搭从空面板到可用大盘Grafana里最核心的概念是Dashboard仪表盘和Panel面板。一个Dashboard由多个Panel组成每个Panel就是一张图表。我刚开始用的时候觉得面板数量越多越好后来发现一屏塞几十个图根本看不过来。真正好用的做法是围绕场景组织面板比如“节点总览”、“容器监控”、“MySQL专项”各建一个Dashboard每个Dashboard控制在10个以内Panel这些Panel都经过筛选确保打开就能快速定位问题。创建一个Panel的流程是点击“Dashboard → New dashboard → Add visualization”然后选择数据源Prometheus再在查询编辑器里输入PromQL表达式。比如我想看CPU使用率趋势输入下面这条100 - (avg by (instance) (rate(node_cpu_seconds_total{modeidle}[5m])) * 100)右侧的图例马上会渲染出曲线。这时你会发现Grafana的查询编辑器本身还带一整套PromQL提示和函数菜单对不熟悉PromQL的朋友非常友好。你可以调整时间范围、添加阈值线、修改图例名称还可以设置单位比如把内存指标的单位显示为GB而不是字节这些细节直接决定面板的易读性。4.3 变量模板化一个面板看所有机器面板画多了以后会有一个很痛的体验几十台机器的CPU图表难道要重复创建几十个面板当然不需要这就轮到变量Variable出场了。在Dashboard的Settings里添加一个变量类型选择Query数据源选Prometheus查询语句写label_values(node_uname_info, instance)这个变量就会自动列出当前所有node_exporter的实例地址。然后在每个Panel的查询里把硬编码的目标地址替换成$instance这个变量比如100 - (avg by (instance) (rate(node_cpu_seconds_total{modeidle, instance$instance}[5m])) * 100)保存后Dashboard顶部会出现一个下拉框你可以自由切换机器同一个面板立刻就能看任何一台机器的数据。用变量做维度下钻是Grafana高效使用的关键技巧学会了之后你会觉得之前一个个建面板的方式真的太原始了。4.4 面板导出、导入与社区复用Grafana社区有一个规模非常庞大的面板市场很多常见监控对象都能直接找到现成面板不需要从零开始画。官方社区网址是grafana.com/grafana/dashboards网站上可以按数据源、按采集对象搜索面板每个面板都有一个ID比如node_exporter经典面板ID是1860容器监控常见面板ID是14282MySQL监控是7362。导入方式很简单在Grafana左侧菜单点击“Dashboards → New → Import”填入面板ID点击Load再选择对应的数据源就能导入。导入后一定要做两件事一是检查面板里用的指标名和采集target是否匹配二是查看每个Panel用到的PromQL是否需要调整比如有些社区面板默认采集频率是1分钟你需要把查询里的时间窗口改成和你的抓取间隔匹配否则图上可能都是空值。还有一个小技巧是面板的JSON模型。Grafana的每个Dashboard本质上是一个JSON对象你可以在Dashboard设置里查看或编辑JSON。如果你想把面板从一台Grafana拷贝到另一台最稳妥的方式是导出一个JSON文件再导入而不是直接用别人的链接。网络上我见过有人遇到“grafana 拷贝整个面板”不知道怎么操作其实核心就是这一份JSON。4.5 一个经典问题legacy queries数据源报错在用社区面板时你可能会遇到一个报错信息failed to upgrade legacy queries datasource im7_otuvz was not found。我最初遇到这个提示时也愣了一下以为是面板文件损坏了。这个报错的本质是老版本Grafana会以“legacy query”格式保存查询面板里的每个查询都记录了所属数据源的uid。当你把面板导入到新版本Grafana时查询里引用的数据源uid在当前实例上不存在于是Grafana不知道这个查询该发往哪个数据源升级解析就失败了。解决办法是在面板JSON文件里找到所有的datasource字段把里面的uid改成当前实例中Prometheus数据源的uid。你可以先到数据源配置页拿到正确uid然后全局替换JSON后再导入。如果是导入社区面板时遇到直接编辑JSON里的uid: 也可以留空通常会让Grafana使用默认数据源。5. 告警通知Prometheus与Alertmanager的完整对接5.1 从告警规则到Alertmanager的完整链路监控不只是用来看图告警才是真正防止故障恶化的手段。告警链路分三段Prometheus负责评估规则并产生Alert事件Alertmanager负责接收这些Alert然后做分组、去重、静默处理再通过不同渠道通知人。在Prometheus配置里增加rule_files指向规则文件目录然后新建规则文件文件名任意但后缀必须是.yml。里面定义告警规则的示例groups: - name: node_alerts rules: - alert: NodeCPUUsageHigh expr: 100 - (avg by (instance) (rate(node_cpu_seconds_total{modeidle}[5m])) * 100) 85 for: 5m labels: severity: warning annotations: summary: {{ $labels.instance }} CPU usage is above 85% description: Instance {{ $labels.instance }} CPU usage has been above 85% for more than 5 minutes.这里面的expr是触发条件for: 5m表示连续5分钟满足条件才触发告警这是避免瞬时抖动造成告警轰炸的有效手段。labels里自定义严重级别annotations里写告警内容模板。Prometheus产生告警后会把消息推给Alertmanager。两者之间的对接不需要额外写接口Prometheus启动参数加上--alertmanager.urlhttp://alertmanager:9093并确保配置了相应的alerting配置块。我在Compose里已经定义了Alertmanager服务Prometheus默认就会尝试和同名的alertmanager服务通信。5.2 Alertmanager配置通知渠道和路由规则Alertmanager的核心是alertmanager.yml下面是一个比较典型的配置框架global: resolve_timeout: 5m smtp_smarthost: smtp.example.com:465 smtp_from: alertexample.com smtp_auth_username: alertexample.com smtp_auth_password: your-password route: group_by: [alertname, instance] group_wait: 10s group_interval: 2m repeat_interval: 4h receiver: email receivers: - name: email email_configs: - to: opsexample.comroute里的几个间隔参数结合了告警的实际体验group_wait是同一分组告警首次通知前等待的时间用来收集同组更多告警合并发送group_interval是同一分组新告警的发送间隔repeat_interval是同一告警重复通知的最小间隔我一般设4小时防止同一问题一直刷屏。企业微信、钉钉、Webhook的配置其实原理都一样换个receivers类型而已。Alertmanager的优势是支持多级路由比如把“严重”级别告警发到IM群把“一般”级别的发到邮件列表这些都可以在routes子节点里按severity标签区分。告警配置这块Prometheus官网文档和社区文章都很成熟但纸上得来终觉浅建议先发一条测试告警验证整套链路。5.3 告警规则验证与常见错误告警规则写完之后我强烈建议不要直接等它触发。你可以用Prometheus的“Alerts”页面查看规则状态每条规则会显示评估结果。如果规则有语法错误Prometheus日志里会直接报出来常见的有yaml缩进错误、PromQL函数拼写错误、标签引用格式错误。我还遇到过一个看似诡异的问题规则明明没触发但告警列表里看不到规则。排查后才发现是rule_files的路径挂载不对Prometheus容器里根本没有读到规则文件。用docker exec prometheus cat /etc/prometheus/rules/node_alerts.yml验证一下文件是否存在是最快的排查方法。发送测试告警还有一个更直接的方法临时写一条一定会触发的规则比如expr: vector(1)这样Prometheus评估时永远为真Alertmanager会立刻收到告警。确认链路通了你再把这条规则删掉这种“先打通再优化”的思路能省下很多调试时间。6. 常见问题与排查技巧实录6.1 Prometheus端口、容器和存储问题排查问题时我习惯先用最简单的命令验证基础状态。Prometheus的Targets页面里每个采集目标会显示当前抓取状态UP是正常DOWN是抓不到。如果显示DOWN先确认目标机器防火墙是否放行了对应端口再用curl http://IP:9100/metrics手动访问看返回是否正常。另外两个经常遇到的问题一是容器重启后数据丢失。如果你没有给Prometheus或Grafana配置持久化卷容器销毁后数据全没了。我们在Compose里已经声明了named volume但如果你是用docker run临时启动的一定要加上-v参数挂载数据目录否则重建容器等于重置。二是Prometheus启动后页面打不开。这通常是端口没映射好或者防火墙没放开用docker ps看端口映射再curl localhost:9090/-/healthy测试健康接口。关于存储还有一个容易被忽略的经验Prometheus默认的TSDB对磁盘IO有一定要求如果机器本身磁盘性能很差查询大范围数据时会明显变慢。遇到这种情况第一选择不是加机器而是检查是否有不必要的指标在持续采集高基数数据。高基数是Prometheus最常见的性能杀手比如把请求URL的完整路径作为标签会导致标签组合数量爆炸。尽量用固定业务维度做标签不要用高可变值做标签。6.2 Grafana常见报错与显示异常排查Grafana里报错最多的两类一类是数据源连通性问题前面介绍的localhost坑是头号元凶另一类是面板数据为空。面板没数据时先看右上角时间范围是否覆盖了数据实际产生的时间段再看查询里是否有变量没有正确匹配上最后看Prometheus的Targets页面确认数据真的抓取到了。如果数据源测试是通过的面板偶尔会显示No data这时候在Prometheus查询页面里手动执行同一条PromQL看是否有返回值。这一步能快速区分是查询问题还是数据问题。如果Prometheus有数据但Grafana没有大概率是变量或者数据源的uid不匹配对照之前讲的legacy queries处理方式检查一下。还有一个视觉上的问题值得提Grafana默认时区是浏览器本地时区如果你和服务器时区不一致图上时间轴会看起来“偏了”。在Dashboard Settings里把时区固定为UTC或者服务器所在时区团队协作时看到的时间线才能对得上。6.3 告警没触发、通知没收到怎么排查告警链路长了任何一个环节断掉都会导致“没收到通知”的结果。我会按下面这个顺序排查第一步在Prometheus的Alerts页面看规则状态确认规则是OK还是Pending、Firing。如果规则一直处于Pending说明条件已经满足但还在等待for参数规定的持续时间需要继续观察。如果规则是Inactive表示条件不满足或压根没评估看规则里的PromQL返回是否有值。第二步确认Prometheus能连上Alertmanager。在Prometheus的Status → Runtime Build Information里能看到Alertmanager的连接配置也可以直接用浏览器打开http://IP:9093看Alertmanager界面有没有接收到告警。如果Alertmanager里空空如也说明Prometheus没推送过来检查启动参数和alerting配置。第三步假设Alertmanager已经收到了告警但通知渠道没发出来看Alertmanager日志。SMTP配错、Webhook地址不可达、路由规则没有匹配到任何receiver这些都会在日志里留下线索。如果没有日志输出检查Alertmanager的配置文件有没有被正确加载尤其是缩进yaml配置最怕缩进错位错一个空格可能就导致整个路由失效。6.4 监控系统日常维护的几个小习惯搭建只是开始真正考验系统的是长期运行。在这几年的维护过程中我养成了几个比较实用的习惯。我会定期查看Prometheus的TSDB状态和指标量。如果指标增长速度异常马上检查是否新增了高基数的采集目标及时调整抓取配置。Data页面的/api/v1/status/tsdb接口会给出标签对数量等详细信息这些趋势数据对预判容量问题很有帮助。然后我会给配置文件的变更做一个简单记录。不管是新增采集任务、调整告警阈值还是修改通知路由都在一个文档里记一笔。监控系统的变更经常是低频但高风险的一个看似无害的配置改动可能会在故障时才发现问题有记录才好回溯。还有一点是关于Grafana的版本升级。除非有必须升级的功能或安全修复否则我不会频繁升级。监控系统最怕的是升级后图表显示变了、数据源插件不稳定。即便要升级也建议先导出所有Dashboard的JSON备份再升级万一出问题还能快速回滚。结尾说实话这套监控体系我现在用起来已经形成肌肉记忆了但回头看第一次搭建时的磕磕绊绊还是很想把那些踩过的坑一条条告诉你。Prometheus和Grafana之所以被这么多人选择并不是因为功能堆得最多而是因为整个生态已经把“采集、存储、展示、告警”这件复杂的事拆解得足够清晰你按部就班就能搭出一套能用的系统而每一层又都有足够深的空间去精进。如果你搭建过程中遇到什么奇怪的问题先别急着怀疑工具不行大概率是网络配置、路径挂载或者标签使用上的细节出了偏差。对照这篇文章里讲的检查思路一项项排查基本都能解决。最后再分享一个小技巧监控系统上线后一定要主动制造一次“故障”拉高某个资源的使用率或者停掉一个服务看看告警通知能不能及时到达别等到线上真的出问题时才第一次看到告警长什么样。