Linux服务器如何搭建实时监控系统?CPU、内存、磁盘与网络监控教程

凌晨两点,业务群里弹出一条消息:"网站打不开了。"你爬起来登录服务器,敲下 top,发现 CPU 早就跑满了,而这一切从一小时前就开始了——只是没人知道。这种被动救火的局面,几乎每个运维都经历过。真正的问题不在于故障本身,而在于故障发生时你毫不知情,只能靠用户投诉来"告警"。搭建一套实时监控系统,本质上是把"事后救火"变成"事前预警":让 CPU、内存、磁盘、网络这四类核心资源的状态始终可见,让异常在演变成故障之前就被捕捉到。本文从零开始,讲清楚在 Linux 服务器上搭建实时监控系统的完整路径:先看命令行即时工具,再讲如何做成持续采集与可视化的监控系统,最后给出可落地的阈值与告警策略。

一、先搞清楚要监控什么:四大类指标与判断标准

很多人一上来就装监控软件,装完发现几百个指标看得眼花,真正出问题时反而不知道看哪个。正确的顺序是:先定义"什么算异常",再决定采集什么。对于单台 Linux 服务器,需要关注的核心指标其实只有四类。

1.1 CPU:别只看使用率,要看负载与队列

CPU 使用率只是结果,负载(load average)才是压力的体现。执行 uptime 会输出三个数值,分别代表 1 分钟、5 分钟、15 分钟的平均负载。判断标准是:负载除以 CPU 逻辑核数,如果持续大于 1,说明请求排队了。一台 4 核机器 15 分钟负载为 8,意味着平均有 4 个进程在等待 CPU 时间片。另外要区分 CPU 时间的构成:us(用户态)高通常是业务代码消耗;sy(内核态)高可能是系统调用频繁或上下文切换过多;wa(iowait,等待 I/O)高则说明瓶颈在磁盘而不在 CPU——这一点很多人会误判,看到 CPU 使用率高就去升级 CPU,结果钱白花了。

1.2 内存:看懂可用内存,别被"free 很小"吓到

Linux 会用空闲内存做 page cache(页缓存),所以 free 命令里 free 一栏很小是常态,不代表内存不够。真正要看的是 available 一列,它估算的是"在不发生 swap 的前提下还能分配给进程的内存"。判断标准:available 低于总内存的 10%,或者 si/so(swap in/out)持续大于 0,说明内存已经吃紧。另外关注 buff/cache 是否被大量占用却无法回收,以及是否有进程内存持续上涨——后者往往是内存泄漏的信号,可以通过连续采样 ps 的 RSS 字段来确认。

1.3 磁盘:容量与 IO 性能是两回事

磁盘监控要分两个维度。第一是容量:df -h 看使用率,建议阈值是超过 85% 发预警、超过 90% 发告警。为什么要留 10% 以上?因为很多文件系统(如 ext4)默认保留 5% 给 root,且大文件写入需要连续空间,磁盘接近满时写入性能会断崖式下降。第二是 IO 性能:iostat -x 1 里的 %util 表示设备忙于处理 I/O 的时间比例,持续超过 80% 基本可以判定设备饱和;await 是 I/O 平均等待时间,机械盘超过 20ms、SSD 超过 5ms 就值得排查。还要额外监控 inode 使用率(df -i),小文件多的机器上 inode 耗尽比容量耗尽更常见。

1.4 网络:带宽、连接数与丢包

网络要看三件事:吞吐量是否接近带宽上限、TCP 连接数是否异常、是否有丢包和重传。sar -n DEV 1 可以看每秒收发字节数,与购买带宽(注意运营商按 bit 计、系统按 Byte 计,1 Mbps ≈ 125 KB/s)对比判断是否跑满。ss -s 看连接总数,ss -ant | grep TIME-WAIT | wc -l 看 TIME_WAIT 堆积情况——短连接服务上 TIME_WAIT 过多会耗尽端口。sar -n EDEV 1 里的 rxdrop/s、txdrop/s 非 0 说明网卡缓冲区已经开始丢包。

类别核心指标预警阈值告警阈值常用命令
CPUload1 / CPU 核数> 0.7 持续 10 分钟> 1.5 持续 5 分钟uptime、top、vmstat 1
内存MemAvailable 占比< 15%< 10% 或 si/so > 0free -h、vmstat 1
磁盘容量used 百分比> 85%> 90%df -h、df -i
磁盘 IO%util、await%util > 70%%util > 80% 持续 5 分钟iostat -x 1
网络带宽占用、重传率> 70% 带宽> 90% 带宽或丢包 > 0sar -n DEV 1、ss -s

二、命令行即时监控:不用装任何东西就能看到实时状态

在搭建长期监控系统之前,先掌握一套命令行工具。它们的价值在于"立刻可用"——机器已经卡死了,你 SSH 上去第一件事就是用这些命令定位问题,而不是等监控面板加载。这类工具大多来自 sysstat 和 procps 软件包,CentOS/RHEL 用 yum install -y sysstat,Debian/Ubuntu 用 apt install -y sysstat 安装。

# 综合体检:每 1 秒刷新一次,看 CPU、内存、IO、系统整体情况
vmstat 1

# 只看磁盘:x 表示扩展统计,1 表示每秒一次
iostat -x 1

# CPU 逐核使用率(mpstat 来自 sysstat)
mpstat -P ALL 1

# 网络接口流量,DEV 看吞吐,EDEV 看错误和丢包
sar -n DEV 1
sar -n EDEV 1

# 内存以 MB 显示,重点关注 available 列
free -m

# 实时进程视图,按 P 按 CPU 排序,按 M 按内存排序
top

读懂输出比记住命令更重要。以 vmstat 1 为例,输出分为 procs、memory、swap、io、system、cpu 六组。r 列是运行队列长度,如果长期大于 CPU 核数,说明 CPU 不够用;b 列是不可中断睡眠的进程数,非 0 通常意味着进程卡在磁盘 I/O;si/so 两列只要持续不为 0,就说明系统在用 swap,性能会明显下滑;cpu 组的 wa 列即前面提到的 iowait。iostat -x 1 输出里 r/s、w/s 是每秒读写请求数,rkB/s、wkB/s 是每秒读写数据量,aqu-sz 是请求队列平均长度——队列越长,说明设备处理不过来。

命令行工具的局限也很明显:只能看当下,看不到历史;只能看一台机器,无法横向对比。所以它们适合"现场排查",不适合"长期监控"。两者要配合使用。

三、搭建持续化监控系统:node_exporter + Prometheus + Grafana

要做长期监控,业界最主流的开源组合是 node_exporter(采集)+ Prometheus(存储与查询)+ Grafana(可视化)。架构很简单:每台被监控的服务器上跑一个 node_exporter 进程,它把操作系统指标通过 HTTP 暴露在 9100 端口;Prometheus 定时来"拉"这些指标存进自己的时序数据库;Grafana 从 Prometheus 读数据画图。这套组合的好处是全部开源、部署轻量、社区面板模板丰富。

3.1 部署 node_exporter

下载解压后,建议用 systemd 托管,保证开机自启和异常退出后自动拉起。

# 下载并解压(以 v1.7.0 为例,实际版本请到官方 Release 页确认)
wget https://github.com/prometheus/node_exporter/releases/download/v1.7.0/node_exporter-1.7.0.linux-amd64.tar.gz
tar -xzf node_exporter-1.7.0.linux-amd64.tar.gz
mv node_exporter-1.7.0.linux-amd64/node_exporter /usr/local/bin/

# 创建 systemd 服务
cat > /etc/systemd/system/node_exporter.service <<'EOF'
[Unit]
Description=Prometheus Node Exporter
After=network.target

[Service]
Type=simple
User=nobody
ExecStart=/usr/local/bin/node_exporter \
  --collector.disable-defaults=false \
  --collector.filesystem.ignored-mount-points=^/(dev|proc|sys|run|var/lib/docker)($|/)
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable --now node_exporter
systemctl status node_exporter

# 验证:能看到大量 node_ 开头的指标即为正常
curl -s localhost:9100/metrics | grep node_memory_MemAvailable_bytes

注意 --collector.filesystem.ignored-mount-points 这个参数,它把 docker 的 overlay 挂载点排除掉,否则容器环境里会有几十上百个文件系统指标刷屏。另外 node_exporter 默认监听 9100,务必用防火墙限制只允许 Prometheus 服务器访问,否则指标接口会暴露整机的内部信息。

3.2 node_exporter 必须记住的指标名

指标名记住几个就够覆盖日常场景:node_cpu_seconds_total(CPU 各模式累计时间,Counter 类型,要配合 rate() 使用)、node_memory_MemAvailable_bytes(可用内存字节数,Gauge)、node_memory_MemTotal_bytes(总内存)、node_filesystem_avail_bytes(文件系统可用字节)、node_filesystem_size_bytes(文件系统总大小)、node_disk_io_time_seconds_total(磁盘 IO 累计耗时,算 %util 要用它)、node_network_receive_bytes_total 与 node_network_transmit_bytes_total(网卡收发字节累计值)、node_load1/node_load5/node_load15(负载)。

3.3 Prometheus 抓取配置要点

Prometheus 的配置文件是 prometheus.yml,核心是 scrape_configs 段。每个采集任务用 job_name 区分,scrape_interval 控制采集频率,static_configs 里列出目标地址。

global:
  scrape_interval: 15s        # 全局采集间隔
  evaluation_interval: 15s    # 告警规则评估间隔

scrape_configs:
  - job_name: 'node'
    scrape_interval: 15s
    static_configs:
      - targets:
          - '10.0.0.11:9100'
          - '10.0.0.12:9100'
        labels:
          env: production
          role: web

  - job_name: 'prometheus'
    static_configs:
      - targets: ['localhost:9090']

关于采集间隔有个常见误区:不是越短越好。scrape_interval 设成 5s 会让数据量翻三倍,磁盘占用和查询压力都上升,但对大多数业务来说,15s 的精度已经足够定位问题。建议生产环境用 15s 或 30s,排查疑难问题时临时开一个 5s 的任务。另外,如果要监控几十上百台机器,手写 targets 会很难维护,这时应该改用基于文件的服务发现(file_sd_configs)或对接 CMDB 的 consul_sd_configs。

四、告警:阈值怎么定才不会把你吵醒

监控系统最容易失败的地方不是采集,而是告警。阈值定得太松,故障来了没人管;定得太紧,每天几十条噪音告警,最后大家集体屏蔽群消息。合理的做法是分层:预警(Warning)记录到工单或低频通知,告警(Critical)才触发电话或短信。同时必须设置 for 持续时间,避免瞬时抖动触发告警。比如 CPU 使用率高这条规则,应该写成"CPU 使用率大于 85% 持续 5 分钟",而不是"大于 85%"。

groups:
  - name: node.rules
    rules:
      # 磁盘容量:按 10 天内将被写满的趋势预测
      - alert: DiskWillFillIn10Days
        expr: |
          predict_linear(node_filesystem_avail_bytes{fstype!~"tmpfs|overlay"}[1h], 10*86400) < 0
        for: 30m
        labels:
          severity: warning
        annotations:
          summary: "磁盘将在 10 天内写满"

      # 磁盘已用比例
      - alert: DiskUsageHigh
        expr: |
          (1 - node_filesystem_avail_bytes{fstype!~"tmpfs|overlay"} / node_filesystem_size_bytes{fstype!~"tmpfs|overlay"}) * 100 > 90
        for: 10m
        labels:
          severity: critical
        annotations:
          summary: "磁盘使用率超过 90%"

      # 可用内存不足
      - alert: MemoryLow
        expr: |
          node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes * 100 < 10
        for: 5m
        labels:
          severity: critical

值得特别推荐的是 predict_linear() 这个函数:它根据过去 1 小时的趋势,线性外推 10 天后剩余空间是否会小于 0。相比固定阈值,它能提前好几天发现"增长很快但还没满"的磁盘,这对日志盘尤其有用。

五、从零落地的实施步骤

  1. 梳理资产:列出所有需要监控的服务器 IP、角色(Web/DB/缓存)、业务归属,这是后面分组告警的基础。
  2. 统一安装 sysstat:在所有机器上装好 sysstat 并启用 sar 的历史采集(systemctl enable --now sysstat),这样即使 Prometheus 挂了也有本地历史可查。
  3. 部署 node_exporter:用 Ansible 批量推送(见自动化相关文章),确认 9100 端口只对内网监控机开放。
  4. 部署 Prometheus:单机起步即可,先配置好 scrape_configs 与 alerting,数据保留期建议设 15 天(--storage.tsdb.retention.time=15d)。
  5. 接入 Grafana:导入社区成熟的 Node Exporter 面板模板,再按自己业务加自定义图表。
  6. 配置告警规则与通知渠道:先只开 Critical 级别,运行两周观察误报率,再逐步打开 Warning。
  7. 做一次故障演练:人为把测试机 CPU 跑满、磁盘写满,确认告警能在预期时间内到达,验证通道真实可用。

小结

搭建 Linux 服务器实时监控系统,核心不是工具,而是"定义异常—采集数据—可视化—告警—复盘"这条闭环。命令行工具(vmstat、iostat、sar、free、ss)解决的是现场排查,Prometheus + node_exporter + Grafana 解决的是长期趋势与自动告警,两者缺一不可。落地时有几个坑要避开:一是只看 CPU 使用率不看 iowait,容易把磁盘问题当成 CPU 问题;二是被 free 命令的小数值误导,要学会看 available;三是忘记监控 inode,小文件业务上 inode 耗尽比空间耗尽更突然;四是告警不做 for 持续时间限制,导致告警风暴;五是 node_exporter 的 9100 端口不加访问限制,等于把服务器内部状态公开出去。把这几件事做对,你就能在用户投诉之前发现问题。


关键词:Linux服务器监控、实时监控系统、CPU监控、内存监控、磁盘监控、网络监控、Prometheus、node_exporter