Ubuntu服务器跑久了,最怕的不是突然宕机,而是资源耗尽前没有任何预警,等发现时业务已经中断。很多人以为装个监控面板就够了,实际上真正的资源预警配置是一套组合拳:阈值怎么定、告警往哪发、触发后自动做什么,这三件事缺一不可。下面直接讲在Ubuntu生产环境里怎么把这套机制落地。
先确定要监控哪些资源指标CPU、内存、磁盘、网络是四个基础维度,但只看使用率百分比远远不够。CPU要关注load average和iowait,内存要区分实际可用内存和swap使用量,磁盘除了使用率还要监控inode耗尽和IO延迟,网络则要盯住连接数、丢包率和带宽饱和度。建议用vmstat、iostat、ss、df -i这些命令先手动跑一遍,摸清自己服务器在正常负载下的基线值。没有基线,后面设阈值就是拍脑袋。
用Monit做轻量级资源预警Ubuntu仓库自带的Monit非常适合中小规模部署,它不依赖外部服务,配置简单,能直接执行动作。先安装:
sudo apt update && sudo apt install monit -y
然后编辑主配置文件,开启Web管理界面和告警邮件:
sudo nano /etc/monit/monitrc
关键配置如下:
set daemon 60
set mailserver localhost
set alert admin@example.com
set httpd port 2812 and
use address localhost
allow localhost
allow admin:monitpassword
这里daemon 60表示每60秒检查一次。邮件告警依赖本机MTA,如果没装postfix,建议先装一个并配置为relay模式,或者改用ntfy、Slack webhook等方式推送。
编写资源监控规则Monit的规则写在/etc/monit/conf.d/目录下,每个资源一个文件。CPU和内存的监控规则示例:
check system $HOST
if loadavg (1min) > 4 for 3 cycles then alert
if loadavg (5min) > 3 for 5 cycles then alert
if memory usage > 85% for 3 cycles then alert
if swap usage > 50% then alert
这里的关键是for cycles,它表示连续多少个检查周期都超过阈值才告警,能有效避免瞬时波动造成的误报。loadavg阈值要根据CPU核数来定,一般不超过核数的1.5倍。内存85%是通用线,但如果跑数据库或缓存服务,建议调到90%以上再告警,因为这类服务会主动占用大量内存做缓存。
磁盘监控要同时看使用率和inode磁盘满了系统会拒绝写入,inode耗尽同样会导致无法创建新文件,但后者经常被忽略。规则示例:
check filesystem rootfs with path /
if space usage > 85% for 5 cycles then alert
if space usage > 95% then exec "/usr/local/bin/disk_cleanup.sh"
if inode usage > 80% then alert
注意这里用了两级策略:85%只发告警,95%触发自动清理脚本。清理脚本可以删临时文件、清日志、清包缓存,但一定要谨慎,只删确定可以删的东西。另外建议单独监控/var、/tmp、/home等挂载点,尤其是/var/log如果没做logrotate,很容易被日志撑爆。
网络连接数监控防端口耗尽高并发场景下,TCP连接数激增会耗尽文件描述符或端口范围,导致服务无法接受新连接。用Monit监控特定端口的连接数:
check host api.example.com with address 127.0.0.1
if failed port 8080 protocol http for 3 cycles then alert
if total memory > 90% then alert
更直接的方式是用脚本统计ss -s里的TCP连接总数,超过阈值就告警。把脚本放到/usr/local/bin/check_conn.sh,然后在Monit里调用:
check program conn_count with path "/usr/local/bin/check_conn.sh"
if status != 0 then alert
if status != 0 then exec "/usr/bin/systemctl restart nginx"
这个例子还展示了自动恢复动作:连接数异常时直接重启nginx。但自动重启要慎用,必须确保服务是无状态的,或者重启不会造成数据不一致。
用systemd timer配合脚本做深度检查Monit适合做常驻监控和快速响应,但有些深度检查需要更复杂的逻辑,比如分析磁盘IO延迟、检查特定进程的内存泄漏趋势、或者跑自定义的SQL健康检查。这类任务用systemd timer定时执行更合适。创建一个服务单元:
sudo nano /etc/systemd/system/resource-check.service
[Unit] Description=Custom resource deep check [Service] Type=oneshot ExecStart=/usr/local/bin/resource_deep_check.sh
再创建对应的timer:
sudo nano /etc/systemd/system/resource-check.timer
[Unit] Description=Run resource deep check every 10 minutes [Timer] OnBootSec=5min OnUnitActiveSec=10min [Install] WantedBy=timers.target
启用并启动:
sudo systemctl daemon-reload sudo systemctl enable resource-check.timer sudo systemctl start resource-check.timer
脚本里可以调用iostat -x看await和util,用ps aux按内存排序找异常进程,用dmesg检查OOM killer记录。发现异常后通过curl调用ntfy或企业微信机器人发告警,比邮件更实时。
告警通道的选择与分级邮件是最基础的通道,但容易被淹没。生产环境建议至少配置两级告警:普通告警走邮件或IM群,严重告警走短信或电话。用ntfy.sh自建推送服务很简单,Ubuntu上装个ntfy服务端,客户端用curl就能发:
curl -H "Title: CPU告警" -H "Priority: high" -d "服务器负载超过4,当前值5.2" https://ntfy.example.com/server-alerts
优先级用Priority头控制,high和urgent级别可以在手机端触发强提醒。如果不想自建,直接用企业微信机器人、钉钉机器人、飞书机器人也都很方便,本质都是webhook,在脚本里加几行curl就行。
阈值调优:别让告警变成噪音很多人配完预警后,一天收到几十封告警邮件,最后干脆把告警关了,这比不配还危险。阈值设置要遵循“告警疲劳”原则:每个指标只告警真正需要人工介入的情况。比如CPU loadavg偶尔冲到4但5分钟内就回落,这种不需要告警;连续15分钟高于4才说明有持续压力。内存使用率85%在跑Elasticsearch的机器上就是正常状态,应该设到92%。磁盘使用率从85%到100%可能只需要几小时,所以85%告警是合理的,但95%必须触发自动清理或限流。
验证告警链路是否真的能通配置完成后,不要假设一切正常。手动触发一次告警测试:把阈值临时调低,或者用stress工具制造负载,确认能收到告警。同时检查告警内容是否包含足够信息:哪个服务器、哪个指标、当前值、阈值、持续时间、建议动作。如果告警信息只有一句“CPU usage high”,收到的人还得登录服务器查半天,这种告警价值很低。
资源预警与自动扩容的边界Ubuntu服务器如果跑在云平台上,资源预警可以和云API联动做自动扩容。但自动扩容不是银弹,扩容本身需要时间,而且会带来成本。更务实的做法是:预警触发后先执行降级策略,比如关闭非核心功能、限流、清理缓存,如果5分钟内无法恢复再触发扩容。这个决策逻辑要写在脚本里,而不是靠人肉判断。
整套配置做完后,建议每季度回顾一次告警记录,看看哪些告警是误报、哪些阈值需要调整、哪些资源基线发生了变化。服务器资源预警不是一次性配置,而是随着业务演进的持续调优过程。把基线和阈值做成文档,交接给下一个运维时也能快速理解这台机器的“脾气”。
