为Ubuntu服务器预防宕机,如何设置资源告警与变更前容量检查
面向具备基础操作能力的运维人员,介绍如何基于CPU、可用内存、磁盘、inode及I/O建立持续资源告警,并在升级或扩容前计算容量余量,明确正常与异常分界、监控验收及留证方法,降低服务器宕机风险。

很多 Ubuntu 服务器宕机前并不是“资源突然归零”,而是已经出现持续 CPU 排队、可用内存下降、磁盘或 inode 接近耗尽、I/O 等待升高等信号。问题在于,仅观察 CPU 使用率或 free 中的空闲内存,很容易把短时峰值当故障,或者漏掉真正的资源压力。
预防这类宕机应同时完成两件事:用持续时间、基线和多指标组合设置资源告警;在升级、扩容应用、提高并发或导入数据前,计算变更后的资源余量,并保留可复核的检查记录。告警阈值不能直接照搬固定数字,下面给出的数值适合作为初始示例,最终应按业务高峰基线、服务容忍度和回滚需求调整。
先明确哪些指标真正接近宕机风险
单个指标只能说明资源状态,不能直接证明服务器一定会宕机。判断时应关注指标之间的关系。
| 资源 | 优先观察指标 | 它能说明什么 | 容易产生的误判 |
|---|---|---|---|
| CPU | 使用率、Load、CPU PSI | 是否持续繁忙、是否出现任务排队 | 单次 CPU 100% 不等于容量不足 |
| 内存 | MemAvailable、Swap 换入换出、OOM |
应用还能否继续申请内存 | free 较低可能只是缓存较多 |
| 文件系统 | 可用字节、可用 inode、增长速度 | 是否还能写日志、缓存和临时文件 | 只看磁盘容量会漏掉 inode 耗尽 |
| 磁盘 I/O | await、队列、吞吐、I/O PSI |
存储响应是否成为瓶颈 | %util 在不同存储设备上不能使用同一边界 |
| 进程限制 | 文件描述符、任务数、cgroup 限额 | 服务是否会先于主机资源触顶 | 主机有余量不代表容器或服务有余量 |
| 网络接口 | 错包、丢包、连接数量 | 是否出现接口、队列或连接资源压力 | 流量高本身不代表网络异常 |
CPU 告警应强调“持续”。例如 CPU 使用率超过某个边界并持续 10 分钟,比瞬时超过 95% 更有价值。如果高使用率同时伴随 Load 持续上升、CPU PSI 增加或请求延迟恶化,才更能支持“CPU 容量不足”的判断。
内存则应优先看 /proc/meminfo 中的 MemAvailable。它包含可以回收的缓存,比单纯查看 MemFree 更接近应用还能申请多少内存。若 MemAvailable 持续下降,同时出现 Swap 频繁换入换出或 OOM Kill,说明风险已经不只是缓存占用。
先采集基线,不要直接套用告警阈值
告警需要覆盖至少一个完整的业务繁忙周期。业务每天有固定高峰,可以覆盖一个或多个高峰;存在周末任务、周报生成或定期备份时,还应覆盖相应周期。几秒钟的 top 截图只能表示当时状态,不能作为容量验收依据。
先核对 Ubuntu 版本、内核以及服务管理方式:
. /etc/os-release
printf 'OS: %s\n' "$PRETTY_NAME"
uname -r
systemctl --version | head -n 1
如未安装 sysstat,可先查看软件包来源和候选版本,再决定是否安装:
apt-cache policy sysstat
sudo apt update
sudo apt install sysstat
安装软件包会改变系统状态,生产环境应纳入变更记录。以下命令只进行读取和短时间采样,可用于建立当前快照:
uptime
free -h
grep -E 'MemTotal|MemAvailable|SwapTotal|SwapFree' /proc/meminfo
df -hT
df -i
vmstat 1 5
mpstat -P ALL 1 5
iostat -xz 1 5
ip -s link
systemctl --failed --no-pager
如果内核支持 PSI,还可以查看资源等待压力:
for resource in cpu memory io; do
file="/proc/pressure/$resource"
if [ -r "$file" ]; then
echo "### $resource"
cat "$file"
fi
done
PSI 表示任务因资源不足而等待的时间比例。它适合与自身历史基线比较,但不宜在不了解业务的情况下设置统一阈值。某些批处理任务允许短时间 I/O 等待,而实时接口服务对相同等待可能无法接受。
建议为每次变更创建权限受限的留证目录:
EVIDENCE="$HOME/capacity-check-$(date +%Y%m%d-%H%M%S)"
mkdir -m 700 "$EVIDENCE"
{
date -Is
. /etc/os-release
echo "$PRETTY_NAME"
uname -a
uptime
free -h
df -hT
df -i
} > "$EVIDENCE/system-summary.txt"
vmstat 1 10 > "$EVIDENCE/vmstat.txt"
iostat -xz 1 10 > "$EVIDENCE/iostat.txt"
ip -s link > "$EVIDENCE/network.txt"
systemctl --failed --no-pager > "$EVIDENCE/failed-units.txt"
sudo journalctl -k --since "-24 hours" --no-pager \
| grep -Ei 'out of memory|oom-kill|i/o error|ext4-fs error|xfs.*error|nvme.*error' \
> "$EVIDENCE/kernel-risk-events.txt"
日志和进程信息可能包含主机名、内部路径及业务名称,留证文件不应放入公开目录。grep 没有输出表示未匹配到这些关键字,但不能证明硬件、文件系统或内存完全正常。
用外部监控建立可持续的资源告警
只在被监控的 Ubuntu 服务器上运行本地告警脚本存在明显缺陷:主机失联、内存耗尽或磁盘只读后,脚本本身也可能无法通知。更可靠的方式是目标服务器运行指标采集端,Prometheus、Alertmanager或其他监控平台部署在独立位置。
Ubuntu 软件源通常提供 Prometheus Node Exporter,安装前应先核对候选版本:
apt-cache policy prometheus-node-exporter
sudo apt install prometheus-node-exporter
sudo systemctl enable --now prometheus-node-exporter
sudo systemctl status prometheus-node-exporter --no-pager
在本机验证指标端点:
curl -fsS http://127.0.0.1:9100/metrics | head
Node Exporter 端口不应直接暴露给公网。应通过监听地址、主机防火墙或上游访问控制,仅允许监控端连接。不同 Ubuntu 软件包版本的启动参数位置可能不同,修改前可先查看实际服务定义:
systemctl cat prometheus-node-exporter
在 Prometheus 端加入采集目标时,将示例地址替换为实际内网或管理地址,并合并到现有 scrape_configs,不要重复创建同名顶层配置:
scrape_configs:
- job_name: ubuntu-nodes
static_configs:
- targets:
- 10.0.0.10:9100
以下规则给出了 CPU、内存、磁盘容量和 inode 的初始告警写法:
groups:
- name: ubuntu-resource
rules:
- alert: UbuntuCPUUsageHigh
expr: 100 * (1 - avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m]))) > 85
for: 10m
labels:
severity: warning
annotations:
summary: "Ubuntu服务器CPU持续繁忙"
description: "{{ $labels.instance }} CPU使用率持续10分钟超过初始告警边界"
- alert: UbuntuMemoryAvailableLow
expr: 100 * node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes < 15
for: 10m
labels:
severity: warning
annotations:
summary: "Ubuntu服务器可用内存偏低"
description: "{{ $labels.instance }} MemAvailable占比持续低于初始告警边界"
- alert: UbuntuFilesystemSpaceLow
expr: 100 * node_filesystem_avail_bytes{fstype!~"tmpfs|devtmpfs|squashfs|overlay"} / node_filesystem_size_bytes{fstype!~"tmpfs|devtmpfs|squashfs|overlay"} < 15
for: 15m
labels:
severity: warning
annotations:
summary: "Ubuntu服务器文件系统空间不足"
description: "{{ $labels.instance }} 的 {{ $labels.mountpoint }} 可用空间比例偏低"
- alert: UbuntuFilesystemInodesLow
expr: 100 * node_filesystem_files_free{fstype!~"tmpfs|devtmpfs|squashfs|overlay"} / node_filesystem_files{fstype!~"tmpfs|devtmpfs|squashfs|overlay"} < 10
for: 15m
labels:
severity: warning
annotations:
summary: "Ubuntu服务器inode余量不足"
description: "{{ $labels.instance }} 的 {{ $labels.mountpoint }} 可用inode比例偏低"
- alert: UbuntuNodeExporterDown
expr: up{job="ubuntu-nodes"} == 0
for: 3m
labels:
severity: critical
annotations:
summary: "Ubuntu服务器指标采集失败"
description: "{{ $labels.instance }} 已连续无法被监控端采集"
85%、15%和10%不是所有服务器的统一正常线。它们只适合用作初始边界。例如,大容量数据盘剩余 14% 时可能仍有较多可用空间,而小容量系统盘剩余 16% 也可能无法容纳一次升级和回滚文件。因此,磁盘告警最好进一步结合绝对剩余容量和预计写满时间。
修改规则前应备份现有 Prometheus 配置,并使用当前安装版本自带的工具校验:
promtool check rules /etc/prometheus/rules/ubuntu-resource.yml
promtool check config /etc/prometheus/prometheus.yml
配置路径取决于软件包、容器挂载和自定义启动参数,可通过实际进程参数或服务定义确认,不应直接假定。校验通过后,再使用当前部署已验证的 reload 机制加载配置;如果服务没有定义安全的重载方式,应安排维护窗口重启,而不是在业务高峰盲目操作。
告警进入 Prometheus 的 firing 状态不等于通知已经送达。还需要在 Alertmanager或所用监控平台中配置接收渠道、分组、抑制和恢复通知,并进行一次测试告警。验收至少包括:
up{job="ubuntu-nodes"}对目标实例为1。- 人为设置的测试告警能从 Pending 进入 Firing。
- 值班渠道收到告警,内容包含实例、挂载点和严重级别。
- 告警恢复后能收到恢复通知。
- 监控端无法采集目标时,能触发失联告警。
- 测试结束后删除临时规则,避免持续发送通知。
变更前要计算“变更后余量”,而不是只看当前空闲
当前有 30% 空闲 CPU,不代表可以直接把工作进程翻倍。容量检查需要把现有高峰、变更新增量、临时开销和回滚空间放在一起计算。
CPU容量判断
可以把 CPU 使用量换算成“核心数”:
当前高峰占用核心数 = 逻辑CPU数 × 高峰CPU使用率
目标容量上限 = 逻辑CPU数 × 计划使用率上限
变更后预计占用 = 当前高峰占用核心数 + 变更新增核心数
例如一台 8 核服务器,高峰 CPU 使用率为 55%,则高峰占用约为 4.4 核。若内部容量边界设为 75%,可用上限为 6 核;变更预计增加 1 核时,变更后约为 5.4 核,仍在边界内。
这只是计算示例,不代表实际性能结果。新增 CPU 需求应来自压测、灰度实例或同类节点记录。若无法估计新增量,就不应仅凭平均 CPU 使用率批准全量变更,应先小范围灰度并观察 Load、PSI和业务延迟。
内存容量判断
内存应按业务高峰期间的最低 MemAvailable 计算:
变更后预计可用内存
= 高峰期最低MemAvailable
- 新增常驻内存
- 启动或重载临时峰值
- 必要的回滚保留
变更后预计可用内存必须高于本机设定的安全保留量,并且不能持续依赖 Swap 才能维持。Java、数据库、缓存服务和大量工作进程在启动或重载时可能产生短时内存峰值,只计算稳定运行后的常驻内存容易低估风险。
还要确认服务是否受到 cgroup 或 systemd 限制:
SERVICE_NAME="your-service.service"
systemctl show "$SERVICE_NAME" \
-p MemoryCurrent \
-p MemoryMax \
-p TasksCurrent \
-p TasksMax \
-p LimitNOFILE
请将服务名替换为实际 unit。MemoryMax 或 TasksMax 先触顶时,即使主机仍有资源,应用也可能退出、拒绝新任务或被 cgroup 终止。容器环境还应检查容器的 CPU、内存和进程限制,不能只依据宿主机数据。
磁盘与 inode 判断
磁盘检查至少应包含以下空间:
变更后剩余空间
= 当前可用空间
- 安装包或镜像下载
- 解压与安装临时空间
- 新旧版本并存空间
- 配置及数据备份
- 回滚窗口内的日志和数据增长
Ubuntu 软件包升级可先模拟,确认将安装、升级或删除哪些软件包:
sudo apt-get -s upgrade
-s 表示模拟,不执行实际安装,但输出仍应人工检查。涉及发行版升级、数据库迁移或大规模镜像拉取时,软件包模拟结果不能覆盖全部临时空间,应根据下载文件、解压比例、备份副本和数据增长分别估算。
同时执行:
df -hT
df -i
sudo du -xhd1 /var 2>/dev/null | sort -h
du 可能对繁忙文件系统造成额外 I/O,生产高峰应谨慎使用,并优先限定目录和文件系统。空间不足时不要直接删除日志、数据库文件或容器目录,应先确认归属、保留要求和回滚方式。
I/O不能只用一个固定阈值验收
iostat -xz 中的 await、队列和吞吐需要与同一设备的历史基线比较。不同设备类型、RAID方式、虚拟化存储和业务访问模式差异较大,不能把某个固定毫秒值当作所有 Ubuntu 服务器的异常线。
以下情况更能支持 I/O 容量不足的判断:
- 变更前业务高峰的
await已明显高于自身日常基线。 - I/O PSI 持续增加,同时应用响应时间升高。
- 磁盘队列持续积压,吞吐量却不再增长。
- 内核日志出现超时、重置或文件系统错误。
- 数据导入、备份或日志压缩会与在线业务争用同一设备。
无法量化新增 I/O 时,应先在灰度节点执行同类操作,并在相同采样周期内比较,而不是直接在全量节点上尝试。
用验收边界决定是否允许变更
变更审批时,可以按以下项目形成明确的正常与异常分界。表中的百分比应替换为本机经过基线验证的阈值。
| 验收项目 | 可继续变更的条件 | 应暂停变更的情况 | 留证方式 |
|---|---|---|---|
| 监控链路 | 指标连续采集,测试通知和恢复通知均送达 | 目标失联、规则未加载、通知渠道不可用 | Prometheus规则状态、通知记录 |
| CPU | 高峰值加新增量仍低于容量边界,Load和PSI无持续恶化 | 只能依赖平均值,或新增量无法估计且没有灰度方案 | 监控曲线、计算表、灰度记录 |
| 内存 | 预计可用内存高于安全保留量,无近期OOM | 高峰已频繁换页,或服务cgroup余量不足 | MemAvailable曲线、内核日志 |
| 磁盘 | 可容纳安装、临时文件、备份、增长及回滚副本 | 只够完成安装,没有回滚和增长空间 | df -hT、目录容量清单 |
| inode | 变更后仍有充足余量,文件数量增长可控 | inode已接近告警边界或小文件增长无法估计 | df -i、文件数量记录 |
| I/O | 高峰基线稳定,灰度后等待和队列可接受 | 已存在持续等待,变更又会增加同盘读写 | iostat、PSI、应用延迟 |
| 系统状态 | 无未解释的失败服务、OOM和文件系统错误 | 存在活动故障但计划带故障变更 | systemctl --failed、内核日志 |
| 回滚条件 | 备份可读取,回滚步骤、负责人和时间窗口明确 | 只有备份文件但没有验证恢复方式 | 备份校验记录、回滚操作单 |
变更完成后不应立即以“服务能启动”作为验收结果。应在与变更前相同的业务负载或同类高峰周期下复测 CPU、MemAvailable、Swap、磁盘增长、inode、I/O等待和告警状态。若资源增长超出预估,即使暂未触发告警,也应暂停继续扩大发布范围,并用新的观测数据重新计算容量边界。