监控Linux系统状态,从最原始的时候登录服务器敲top、df -h、free -m,到后来写脚本定时采集数据,再到折腾各种监控面板,这条路我基本都走过。如果你手里也有一批CentOS服务器,肯定遇到过这样的场景:业务方反馈系统卡了,等你登录上去负载又降下来了,什么证据都没留下;又或者是磁盘空间早就悄悄满了,直到告警电话打过来才发现。Prometheus搭配Node Exporter这套组合拳,解决的就是这类后知后觉的问题。这篇文章我会从方案选型、部署步骤、指标解读到告警配置完整梳理一遍,适合正在搭建基础监控、准备把Linux运行状态收进Prometheus的运维和开发同学参考。
1. 监控方案设计与核心思路
1.1 为什么选择Prometheus + Node Exporter
很多人在选监控方案的时候会纠结:用传统的Agent模式还是Prometheus这种拉取模式?我的结论很简单:如果你已经决定用Prometheus,那就别再犹豫,Node Exporter就是采集Linux系统指标最标准、最省心的选择。
Prometheus的监控模型是“服务端主动拉取”。被监控的机器上跑一个Exporter,它把系统状态变成HTTP接口上的指标数据,Prometheus按你配置的间隔定时去抓取。和传统的推模式相比,拉模式的最大好处是你随时能在监控端查看某台机器“当前还活着没有”,如果拉不到数据,那本身就是一条非常有用的告警信号。
Node Exporter是Prometheus官方维护的系统指标采集器,它通过读取/proc、/sys下的内核统计文件,把CPU、内存、磁盘、网络、文件系统、负载等几百项指标全部暴露出来。你不需要在被监控机器上安装额外的数据库或复杂的Agent服务,一个二进制文件加一个systemd服务就搞定,资源占用可以忽略不计。
1.2 监控拓扑与采集流程
整套系统的数据流是这样的:每台CentOS服务器上运行Node Exporter,监听9100端口,通过/metrics接口暴露指标;Prometheus服务器定期从这些目标抓取数据,按时间序列存储下来;Web UI和Grafana通过PromQL查询语句把数据变成面板和图表;告警规则一旦触发,就交给Alertmanager去通知。
刚开始搭环境的时候,你只需要一台机器同时跑Prometheus和Grafana做展示端,被监控的服务器单独跑Node Exporter,整个结构非常清晰。等机器数量多起来,再考虑把Prometheus单独放到一台机器上,或者增加一套监控高可用方案。
1.3 版本选型与前期准备
版本这块建议直接用官方最新的稳定版。我写这篇内容时,Prometheus稳定版在2.53左右,Node Exporter在1.8左右,Grafana在11.x。下载时认准Linux amd64的压缩包就行,如果你的服务器是ARM架构,记得选对应的arm64包。
部署前有几件事需要提前确认:一是服务器时间必须准确,Prometheus对时间偏差很敏感,时间不对会导致数据错位甚至抓取失败,建议先确认chrony或ntp同步正常;二是防火墙策略,Prometheus默认监听9090端口,Node Exporter监听9100端口,Grafana监听3000端口,这些端口要么放行,要么先临时关闭防火墙测试;三是准备好一个软件安装目录,比如/opt,后续的二进制文件和配置都放这里。
2. 在CentOS上部署Prometheus与Node Exporter
2.1 下载并安装Prometheus服务
先创建一个专用系统用户,避免直接用root运行监控服务,这是安全底线。然后下载、解压、移动到/opt目录下。
# 创建prometheus用户,不分配登录shell useradd --no-create-home --shell /usr/sbin/nologin prometheus # 准备目录 mkdir -p /opt/prometheus mkdir -p /etc/prometheus mkdir -p /var/lib/prometheus # 下载最新稳定版,实际版本号以官方页面为准 cd /usr/local/src curl -LO https://github.com/prometheus/prometheus/releases/download/v2.53.2/prometheus-2.53.2.linux-amd64.tar.gz # 解压并移动 tar -zxvf prometheus-2.53.2.linux-amd64.tar.gz cd prometheus-2.53.2.linux-amd64 cp prometheus promtool /opt/prometheus/ cp -r consoles console_libraries /etc/prometheus/ cp prometheus.yml /etc/prometheus/这里有个细节我特意分开做了:二进制文件放到/opt/prometheus,配置文件和规则文件放在/etc/prometheus,数据目录放在/var/lib/prometheus。这样做的好处是升级时只需要替换二进制目录,不用动配置和数据,回滚也方便。
2.2 配置systemd服务并设置开机自启
手动执行Prometheus进程不现实,生产环境必须用systemd托管。创建一个服务文件/etc/systemd/system/prometheus.service:
[Unit] Description=Prometheus Server After=network.target [Service] Type=simple User=prometheus Group=prometheus Restart=on-failure ExecStart=/opt/prometheus/prometheus \ --config.file=/etc/prometheus/prometheus.yml \ --storage.tsdb.path=/var/lib/prometheus \ --web.listen-address=0.0.0.0:9090 \ --storage.tsdb.retention.time=30d [Install] WantedBy=multi-user.target几个启动参数简单说明一下。--storage.tsdb.retention.time=30d控制数据保留时间,默认是15天,根据你的磁盘空间决定,我一般建议30天起步,方便做月度趋势对比。--web.listen-address默认就是0.0.0.0:9090,如果你本机访问不多,可以改成内网IP。
然后启动并设置开机自启:
chown -R prometheus:prometheus /opt/prometheus /etc/prometheus /var/lib/prometheus systemctl daemon-reload systemctl enable --now prometheus systemctl status prometheus用curl localhost:9090/-/ready检查响应,返回Prometheus Server is Ready就说明服务起来了。这时候访问http://服务器IP:9090就能看到Prometheus自带的基础UI页面。
2.3 部署Node Exporter采集Linux指标
被监控的CentOS机器上,同样先创建用户,下载Node Exporter,然后用systemd托管。重复的步骤我不再赘述,只把服务文件单独列出来:
[Unit] Description=Node Exporter After=network.target [Service] Type=simple User=node_exporter Group=node_exporter Restart=on-failure ExecStart=/opt/node_exporter/node_exporter \ --web.listen-address=:9100 \ --collector.systemd \ --collector.processes [Install] WantedBy=multi-user.target--collector.systemd和--collector.processes这两个参数建议加上。默认Node Exporter不会采集systemd服务状态和进程数,但这两项在实际运维中非常有用,比如你想知道某台机器上有多少个失败的systemd服务单元,这个指标直接能反映出来。
启动后确认9100端口在监听:
ss -lntp | grep 9100 curl http://localhost:9100/metrics | head -n 20能看到以node_开头的指标输出就说明正常了。常见指标有这么几类:node_cpu_seconds_total是CPU累计使用时间,node_memory_*是内存信息,node_filesystem_*是文件系统状态,node_network_*是网卡流量。
3. 配置抓取任务与核心指标解读
3.1 编辑prometheus.yml添加监控目标
在Prometheus服务器上打开/etc/prometheus/prometheus.yml,默认配置文件里已经有一个prometheus的抓取任务,那是监控Prometheus自身的。我们需要加上一个针对Linux节点的抓取任务:
scrape_configs: - job_name: 'prometheus' static_configs: - targets: ['localhost:9090'] - job_name: 'linux-node' static_configs: - targets: - '10.0.0.11:9100' - '10.0.0.12:9100' labels: os: 'centos'job_name就是一组抓取任务的名称,比如你这批CentOS机器可以统一叫centos-node,后续在Grafana里筛选指标会很方便。targets列表里写的每台机器IP:端口,Prometheus启动后会周期性访问这些地址的/metrics路径。labels是附加标签,相当于给这组机器统一打标,方便做分组筛选。
改完配置后用samtool之类的工具校验一下语法更稳妥:
cd /opt/prometheus ./promtool check config /etc/prometheus/prometheus.yml确认无报错后重载配置,Prometheus支持热加载,不用重启:
kill -HUP $(pgrep -f prometheus)3.2 验证抓取状态与指标暴露
打开Prometheus的Web界面,依次进入“Status” -> “Targets”,能看到所有抓取目标的状态面板。如果显示UP,说明抓取正常;如果显示DOWN,点击对应目标的“Show more”能看到失败原因。
用命令快速验证也可以:
curl http://localhost:9090/api/v1/targets | jq '.data.activeTargets[] | {scrapeUrl, health}'如果返回的状态不是"up",大概率是网络不通、9100端口没开、或者是Prometheus服务器访问不到被监控机器。后面第6章我会集中讲排查方法。
3.3 常用系统监控指标的含义与查询示例
拿到指标数据之后,最关键的是搞清楚每个指标如何转换成你关心的“使用率”“剩余空间”和“流量速率”。以下表格整理了最常用的几类指标:
| 指标名 | 含义 | 类型 |
|---|---|---|
| node_cpu_seconds_total | CPU累计使用秒数,按mode区分 | Counter |
| node_load1 / node_load5 / node_load15 | 系统平均负载 | Gauge |
| node_memory_MemTotal_bytes | 总内存大小 | Gauge |
| node_memory_MemAvailable_bytes | 可用内存大小 | Gauge |
| node_filesystem_size_bytes | 文件系统总容量 | Gauge |
| node_filesystem_avail_bytes | 文件系统可用空间 | Gauge |
| node_network_receive_bytes_total | 网卡累计接收字节数 | Counter |
| node_network_transmit_bytes_total | 网卡累计发送字节数 | Counter |
这里最大的坑在于Counter类型不能直接用,必须经过rate()函数换算成每秒速率。CPU指标node_cpu_seconds_total就是这么个Counter,它表示从开机到现在CPU在各种状态(如用户态、内核态、空闲)下累计跑了多少秒。你要看CPU使用率,得先算出最近5分钟内空闲时间的变化速率,再用总数减去它:
100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)这条查询结果就是各台机器的CPU使用率百分比。内存和磁盘类型是Gauge,可以直接相除:
# 内存使用率 (1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100 # 磁盘使用率,排除系统自带的一些特殊文件系统 100 - (sum by(instance) (node_filesystem_avail_bytes{fstype!~"tmpfs|overlay|squashfs"}) / sum by(instance) (node_filesystem_size_bytes{fstype!~"tmpfs|overlay|squashfs"})) * 100网络流量要换算成比特每秒才直观:
# 入方向带宽,单位是bps rate(node_network_receive_bytes_total{device!="lo"}[5m]) * 8在{}里头加device!="lo"是为了过滤掉回环网卡,不然本地流量也算进去会把结果带偏。
4. 接入Grafana实现可视化
4.1 安装Grafana
Prometheus自带的UI只适合临时查数据,生产监控面板基本都用Grafana。CentOS下用官方仓库安装最省事:
# 添加官方yum源,然后安装 sudo yum install -y https://dl.grafana.com/oss/release/grafana-11.1.0-1.x86_64.rpm systemctl daemon-reload systemctl enable --now grafana-server安装完成后访问http://服务器IP:3000,默认账号和密码都是admin,首次登录会强制要求修改密码。这一步在公网环境别偷懒,务必改成强密码。
4.2 添加Prometheus数据源
进入Grafana左侧菜单“Connections” -> “Data Sources”,点击“Add data source”,选择Prometheus类型。在“URL”一栏填写http://localhost:9090,其他配置保持默认,点击下方的“Save & test”,看到绿色提示说明数据源连接成功。
如果在Grafana服务器上访问Prometheus正常,但数据源测试却失败,多半是Grafana容器或特权模式导致的网络隔离问题。本地安装一般不会遇到。
4.3 导入系统监控大盘
手写面板太费时间,直接从社区导入现成的模板更高效。在Grafana左侧菜单找到“Dashboards” -> “New” -> “Import”,在面板库中搜索“Node Exporter Full”或者直接输入面板ID 1860,点击Load,选择刚才创建的Prometheus数据源,最后Import即可。
导入完成后你就能看到一整套完整的Linux监控看板,包含CPU、内存、磁盘、网络、文件系统、systemd服务等十几个Panel。这套面板的查询逻辑可以作为你学习PromQL的绝佳教材,因为每个Panel点进去都能看到原始查询语句和变量定义方式。
4.4 自定义面板与告警配置
社区面板再牛,也不可能完全匹配你的需求。比如你想专门看某块挂载盘的写入延迟,得自己加面板。操作流程是:进入某个Dashboard右上角“Add” -> “Visualization”,选择Prometheus数据源,在查询编辑器里输入PromQL,右侧预览图表效果,顺手设置一下“Unit”单位,比如字节、百分比、秒等。
告警配置建议放在Prometheus规则文件里做,而不是在Grafana里配。因为Grafana的告警依赖Grafana本身一直在线,Prometheus规则告警则更贴近监控主干,后面第5章会专门讲。
5. 告警规则配置
5.1 编写告警规则文件
告警规则文件通常放在/etc/prometheus/下,比如叫node_rules.yml。内容按组划分,一组里可以放多条规则。举个例子:
groups: - name: node_alerts rules: - alert: InstanceDown expr: up == 0 for: 2m labels: severity: critical annotations: summary: "Instance {{ $labels.instance }} down" description: "Prometheus cannot reach {{ $labels.instance }} for more than 2 minutes." - alert: HighCpuUsage expr: 100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 90 for: 10m labels: severity: warning annotations: summary: "High CPU usage on {{ $labels.instance }}" description: "CPU usage has been above 90% for 10 minutes." - alert: DiskSpaceLow expr: (1 - node_filesystem_avail_bytes{fstype!~"tmpfs|overlay"} / node_filesystem_size_bytes{fstype!~"tmpfs|overlay"}) * 100 > 85 for: 5m labels: severity: warning annotations: summary: "Disk nearly full on {{ $labels.instance }}" description: "Disk usage has been above 85% for 5 minutes."规则里的for字段是持续触发时间,含义是“这个条件必须连续满足多少分钟才触发告警”。这个字段非常重要,能避免瞬时尖峰导致的误报。比如CPU瞬间冲到95%但1秒后就回落,这种就不该告警,for: 10m能过滤掉大量无效告警。
改完配置后在prometheus.yml里引用这个规则文件:
rule_files: - "node_rules.yml"然后重载Prometheus配置。进入Web界面“Status” -> “Rules”,能看到规则列表和每条规则的最新计算结果。
5.2 配置Alertmanager通知
规则触发后默认只是显示在界面上,生产环境需要推到企业微信、钉钉或邮件。这时就要安装Alertmanager。
# 下载解压后,创建配置 mkdir -p /etc/alertmanager cat > /etc/alertmanager/alertmanager.yml <<EOF route: group_by: ['alertname'] group_wait: 30s group_interval: 5m repeat_interval: 4h receiver: 'webhook' receivers: - name: 'webhook' webhook_configs: - url: 'http://127.0.0.1:8080/webhook' EOF然后在prometheus.yml里添加alertmanager地址:
alerting: alertmanagers: - static_configs: - targets: - 'localhost:9093'repeat_interval控制同一个告警的重复通知频率,默认4小时比较合理,既能避免刷屏,又不会漏掉持续未解决的问题。
5.3 告警测试验证
配置完成后别以为就万事大吉了,必须实际触发一次。我自己的做法是找一台测试机器,用dd命令快速占满磁盘:
dd if=/dev/zero of=/tmp/testfile bs=1M count=4096然后去Prometheus的“Alerts”页面观察告警状态变化:先是INACTIVE,条件满足进入PENDING,持续for指定的时间后变成FIRING。如果Alertmanager配好了,这个阶段应该能收到测试通知。测完记得删掉测试文件,然后重新打开“Alerts”页面确认告警恢复,规则会自动进入INACTIVE状态。
6. 常见问题与排查技巧实录
6.1 抓取目标显示DOWN怎么办
这是最常见的故障,遇到之后按顺序排查,通常十分钟内能定位。先确认被监控机器的Node Exporter进程还活着:
systemctl status node_exporter curl http://localhost:9100/metrics本机能输出指标说明服务正常,那就从Prometheus机器上用curl测一下网络连通性:
curl http://被监控IP:9100/metrics这一步能直接区分是网络问题还是应用问题。如果超时,检查CentOS的firewalld是否放行了9100端口:
firewall-cmd --list-ports # 查看已放行端口 firewall-cmd --permanent --add-port=9100/tcp && firewall-cmd --reload另一个容易忽略的是SELinux。CentOS默认开启SELinux,虽然这里监听高端口一般影响不大,但如果出现权限拒绝的错误,可以把getenforce的结果查一下。实在排查不出来,去看Node Exporter服务的日志,journalctl -u node_exporter -n 50通常会给出明确原因。
6.2 指标数据有缺失或不连续
抓取目标状态是UP,但Grafana面板上曲线出现断档,这种情况大多和服务器时间有关。Prometheus抓取数据时会带上时间戳,如果被监控机器的时间和Prometheus服务器相差超过一定阈值,Prometheus会丢弃或者错乱这部分时序数据。先同步时间:
systemctl enable --now chronyd chronyc sources数据断档还可能因为抓取超时。默认scrape_timeout是10秒,如果某台机器上Node Exporter加了很多采集器,一次性返回大量指标导致响应超时,就会出现抓取失败。这类问题既可以加大scrape_timeout,也可以精简采集器,我倾向于后者,不用的采集器模块直接禁用,省资源又稳定。
6.3 端口安全与性能优化
Node Exporter默认裸奔在9100端口,如果机器有公网IP,这个是很大的安全隐患。最简单的加固办法就是让Node Exporter只监听内网地址,比如把启动参数改成--web.listen-address=内网IP:9100。如果Prometheus和Node Exporter不在同一个内网,建议用Nginx反向代理加Basic Auth做一层认证,不要让指标接口直接暴露公网。
性能方面,首次启动Prometheus后数据目录会持续增大,特别是采集目标多、机器数量大的时候。合理设置retention.time,定期归档或清理,不要指望无限存储。Node Exporter本身资源占用很低,真正吃资源的是Prometheus存储和大盘查询,查询语句里尽量添加时间范围和rate()窗口,避免全量扫描时间序列数据。
6.4 常见问题速查表
我用一个表格把手头经常遇到的问题汇总一下,方便你直接对照处理:
| 现象 | 可能原因 | 快速处理 |
|---|---|---|
| Target显示DOWN | 9100端口未监听或防火墙拦截 | 检查node_exporter进程,放行端口 |
| 数据有缺口 | 被监控机时间不同步 | 启动chronyd并同步时间 |
| 告警一直不触发 | 规则文件没加载或for时间太长 | 打开Rules页面确认规则状态 |
| Grafana查不到数据 | 数据源URL填错 | 用localhost和IP各试一次 |
| 磁盘图表异常 | 未过滤tmpfs等虚拟文件系统 | PromQL加上fstype过滤条件 |
写到这里,如果你已经跟着把Prometheus、Node Exporter、Grafana这套环境搭起来,并且把第3章的常见指标查询都手动跑了一遍,那么监控Linux系统运行状态这件事的骨架就算完整了。根据我自己的经验,这套体系最核心的价值不是那一堆花花绿绿的图表,而是它能让你在业务出问题之前就看到趋势。早期我们监控刚上线的时候,有一次凌晨两点的告警短信把我叫醒,打开Grafana一看,某台机器磁盘使用率连续三小时稳步上升,按那个斜率算再过两小时就写满。如果不是监控提前报警,等到白天业务高峰再发现,整个服务可能已经处于不可用状态了。最后再提一个小技巧:前期搭建的时候,你可能觉得每台机器都配一套Node Exporter很麻烦,但用配置管理工具批量分发systemd配置和二进制文件,整个流程也就几分钟的事。监控越早建,数据越早积累,后面做容量规划、排查历史故障的时候,你会感谢当初自己没偷懒。