Mac上搭建Prometheus+Grafana监控:从安装到告警的完整实践

发布时间:2026/10/17 11:24:26
Mac上搭建Prometheus+Grafana监控:从安装到告警的完整实践
半夜手机振动我爬起来一看那台放在客厅角落里当开发服务器的Mac mini彻底失联了——SSH连不上、Ping不通、之前挂在上面的几个测试服务也全部没了响应。那台机器一直帮我跑着自动化脚本和缓存服务平时没人去碰结果一个偶然的宕机让我意识到一个扎心的事实我根本没有任何手段提前知道它要出事甚至不知道它是几点挂的。在那之后我花了两周时间把Prometheus Grafana这一整套监控体系在Mac OS上完整落了一遍从安装配置、数据采集到面板可视化和告警推送总算把靠感觉盯服务器变成了等通知就行。这篇文章就是把那次落地过程完整拆开来讲。如果你也在Mac上跑开发环境、个人服务器或者自用的小型应用集群想在机器出问题之前收到提醒同时还想直观看到CPU、内存、磁盘这些趋势那这套方案基本是绕不开的标配。我尽量把每一步都讲透包括那些Linux教程里根本不会提到的Mac专属坑。1. 选型复盘为什么偏偏是PrometheusGrafana1.1 传统监控方式哪里不够用在搭这套监控之前我试过几种更轻的方案比如在机器上挂一个定时脚本把系统状态写进日志文件出问题再去翻日志也用过某些商业监控软件的个人版。前者的问题在于日志是写死的文本我只能看到某个时刻的快照没法看趋势更没法在指标异常时自动通知我。后者的问题更直接——大部分监控软件默认按Linux设计Mac版要么功能被砍掉一大截要么就是要把数据传到第三方服务器对于放在家里的设备来说我心里始终不太踏实。Prometheus和Grafana的优点在于它们是完全本地化、开箱可自托管的方案。数据采集和可视化分离Prometheus负责拉取和存储监控指标Grafana负责把指标画成图、做成面板两者通过标准接口对接。也就是说我不用把自己的服务器数据交给任何第三方所有环节都在自己机器上跑这对于隐私敏感或者网络环境受限的场景非常关键。1.2 这套组合的设计哲学Prometheus的核心思想是拉取模型。它不像传统监控那样要求每台机器上的agent主动把数据上报到中心而是由Prometheus服务端按照设定的时间间隔主动去各台目标机器的某个HTTP端口上抓取指标。这个设计带来了三个非常实际的好处第一我随时可以临时加一台采集目标只要它暴露了metrics端口改一行配置就能接入第二服务端如果短暂挂了恢复后依然能继续拉取数据不会因为agent的重试机制产生大量堆积第三要排查某台机器为什么不报数据直接在Prometheus的目标页面上就能看到抓取是否成功不需要跑到每台机器上去看agent日志。它的数据模型也很有意思。Prometheus把一条监控数据定义为一个指标名加一组标签比如node_cpu_seconds_total{cpu0, modeidle}这里指标名是node_cpu_seconds_total标签cpu和mode把一条时间序列拆成了多个维度。查询的时候可以按标签精确匹配、正则匹配也可以把多条序列聚合起来算总量。这种设计在处理服务器监控时非常自然因为你不只是想要CPU使用率是多少还想知道哪个核心更高哪种模式占了最多时间。1.3 什么时候不该用它当然任何工具都有边界。Prometheus老老实实做的是监控指标也就是数值型数据。它不适合存日志也没法做分布式链路追踪。如果你的需求是分析应用访问日志里的异常堆栈或者排查一个请求经过了哪些服务那应该考虑日志系统或链路追踪工具。我不止一次看到有人想把全链路日志硬塞进Prometheus里最后发现查询又慢又别扭。所以这套组合的定位是判断系统是否正常运行、资源是否充足、性能是否劣化。它替你把人肉盯数据这件事自动化了但日志分析、链路排查这些专项问题还是得交给对口的工具。对比维度传统脚本轮询日志Prometheus Grafana数据形态文本快照带标签的时间序列趋势分析很难要自己解析原生支持PromQL直接查告警触发需另写脚本Alertmanager统一处理多机扩展每台单独维护集中配置拉取即接入数据存储本地普通文件内置TSDB带压缩和保留策略这组对比基本能回答为什么要换成这套组合我想要的不是事后翻记录而是事前有趋势、事中有告警。2. Mac环境下的安装关卡2.1 组件清单和安装命令在Mac上装Prometheus、Grafana和采集器最简单的方式是Homebrew。我建议不要手动下载二进制包用brew的好处有两个一是brew services可以帮你注册成后台服务开机自启二是后续升级只需要一条命令不会出现组件版本对不上、配置文件写错路径的问题。开始之前先确认一下芯片架构因为我发现不少教程还在用Intel Mac的路径和参数。终端执行uname -m如果是arm64就是Apple Silicon输出x86_64则是Intel机型。这一步直接影响Homebrew安装的二进制版本好在brew会自动替你选对版本不用太担心但心理要有数。安装三条命令brew install prometheus brew install grafana brew install node_exporter装完之后可以验证一下版本prometheus --version grafana server --version node_exporter --version2.2 三个容易踩的坑接下来这段是重点。我从踩坑中总结出了Mac环境下最常见的三个问题提前知道能帮你省下大半天。第一Homebrew的服务注册方式会创建默认配置文件路径。Prometheus的默认配置在/usr/local/etc/prometheus.ymlIntel或/opt/homebrew/etc/prometheus.ymlApple SiliconGrafana的配置在/opt/homebrew/etc/grafana/grafana.ini。很多教程让你手动创建一个新的yml文件再指定路径然而在Mac上完全没必要直接改brew生成的那份就好这样brew services start prometheus启动时才能找到配置。第二node_exporter默认端口在Mac上可能已经被占用了。它默认监听9100端口而有些软件比如某些局域网共享工具、自建的分布式存储客户端也会占用9100。我那次启动就碰到了端口冲突现象是Prometheus拉取目标时一直显示connection refused。排查命令lsof -i :9100如果被占用修改node_exporter的启动命令加一个--web.listen-address:9101同时把Prometheus里的采集目标端口改成9101。端口本身没有玄学选一个不冲突的就好。第三不要用sudo启动brew services。Mac和Linux不一样很多路径和权限是基于用户级安装的。如果你用sudo把服务注册到系统级反而可能找不到数据目录、日志目录会出现各种各样莫名其妙的权限报错。正确做法就是不加sudo让服务跑在当前用户下存储目录会自动生成在/opt/homebrew/var/下面。2.3 服务启动与验证启动服务的命令很简单brew services start prometheus brew services start grafana brew services start node_exporter启动后逐个验证# Prometheus自带Web界面 open http://localhost:9090 # Grafana界面 open http://localhost:3000 # node_exporter的指标端点 curl http://localhost:9100/metrics | head -20验证采集是否正常最直接的方式是打开Prometheus界面进到Status - Targets页面看到node_exporter那行的State是UP说明抓取链路已经通了。这里有一个小细节Grafana首次启动会让你设置管理员账号密码如果只是本机自用建议设一个和登录账户完全不同的密码避免和系统密码撞车。整个安装过程到这里其实只完成了三分之一。装起来容易真正决定这套监控能不能用起来、能不能坚持用下去的是把采集指标看明白、把面板和告警配好。3. 采集端接入node_exporter在Mac上到底能采到什么3.1 先搞清楚你手里的数据很多人刚装完node_exporter打开http://localhost:9100/metrics看到几千行指标就懵了。这里我建议不要慌指标看着多常用的就那么几个分类。node_exporter在Mac上主要暴露四类核心指标CPU相关node_cpu_seconds_total按CPU核心和模式区分idle、user、system、iowait这些值都在。内存相关node_memory_MemTotal_bytes、node_memory_MemAvailable_bytes、node_memory_MemFree_bytes全部以字节为单位。磁盘相关node_disk_*系列包括读写字节数、IO耗时文件系统容量相关的是node_filesystem_avail_bytes和node_filesystem_size_bytes。网络相关node_network_receive_bytes_total和node_network_transmit_bytes_total按网卡名区分。除此之外还有系统负载、运行时间、文件描述符数量、进程数量等。这中间有个问题值得注意这里看到的是你本机层面的指标并不包含业务应用的内部指标。比如我在Mac上跑了一个自用的缓存服务我想知道它每秒处理多少请求node_exporter是看不到的。那就需要该服务自己暴露一个metrics端点或者我在应用里挂一个Prometheus客户端库。这是另一个话题后面我会简单提一句。3.2 Mac特有的指标采集Mac上有一个Linux教程里很少提到的场景电池和温度。笔记本用户或者带电池的Mac mini用户通常关心这几项node_power_*开头的指标和电池电量相关。温度传感器数据在Mac上受系统权限限制node_exporter默认采集不到需要额外处理。电池信息可以用以下PromQL查node_power_charge_percent这个指标在Mac上取自系统电源管理只要机器支持电池就能直接看到电量百分比。如果你的机器长时间插电当服务器用可以专门告警一下电量低于某个百分比避免突然断电时电池完全没电导致数据损坏。温度这块就比较麻烦。Mac OS的传感器数据受System Integrity ProtectionSIP限制普通用户态程序很难直接读取。我实测过在某些Mac机型上可以读到电池温度但CPU核心温度、主板温度基本拿不到。如果你想监控温度可以另想办法比如某些外部传感器硬件通过USB连接的方案或者直接用powermetrics命令定时抓取再把结果写入文件。3.3 把自定义指标塞进采集链路node_exporter的textfile collector是一个很实用的功能它可以读取指定目录下的所有文本文件把文件里符合Prometheus文本格式的指标合并进采集结果。这相当于给了我们一个第三方数据注入的入口非常灵活。比如我想监控某个自用脚本的运行成功率脚本每次跑完就往/opt/homebrew/var/node_exporter_textfile/写一个指标文件里面内容是这样的# HELP my_script_success_total 记录脚本执行结果 # TYPE my_script_success_total counter my_script_success_total{resultsuccess} 42 my_script_success_total{resultfailed} 3然后在启动node_exporter的参数里加上--collector.textfile.directory/opt/homebrew/var/node_exporter_textfile这样Prometheus抓取这个采集目标时就会把my_script_success_total一并拉取到能做趋势分析也能做告警判断。这个方法的思路就是凡是能转成数字的东西都可以被监控。3.4 围绕这些原始指标的高频PromQL写法数据采集到位之后查询语句是个绕不开的门槛。PromQL看起来有一堆符号但实际常用的就那么几个套路。一、CPU使用率100 - (avg(rate(node_cpu_seconds_total{modeidle}[5m])) * 100)这里用一个减法先算出过去5分钟CPU处于空闲态的平均时间比例再用100减去它得到的就是整体使用率。二、内存使用率(1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100三、根分区磁盘使用率(1 - node_filesystem_avail_bytes{mountpoint/} / node_filesystem_size_bytes{mountpoint/}) * 100四、流量最活跃的网卡topk(3, rate(node_network_receive_bytes_total[5m]))这些查询语句可以直接在Grafana面板里用。我的建议是不要死记硬背把常用那七八条存到自己的笔记里用到就去改改标签比背语法高效得多。4. 从裸数据到可视化面板Grafana的落地细节4.1 先理解Grafana的工作方式Grafana本身不存监控数据它只负责查询和展示。它在页面上发出PromQL查询Prometheus返回数据Grafana再把返回的数据画成折线图、柱状图、仪表盘等等。这个查询-取数-展示的链路理解清楚之后配置起来就顺了。添加数据源的路径是Configuration - Data Sources - Add data source选择PrometheusURL填http://localhost:9090保存即可。没有密码、没有token本机测试环境就是这么简单。4.2 不要从零画图用现成模板起步Grafana社区里有一个Dashboards仓库上面有大量别人做好的面板JSON导入之后几乎不用改就能用。这是我最推荐的上手方式先站在别人的轮子上跑起来再逐步改成自己的形状。在Grafana左侧菜单选择Dashboards - Import输入面板ID或者上传JSON文件即可。社区里和node_exporter相关的知名面板有很多导进来之后你大概率会看到一堆非常详细的图表CPU、内存、网络、磁盘全齐了。导入后要做的第一件事是检查数据源变量是否选对。有些模板默认叫Prometheus如果你的数据源名字不一样在面板设置里把变量值改掉就行。我之所以强调这一句是因为我见过很多人在这一步卡住图全显示No data一看是数据源名对不上。4.3 亲手做一个单机总览面板模板虽然好用但最常见的使用场景还是我只想自己看几个关键指标这种时候自己做反而更快。我的做法是先建一个名为Mac本地监控的Dashboard然后逐个添加Panel。逐个添加其实就是在Grafana里填PromQL语句内容就是我上面列的那些查询。添加第一个CPU使用率Panel时选择时间序列可视化类型查询条件填那段CPU使用率PromQL然后预览。再添加一个内存使用率Panel、一个磁盘使用率Panel基础总览就有了。这一步我有个心得Panel标题直接用中文。Grafana对中文支持很成熟大屏上CPU使用率比CPU Usage一眼扫过去更清楚对家里用和给同事看都很友好。4.4 用变量实现多主机切换如果你以后要从一台机器扩展到多台机器监控强烈建议尽早引入Variables。在Dashboard Settings - Variables里添加一个变量查询类型选Label values标签名选instance这样面板页面上会出现一个下拉框可以选择不同机器的instance。每条面板查询语句里引用$instance100 - (avg(rate(node_cpu_seconds_total{instance$instance, modeidle}[5m])) * 100)切换到另一台机器所有面板的数据会跟着变。这套逻辑理解之后就算以后手头有几十台机器也不需要重复建面板。5. 告警推送从盯盘变成等通知5.1 为什么光是面板还不够说实话面板只解决了想看的时候能看到的问题真正让监控体系产生价值的是告警。面板开着的时候你会主动去看但如果你恰好在睡觉、在开会、或者在忙别的事一台机器悄悄出问题你依然没法感知。告警的意义就是把这层人肉盯着的负担完全卸掉。Prometheus生态里的告警组件叫Alertmanager它会接收来自Prometheus的告警消息然后按你设定的路由规则把消息推到邮件、Webhook、即时通讯应用等目的地。5.2 写一条实用的告警规则告警规则写在Prometheus配置文件里通过rule_files字段引入。我在/opt/homebrew/etc/prometheus/下建了一个alerts.yml内容如下groups: - name: mac_local_alerts rules: - alert: InstanceDown expr: up 0 for: 1m labels: severity: critical annotations: summary: 实例 {{ $labels.instance }} 已下线 description: 该实例超过1分钟无法抓取请检查进程和端口。 - alert: DiskUsageHigh expr: (1 - node_filesystem_avail_bytes{mountpoint/} / node_filesystem_size_bytes{mountpoint/}) * 100 85 for: 5m labels: severity: warning annotations: summary: 根分区使用率超过85% description: 当前使用率已经达到 {{ $value }}%建议清理文件或扩容。然后在prometheus.yml里加上rule_files: - /opt/homebrew/etc/prometheus/alerts.yml修改完配置文件后重启Prometheus服务brew services restart prometheus配置语法有两点值得注意一是for字段表示持续多久才触发它能过滤掉瞬时抖动造成的误报二是up 0里的up是一个系统自动生成的指标值为1表示抓取成功为0表示抓取失败。这个指标是排查任何采集问题时的重要线索。5.3 配置Alertmanager和通知渠道Alertmanager也需要单独安装brew install alertmanager brew services start alertmanager它的配置文件在/opt/homebrew/etc/alertmanager.yml。我在里面配置了一个Webhook地址这样告警可以自动推送到我常用的协作软件上。route: group_by: [alertname] group_wait: 10s group_interval: 10s repeat_interval: 1h receiver: webhook receivers: - name: webhook webhook_configs: - url: http://localhost:8000/alert send_resolved: true然后在Prometheus主配置里把Alertmanager地址告诉它alerting: alertmanagers: - static_configs: - targets: [localhost:9093]这里的send_resolved: true表示告警恢复之后也推一条通知能形成完整闭环出问题收到一条恢复后再收到一条不会悬念留到第二天。5.4 防止告警变成噪音配置完告警之后最常遇到的问题就是告警轰炸。磁盘使用率超过阈值之后如果不做处理Alertmanager会按配置的间隔反复推送相同告警几个小时后你的手机通知栏就沦陷了。这里有三个层面可以控制第一规则里的for字段。如果只是一个瞬时峰值持续10秒就没影了那就不该触发告警。我通常设置1到5分钟保证告警确实代表一个问题存在。第二Alertmanager路由里的group_wait和repeat_interval前者控制同一类告警首次聚合的等待时间后者控制重复通知的间隔。我把重复间隔设为1小时避免深夜连续轰炸。第三也是最实用的告警规则里尽量只写需要人处理的场景不要追求大而全。比如CPU使用率超过95%持续10分钟才值得告警而CPU使用率超过50%这种平时就常见的状态不该设成告警它更适合放在面板里看趋势。6. 跑了半年之后总结出的Mac专属坑6.1 休眠、时间漂移和数据缺口Mac作为监控服务器最典型的坑就是系统休眠。默认情况下Mac闲置一段时间后会自动进入睡眠状态网卡停止响应Prometheus这边自然就抓不到数据了图表上会形成一个大缺口。更麻烦的是从睡眠唤醒后有些系统统计指标会清零或者跳变比如node_boot_time_seconds会更新某些累计计数器会重置。解决办法分两个层面一是如果这台机器的工作就是当服务器可以在系统设置 - 电池 - 电源适配器里把防止自动休眠打开或者调整硬盘睡眠时间为永不。二是如果机器确实需要偶尔休眠省电那就要接受数据缺口同时让告警规则能容忍这种中断——比如不给up 0配太短的for时间否则每次休眠都会触一遍告警。时间漂移是另一个容易被忽视的问题。Mac如果长时间运行且没有开启网络时间同步系统时间和真实时间偏差会越来越大Grafana图表的时间轴会跟着错位。解决方式是在系统设置 - 通用 - 日期与时间里打开自动设置时间和日期确保系统有时间服务器可用。6.2 资源开销小内存机器怎么撑住Prometheus本身是Go写的内存占用看数据量。只监控一台本地机器、默认抓取间隔15秒的情况下Prometheus的进程内存通常在300MB到500MB之间Grafana会再占一部分内存整体加起来接近1GB。如果你的Mac是8GB内存还跑着其他开发工具会明显感觉到压力。我当时的处理手段是把prometheus.yml里的scrape_interval从15s改为30s数据量直接减半内存占用也降了一截。调短数据保留时间在启动参数里加--storage.tsdb.retention.time15d只保留15天的数据。对于本地个人监控来说15天完全够用再早的数据基本不会翻回去看。给node_exporter限制采集器数量禁用掉用不到的内核锁、压力统计等收集模块减少无效占用。这一套下来Prometheus加Grafana的总内存占用大概能降到500MB出头在8GB机器上终于能安心常驻了。6.3 服务升级和数据备份的节奏Homebrew升级时会顺手把Prometheus和Grafana更新但有一个隐患新版配置文件的默认行为可能变化不兼容旧的告警规则语法。我在一次大版本升级中遇到过告警规则格式不兼容的情况现象是Prometheus启动后一直报规则文件解析错误。后来我的做法是升级前先备份prometheus.yml和alerts.yml然后在本地开一个测试实例用相同参数启动新版看看有没有报错。确认没问题再brew services restart。备份Prometheus自身的时序数据也有必要毕竟那些历史趋势图是慢慢积累出来的。数据存储在/opt/homebrew/var/prometheus/直接把这个目录定期拷贝到移动硬盘或网络备份盘就行。这套监控体系跑了大半年我最大的体会是它不是给你增加麻烦的而是替你把担心这件事自动化了。现在每次手机收到告警我心里都不会慌因为知道是Prometheus已经确认了问题持续存在才推给我而不是随机提醒。如果你也在Mac上跑着自己的项目建议就从今天开始装一套先只采集指标、做张简单的面板跑通之后再慢慢加告警。数据不会骗人趋势会比直觉更早告诉你机器哪里不对劲。