1. 项目背景一个连名字都没起好的项目为什么会做起来先说个真实情况这个项目最初的名字就叫“这是一个标题”——不是故弄玄虚而是当时确实没想好叫什么需求也只有一个模糊的方向给手头几台经常出幺蛾子的服务器加一套能及时发现问题、主动报警的监控。项目从立项到写出第一行代码只花了不到半小时因为大家心里都清楚真正难的不是写代码而是想明白到底要监控什么、怎么报警才不会吵死人、出了问题怎么才能快速定位。如果你也维护过三五台服务器、跑过几个业务脚本大概率体会过这种状态白天一切正常凌晨三点某个进程悄悄挂了第二天用户反馈才被动发现磁盘空间慢慢被日志撑爆直到写入失败才惊慌失措CPU飙到 100%你登上去的时候已经卡得敲命令都要等半天。这些问题的共性是没有监控全靠事后补救。所以这个项目最终要解决的事情很朴素——在一台资源不算宽裕的轻量服务器上搭一套能采集、能存储、能可视化、能主动通知的监控报警系统把“被动救火”变成“提前预警”。整个项目用到的核心组件是 Prometheus、Grafana、Node Exporter 和 Alertmanager部署方式走的是 Docker Compose面向的读者是那些已经有了几台服务器、想自己搭监控但还没理清组件关系的人。文章会讲清楚每个组件为什么存在、配置怎么写、踩过哪些坑、报警规则怎么定才不会被误报淹没最后提供一个可以直接抄作业的完整方案。2. 整体架构设计从“一个标题”到一张清晰的组件关系图2.1 为什么选 Prometheus 这套组合而不是其他监控方案在选型之前我把市面上的方案粗略过了一遍云厂商自带监控、Zabbix、Prometheus 全家桶。云厂商监控最省事但每台机器都要装 agent而且很多指标要额外付费数据导出也受限换了云厂商就得重新搞一套绑定太深。Zabbix 是老牌选手擅长设备监控和复杂告警但部署偏重配置文件写起来不够灵活图形化展示也不是它的强项。Prometheus 这套组合之所以胜出核心原因有三个。第一采集模型是“拉取式”的。Prometheus 定期主动去抓取目标暴露的指标接口而不是像传统方案那样由 agent 把数据推给服务端。这个区别在实际运维中很有价值你只要保证目标端口的 /metrics 接口可访问Prometheus 这边配置好目标地址就能采集新增一台机器就是加几行配置的事不用在每台机器上都折腾安装包和重启服务。第二指标数据模型统一且自带标签机制。Prometheus 把每一条数据都抽象成指标名加一组键值对标签比如 cpu_usage{hostnode1, core0}这种设计让数据查询和聚合变得非常灵活分组、过滤都靠标签完成不用像关系型数据库那样写一堆 GROUP BY。第三生态完整。采集层有各种 Exporter存储层有自带的时间序列数据库告警层有独立的 Alertmanager可视化层可以和 Grafana 无缝对接每个环节都有成熟方案不用自己造轮子。当然这并不代表 Prometheus 没有缺点。它的数据是本地存储在单机上的想搞长期归档或者大规模集群还得接远程存储对于只有几台服务器的小规模场景这一点根本不是瓶颈所以选它完全合理。2.2 四个组件各司其职谁先启动谁后启动很关键这套架构里的四个角色从一开始就要把它们的职责边界划清楚Node Exporter跑在被监控机器上负责收集操作系统层面的原始指标比如 CPU 使用率、内存占用、磁盘空间、网络流量、文件系统状态然后通过 HTTP 接口暴露出来。它本身不存储数据也不做任何判断只负责“采”和“露”。Prometheus核心中枢负责按照配置的规则周期性去各台机器的 Node Exporter 拉取数据存进自带的时间序列数据库同时根据告警规则持续做判断条件满足就生成一条告警事件推给 Alertmanager。它负责“存”和“判”。Alertmanager处理 Prometheus 推过来的告警事件负责去重、分组、静默、限流然后通过配置好的接收器邮件、Webhook、钉钉机器人把消息发出去。它负责“管”和“送”。Grafana纯粹的数据展示层从 Prometheus 里读数据绘制成各种图表和仪表盘解决“数据看到了但不直观”的问题。它只负责“看”。这个依赖关系决定了启动顺序Node Exporter 先起来Prometheus 等它起来了再去抓Alertmanager 要先于 Prometheus 的告警规则生效前就位否则告警推过来没人接Grafana 最后起因为它只是去查询别人已有的数据。用 Docker Compose 管理时虽然依赖设置不能百分之百保证容器内部服务就绪但配置好 depends_on 至少能控制容器启动的顺序避免 Prometheus 启动时抓不到目标而报一堆连接错误。3. 采集端部署与指标解读Node Exporter 的完整落地细节3.1 在不同环境下的部署方式对比Node Exporter 的部署方式取决于被监控机器的情况。如果目标机器本身就是 Docker 环境直接用一个轻量容器跑起来最省事但要注意一个小细节容器里的 Node Exporter 要看到宿主的文件系统和网络状态必须挂载宿主的 /proc、/sys 等目录而且网络模式要用 host这样才能拿到真实的主机指标而不是容器自己的受限视图。如果目标机器是裸金属或者没有装 Docker 的系统那直接下载二进制文件用 systemd 托管是最干净的方案。我在实际部署中更推荐二进制加 systemd 的方式因为 Node Exporter 本身是一个静态编译的二进制文件没有任何依赖拷贝过去就能跑占用内存大约 20MB对一个资源紧张的服务器来说几乎可以忽略。systemd 的好处是开机自启、崩溃自动拉起、日志统一管理这些都是容器方式需要额外配置才能达到的效果。如果你有十台机器挨个手动部署确实烦人可以准备一个简单的安装脚本把下载、校验、安装 systemd 单元文件、启动的流程串起来十几秒就能搞定一台。3.2 采集到的核心指标都代表什么怎么用不踩坑Node Exporter 默认暴露的指标非常多大多数人并不需要全部关心重点盯住几类就够用了node_cpu_seconds_total这是 CPU 时间的累计值注意是 counter 类型一直在增长。使用时必须用 rate() 函数做变化率计算才符合直觉比如 rate(node_cpu_seconds_total{modeidle}[5m]) 表示过去 5 分钟空闲时间的比例用 1 减去它才是使用率。直接查询原始值会得到一个持续变大的数没有任何业务含义。node_memory_MemTotal_bytes / node_memory_MemAvailable_bytes内存总量和可用量单位是字节。查询时要除以 1024 的三次方换算成 GB或者直接在 Grafana 里设置单位否则看到一长串数字很难受。这里有个经典误区不要用 MemFree 判断内存余量因为在 Linux 里已经被缓存占用但可以随时释放的内存对应用来说仍然是可用的MemAvailable 才是内核根据回收成本算出来的真实可用值。node_filesystem_avail_bytes文件系统可用空间做磁盘告警时一定要按挂载点分组过滤把 tmpfs、overlay 这类虚拟文件系统排除掉。我在最开始写磁盘告警规则时没过滤结果 tmpfs 因为容量小动不动就触发告警后来才发现这类文件系统增长正常不应该纳入监控范围。node_network_receive_bytes_total / node_network_transmit_bytes_total网络收发累计字节数同样是 counter 类型必须配合 rate() 才能看出实时速率。判断网卡是否正常时可以用一个固定窗口观察基线值如果长时间断崖式下跌大概率是物理链路或带宽限速出了问题。这些指标类型是理解 PromQL 查询的基础。简单说counter 类型的指标只增不减适合用 rate 求速率gauge 类型的指标可增可减直接查询就是当前值。很多查询不达预期问题都出在把 counter 当 gauge 用。3.3 Node Exporter 的 systemd 托管配置模板如果选择二进制部署systemd 单元文件建议按下面这样写。需要注意的有三点User 指定为普通用户不要用 root 跑 ExporterExecStart 里加 --collector.systemd 可以额外收集 systemd 服务的状态方便后面监控某个关键进程是否存活Restartalways 加上 RestartSec10 能让进程在意外退出后十秒自动拉起相当于多了一层保障。[Unit] DescriptionNode Exporter Wantsnetwork-online.target Afternetwork-online.target [Service] Usernode_exporter Groupnode_exporter Typesimple ExecStart/usr/local/bin/node_exporter --collector.systemd --web.listen-address:9100 Restartalways RestartSec10 [Install] WantedBymulti-user.target配置好后依次执行 daemon-reload、enable、start再用 curl 访问本机 9100 端口的 /metrics 接口看到大量以 node_ 开头的指标就说明采集端已经就绪。如果访问不到先检查端口有没有被防火墙拦住再确认进程是否真的起来了这是最常见的两个原因。4. Prometheus 配置和告警规则核心中枢的完整拆解4.1 采集配置里最容易忽略的细节Prometheus 的采集配置写在 prometheus.yml 里构成了整个监控系统的心脏。给出一个可直接使用的例子global: scrape_interval: 15s evaluation_interval: 15s alerting: alertmanagers: - static_configs: - targets: - alertmanager:9093 rule_files: - /etc/prometheus/alerts.yml scrape_configs: - job_name: node static_configs: - targets: - 192.168.1.11:9100 - 192.168.1.12:9100 labels: env: productionscrape_interval 是抓取周期evaluation_interval 是告警规则评估周期这两个值可以不同但为了直觉上容易理解可以设成一样。实际使用中抓取周期不要低于 5 秒频繁的抓取对目标机器是额外的 I/O 负担对 Prometheus 本身的存储写入压力也会翻好几倍收益却很小。labels 的作用不能小看它可以按环境、可用区、业务线给目标机器打上标签后面写告警规则和查 Grafana 面板时这些标签就是分组过滤的维度。还有一个细节是 job_name 的命名。它会被自动加为指标的一个标签叫 job。规范命名非常重要比如把生产环境的 job 起名为 node_prod、预发环境的叫 node_staging或者干脆用 labels 区分都可以。否则所有机器在一个 job 下想单独看某个环境的资源使用情况就要写很多正则过滤器麻烦得很。4.2 告警规则的正确写法从报警疲劳到精准触达告警规则文件是这套系统里最考验经验的部分。写得好是预警利器写得差就是通知轰炸器。最经典的三个规则如下groups: - name: node_alerts rules: - alert: HostHighCpuUsage expr: (1 - avg(rate(node_cpu_seconds_total{modeidle}[5m])) by (instance)) * 100 85 for: 10m labels: severity: warning annotations: summary: {{ $labels.instance }} CPU 使用率过高 description: 当前 CPU 使用率已达 {{ $value | humanizePercentage }}持续时间超过 10 分钟。 - alert: HostDiskAlmostFull expr: (node_filesystem_avail_bytes{fstype!~tmpfs|overlay} / node_filesystem_size_bytes{fstype!~tmpfs|overlay}) * 100 15 for: 5m labels: severity: critical annotations: summary: {{ $labels.instance }} 磁盘空间不足 description: 挂载点 {{ $labels.mountpoint }} 可用空间剩余不足 15%。CPU 告警里用 avg by (instance) 是取单台机器所有核心的平均使用率如果有的机器是多核某一核跑满但整体没超阈值这种算法可能看不出问题这时可以用 max by (instance) 把单核最高使用率暴露出来。用哪个取决于你的业务类型在线请求类服务看平均更合理批处理任务看单核更靠谱。for: 10m 这个参数极易被忽略。它表示指标条件持续满足 10 分钟后才真正触发告警目的是过滤瞬时抖动。比如某次 GC 导致 CPU 短暂冲高几秒就恢复了如果没有 for 条款系统会立刻告警造成打扰。但 for 也不能设太长时间越长发现问题越滞后一般 5 到 10 分钟是合理区间。磁盘告警里最关键的是 fstype!~tmpfs|overlay 这个正则过滤。tmpfs 是内存文件系统它的大小本来就是动态的overlay 是容器镜像层这类虚拟文件系统不适合参与磁盘告警。去掉这个过滤你会发现 /run、/var/run 这类小配额目录整天报磁盘满实际业务磁盘却很健康告警疲劳就是这么来的。4.3 Prometheus 查询请先搞懂 rate、irate 和 increase 的区别写告警规则和做图表都离不开 PromQL最常见的三个函数 rate、irate、increase 让很多人犯迷糊这里一次性说清楚。rate 和 irate 都是计算 counter 类型指标的变化率区别在于 rate 取的是时间区间内首尾两个点的差值除以区间长度得到的是这个窗口内的平均速率曲线平滑irate 取的是区间内最后两个数据点的差值除以时间间隔得到的是瞬时速率曲线毛刺多对突发情况更敏感。increase 则是计算整个时间区间内 counter 的增长量相当于把速率乘以了区间长度。选型建议做告警规则用 rate因为告警需要稳定趋势而不是剧烈波动irate 很容易导致误报做实时流量监控图可以用 irate 配合短窗口能更快反映当前状态。increase 一般用于统计总量变化比如“这台机器今天接收了多少网络流量”不适合作为判断是否异常的手段。理解了这三个函数PromQL 就算入门了一半。5. 告警通知与可视化落地Alertmanager 和 Grafana 的实操记录5.1 Alertmanager 配置分组、抑制、路由一个都不能少Alertmanager 存在的意义不只是把告警转发出去它承担了更重要的职责防止告警轰炸。如果每台机器每项指标不满足条件都各发一条消息几百条通知同时涌进手机的时候你会关了所有通知系统彻底失去意义。合理的做法是分组和路由。我的配置思路是这样的同一台机器上同时有多条告警触发时只在分组里发一条消息把多个告警标题拼在一起不同机器的相似问题按机器名拆分成不同消息保持可读性如果已经有严重告警在被处理同机器的其他次要告警可以抑制避免重复打扰。这些逻辑都可以在 Alertmanager 的 route 和 inhibit_rules 里实现。接收端的配置用的是 Webhook 加钉钉机器人因为没有单独部署邮件服务器的成本。钉钉机器人只需要一个 Webhook 地址Alertmanager 官方没有内置钉钉的接收器所以用了一个通用的 webhook 服务把 Alertmanager 发来的 JSON 转成钉钉支持的消息格式。这个转换服务就是一个很轻量的 Python 脚本监听一个端口收到 POST 请求就转发到钉钉 Webhook部署起来比想象中简单还不用引入额外的开源组件。如果想从零开始配置一个要点是 alertmanager.yml 里 receivers 与 route 的对应关系。route 规定哪类告警走哪个 receiverreceiver 定义具体怎么发。初学者最容易犯的错是只配置了 receiver 没把它写进 route结果告警倒是生成了消息却发不出去。5.2 Grafana 仪表盘数据都采集了你还得让它看得懂Grafana 是这套系统里观感提升最明显的一环。它本身不采集数据只是个查询展示工具天生适配 Prometheus。我的仪表盘配置有三块主机总览、核心指标明细、告警状态看板。主机总览放最常用的几个面板CPU 使用率、内存余量、磁盘空间和网络流量核心指标明细用下拉框做实例切换方便对比不同机器告警状态看板直接查 ALERTS 这个内置指标能看出当前有哪些活跃告警配合日志用效果很好。Grafana 里设置 Prometheus 数据源时URL 填 http://prometheus:9090 这种容器内主机名但要注意如果 Grafana 和 Prometheus 不在同一个 Docker 网络里这个主机名是解析不了的。直接填 IP 地址永远是最保险的方式。导入面板后很多官方分享的模板拿来就能用但也不要迷信官方模板的指标用的是同一个 Exporter 的字段名版本兼容性一般没问题最怕的是指标已经被自己写的容器方式暴露路径改过匹配不上就全部显示 No Data这时候先检查数据源的 query 和采集目标不要急着改面板。数据存储方面Prometheus 的本地存储清理是一件需要主动做的工作。默认的存储方式会把时间序列数据写进 data 目录时间长了磁盘占用不断上涨但 Prometheus 本身提供数据保留期配置在启动参数里加 --storage.tsdb.retention.time15d 和 --storage.tsdb.retention.size10GB分别表示保留 15 天的数据和最多占用 10GB 磁盘超过的部分会被自动清理。设置了这一层才不用天天盯着数据目录的膨胀速度。6. Docker Compose 编排一套命令拉起的完整监控栈6.1 编排文件的完整样例与网络配置把四个组件串起来最省心的方式就是 Docker Compose。我用的编排文件大致如下核心思路是保证四容器在同一网络里数据文件挂在宿主机目录上防止容器重建丢数据Prometheus 和 Alertmanager 的配置文件也挂出来方便改动version: 3.8 services: node-exporter: image: prom/node-exporter:latest container_name: node-exporter command: - --path.rootfs/host network_mode: host pid: host restart: unless-stopped volumes: - /:/host:ro,rslave prometheus: image: prom/prometheus:latest container_name: prometheus restart: unless-stopped ports: - 9090:9090 volumes: - ./prometheus.yml:/etc/prometheus/prometheus.yml:ro - ./alerts.yml:/etc/prometheus/alerts.yml:ro - prometheus-data:/prometheus command: - --config.file/etc/prometheus/prometheus.yml - --storage.tsdb.path/prometheus - --storage.tsdb.retention.time15d - --storage.tsdb.retention.size10GB alertmanager: image: prom/alertmanager:latest container_name: alertmanager restart: unless-stopped ports: - 9093:9093 volumes: - ./alertmanager.yml:/etc/alertmanager/alertmanager.yml:ro grafana: image: grafana/grafana:latest container_name: grafana restart: unless-stopped ports: - 3000:3000 environment: - GF_SECURITY_ADMIN_PASSWORDyour_strong_password volumes: - grafana-data:/var/lib/grafana volumes: prometheus-data: grafana-data:Node Exporter 用了 network_mode: host 和 pid: host这是让它拿到主机真实数据的两个前提。pid: host 保证它能看到宿主机上的所有进程个数path.rootfs 挂载让它可以读取宿主根目录的文件系统信息。Prometheus 和 Grafana 的端口都映射到了宿主机号段选择不冲突即可。注意 Grafana 的初始密码环境变量只在第一次启动时生效之后改了它也不会更新认证方式这是安全上的一个坑上线前必须改掉默认密码。6.2 数据持久化与升级注意事项数据卷的作用在容器升级时特别明显。刚开始部署的时候我没用命名卷而是把数据直接放在容器层运行一段时间后 Prometheus 升级容器被重建收集的时序数据全部消失等于监控从头开始积累。后面改成命名卷后哪怕是删除容器重新创建数据依然完好这一点在长期运行的项目里必须在一开始就做好。升级镜像时也要注意版本兼容。Prometheus 和它的配置文件结构存在持续调整有时候新版本会废弃旧的配置项。按照我的经验升级前先在测试环境用新镜像启动一遍看日志有没有 warning 级别以上的报错再决定是否替换生产容器。虽然多花一点时间但能省去回滚的麻烦。7. 常见问题与排查技巧实录这台机器还没旧到能报修7.1 目标挂了却不触发告警问题出在哪有次同事反馈某台机器明显已经宕机了Prometheus 的 UI 里看 target 显示 DOWN但手机却没有收到任何告警消息。排查一圈发现问题出在告警规则本身我只配了 CPU、磁盘这类指标做阈值判断但这一类指标在目标机器挂了之后根本采集不到数据Prometheus 在查询时遇到“没有数据”的情况不会返回数值所以告警条件永远不成立就不会触发告警。解决方法是单独加一条“Up 指标为零”的规则。Prometheus 会给每个采集目标生成一个特殊的合成指标 up目标正常时值为 1抓取失败时值为 0。所以规则可以这样写- alert: InstanceDown expr: up 0 for: 2m labels: severity: critical annotations: summary: 实例 {{ $labels.instance }} 已停止响应这条规则几乎可以覆盖所有“目标无响应”的场景比监控单个进程是否存活的指令更可靠因为进程可能一直跑着但采集接口已经因为网络或端口问题断开了。从此之后多写一条 up 规则成为我构建任何监控面板的默认动作。7.2 告警重复轰炸与消息延迟分组和超时的取舍另一个低频但头疼的问题是告警没有按预期分组同一时间多条类似告警会来好几条通知。刚开始我在 Alertmanager 的 route 配置里没有设置 group_by默认情况下所有告警都收到同一个分组一条消息里堆了几十条告警看起来信息很全但实际很难看清是哪个实例的哪个问题。后来我改成按 instance 分组每条消息保持清晰的单一问题语境虽然消息数量增多了但每条都有用可读性大幅提升。消息延迟方面Alertmanager 有 group_wait 和 group_interval 两个参数。group_wait 表示一组新的告警等待时间默认 30 秒在这段时间内如果同一分组有更多告警到达它们会被合并进同一条消息里再发出去适合批量问题的场景。group_interval 表示已存在的告警组再次检查的间隔默认 5 分钟。这个值会导致一个问题当记忆中的告警已经恢复时恢复通知可能延迟到下一个周期才发出。如果业务对通知时效要求高可以把 group_interval 调短到 1 分钟代价是收到的通知更频繁。按需权衡没有标准答案。7.3 时间数据错乱或缺失检查时区和抓取间隔部署完成后检查 Grafana 面板发现两条很诡异的记录一是时间轴显示的时间比本机时间快了整整 8 小时二是某些数据点呈锯齿状一会儿高一会儿低。第一个问题的原因很明确Prometheus 内部一律使用 UTC 时间存储数据Grafana 在展示时默认会按浏览器的时区换算如果浏览器时区设置不对看起来就存在偏移。Grafana 面板右上角的 Time zone 设置改成 UTC 或者浏览器自动模式一般就能解决显示问题。第二个问题则出在我自己的抓取间隔配置。我最初为了实时性把 scrape_interval 设为 5s但告警评估周期是 15s数据点的采集密度和查询窗口不匹配画出图来曲线自然呈阶梯状。后来统一把抓取和评估都设成 15 秒曲线平滑了很多。注意PromQL 里的区间向量时长最好大于等于两倍的抓取间隔这样每个窗口内至少有两个数据点计算的速率才有足够的样本支撑结果也有意义。这是个容易踩的坑尤其在查询结果出现 No Data 或明显抖动时要先检查这里。7.4 快速定位问题的自检清单基于这些经验我把常见的监控故障排查整理成一张速查表遇到问题时按顺序检查基本能覆盖九成的情况现象排查思路常见原因采集目标显示 DOWNcurl 目标 9100 端口检查 /metrics 是否能访问防火墙拦截、Node Exporter 进程未启动、网络不通有告警但没收到通知查看 Alertmanager UI 的 Alerts 页面看告警状态是否为 Firing 且 receiver 是否正确route 未关联 receiver、Webhook 或钉钉地址失效、分组等待时间没过面板显示 No DataPrometheus UI 里手动执行一次查询确认指标名正确数据源 URL 写错、时间范围选错、指标标签过滤写错图表时间偏移 8 小时检查 Grafana 面板时区和浏览器时区时区设置不一致不影响数据准确性只影响显示磁盘占用持续上涨查看 Prometheus data 目录大小和保留策略参数未设置 retention 参数或设置无效导致数据积压这张表是我踩完坑之后整理的每次排查问题先过一遍能节省大量翻日志的时间。8. 实际踩坑记录与经验总结8.1 一张表收集的运维黑历史做这个项目前后踩过的坑几乎每个都是典型的“文档没写但实际会遇到的”问题。这里系统整理一下能给后来者省下不少时间。踩坑场景错误做法正确做法影响等级容器化部署 Node Exporter使用默认网络模式和路径挂载network_mode: hostpid: hostrootfs 挂载高否则采集的是容器内部指标磁盘告警规则未排除 tmpfs 和 overlay 文件系统fstype 正则过滤虚拟文件系统中误报频繁判断目标是否存活只监控 CPU 或内存指标增加 up 0 规则单独判断高目标挂掉时其他规则全失效数据持久化未使用命名卷prometheus-data、grafana-data 命名卷高容器重建数据全丢告警通知消息过多所有告警塞在一个分组按 instance 分组设置合理的 group_wait中告警疲劳导致通知被忽略告警间隔过长group_interval 保持默认 5 分钟时效敏感时调短到 1 分钟中恢复通知延迟查询窗口过短跟抓取间隔相同甚至更短窗口至少两倍抓取间隔低数据点不足结果不平滑Grafana 时区混乱浏览器时区不一致面板显示 UTC 或固定脚本时区低仅显示问题8.2 告警阈值的动态调优方法告警规则里最难的不是语法而是阈值定多少。阈值定太严系统天天狼来了最后没人看定太松真出问题时不报警形同虚设。我的方法是先观察一星期的基线数据把高水位和低水位统计出来设置阈值时留出百分之二十的余量。比如日常 CPU 平均使用率稳定在 30% 到 45%那告警阈值设在 80% 更合适而不是 60%否则一个正常的业务高峰就会误报。磁盘空间的阈值相对静态可以直接按剩余容量比例定但要根据日志增长速度做预估比如日志每天涨 2GB磁盘只有 50GB那 15% 的剩余空间其实只够用不到四天最早可在剩余 30% 时触发提醒级别告警15% 触发严重告警留给运维人员足够处理时间。阈值调优没有一劳永逸的方案业务量在变基线也在变。每季度拿最近一个月的指标重新看一下及时调整比任何时候都可靠。8.3 一个小细节告警消息模板里要带上什么信息告警消息模板越完善收到告警后的处理效率就越高。这点亲身经历过最开始只发了一条“CPU 使用率过高”的通知人到服务器前才发现连哪台机器、什么时候开始的、当前值是多少都不知道还得自己手动查。后来模板里加上实例名、持续时间、当前值、阈值、告警级别再附上一个到 Grafana 面板的跳转链接处理效率完全不同。以下是我的建议模板结构[告警] 实例 192.168.1.11 磁盘空间不足 级别: critical 当前状态: 挂载点 /data 可用空间剩余 8%低于阈值 15% 触发时间: 2024-XX-XX 10:23:00已持续 12 分钟 查看面板: http://grafana.example.com/d/xxxx一条包含这些字段的告警已经足够让值班人员在手机上一眼判断出问题的重要性、位置和紧急程度很多时候可以不打开电脑直接决定是加强关注还是马上处理。这个模板设计上的收益远超想象的投入。9. 部署完成后我还做了哪些事9.1 把历史数据盘了一遍确认监控覆盖到“该关心的东西”监控系统上线后我先用 PromQL 把近七天所有机器的核心指标跑了一遍不是为了验证监控本身而是为了发现那些我以为正常但实际不正常的指标。不看不知道有一台机器的网络接收流量每天凌晨都会出现一个尖峰持续十几分钟平时完全没注意过排查后才发现是一个定时任务在凌晨拉取大量更新包尖峰完全合理。通过这样的数据盘查能对现有业务有一个更客观的认识也为后续告警阈值设定提供了参考基础。这个习惯后来一直保留着新系统上线、业务版本大更新后花十分钟翻一翻监控数据确认基线和预期一致顺便看看有没有异常趋势出现比事后再排查节省大量时间。9.2 加了一个“自监控”任务监控系统本身也可能出问题比如 Prometheus 进程挂掉了所有采集和告警都停止那谁来告诉运维监控挂了这个问题非常现实。我在 Prometheus 自身上也配置了一个简单的探测规则定期去检查 Prometheus 自己的 /-/healthy 接口。这样 Prometheus 还活着的时候它能通过告警规则发现 Web 接口异常并推送出去如果 Prometheus 进程整个挂了至少还有 systemd 的 Restartalways 兜底能在进程退出后自动拉起来。这也算是一个朴素的“监控替身”方案。10. 这个项目后续还能怎么扩展因为我当时的需求只是一个基础的监控报警所以没有继续做太多扩展。但如果你基于这套基础继续往下走有几个方向性价比很高。一个是增加更多 Exporter。目前只覆盖了主机层面的指标如果跑着 MySQL、Nginx、Redis各自的 Exporter 可以补齐应用层的监控盲区。每个 Exporter 的接入方式都类似配置好采集目标和告警规则即可成本很低。另一个是接入日志监控。Prometheus 本身不擅长日志分析但如果日志里有明显响应异常可以考虑配合 Loki先把日志采集做起来再设定简单的关键字告警规则形成“主机指标加应用指标加日志告警”的三层监控结构。第三个方向是自动化部署和回滚。现在这套方案还是手工在服务器上执行 docker compose up -d如果机器数量再多一点可考虑用自动化工具把配置分发和启动流程批量管理起来。只要做好基础编排文件的幂等性就能实现新机器几十秒内自动接入监控体系。对我来说当初从零搭建这套系统的最大收获不只是那几块数据可视化面板而是理解了监控运维中组件协作的逻辑——每个组件都做得很窄但拼起来就是一个可靠的预警网络。这也是建议你从这套组合开始上手的原因。
阅读完成 · 觉得有帮助?