小内存服务器宝塔面板磁盘读IOPS打满被阿里云限流的排查与防坑记录

背景:阿里云轻量服务器一台,装了宝塔面板,经常性无法访问、需在控制台强制重启才能恢复。阿里云诊断提示:实例 IOPS 读速率达到上限的 100%(2060 次/秒),云盘读写受限。机器内存只有 882MB。

原因:内存过小导致文件缓存不足,读操作频繁落到真实磁盘;同时宝塔若干常驻功能在反复全盘扫描、读取超大日志,两者叠加把读 IOPS 顶满,触发云厂商限流。因此处理思路就三条——关闭重读盘的功能、控制日志体量、内存尽量给够。

一、排查命令

以下均为只读命令,不改动系统。尽量在卡顿发生时执行,空闲时抓不到尖峰。可整段贴入终端一次跑完:

echo "==内存/swap=="; free -m
echo "==磁盘空间=="; df -h
echo "==IO总览(si/so换页, bi/bo块读写, wa等待IO)=="; vmstat 1 5
echo "==谁在读盘(kB_rd/s最高的即元凶)=="; pidstat -d 1 10
echo "==各磁盘设备IOPS与等待(%util接近100即被打满)=="; iostat -x 1 5 2>/dev/null | grep -A30 "Device"
echo "==计划任务(盯*/分钟高频、全盘扫、备份)=="; crontab -l
echo "==已装宝塔插件=="; ls /www/server/panel/plugin/
echo "==相关常驻进程=="; ps -ef | grep -E "monitor|site_total|btwaf|webshell|nethogs|fail2ban|alist" | grep -v grep
echo "==journald占用=="; journalctl --disk-usage
echo "==大目录体量=="; du -sh /www/wwwlogs /www/server/monitor /www/server/data /var/log/journal 2>/dev/null
echo "==最大的访问日志=="; ls -lhS /www/wwwlogs 2>/dev/null | head

二、结果判读

  • pidstat 中 kB_rd/s 持续偏高、进程名带 monitor / site_total / btwaf / webshell 的,即为目标。
  • iostat -x 中某设备 %util 逼近 100%、r/s 很高,说明该盘被读满。
  • vmstat 中 si/so 持续非 0,为内存换页;wa 高为 CPU 等待 IO。
  • crontab 中出现 */5、*/20 等高频任务的,重点怀疑。

三、定位到的进程

吃读 IOPS 的基本都是宝塔自带功能,与网站业务无关:

  • 网站监控报表 monitor:持续读取访问日志写 sqlite,数据目录 968M,瞬时读 6000+ kB/s。
  • Nginx 防火墙 btwaf 的 Webshell 查杀:默认每 20 分钟全盘扫描所有网站文件,一天 72 次,为主要元凶。
  • 资源管理器 resource_manager:每 5 分钟拉起 nethogs 采集流量。
  • journald:堆到 1.3G,systemd 整理时大量读盘。
  • 访问日志未切割:单文件几百 M、共 2G,被上述功能反复读取。

四、处理

1. 面板中停用「网站监控报表」、关闭「每 20 分钟的 Webshell 查杀」、停用「资源管理器 */5 任务」。

2. 清理 journald,实测释放 1.2G,systemd 读尖峰随即消失:

journalctl --vacuum-size=200M

3. 处理后再跑 pidstat -d 1 10 对比,高读进程基本清零,基线 IOPS 大幅下降。

注:磁盘剩余充足(40G 用了 7.1G)时,那 2G 老日志可暂不处理,关掉重读功能后它已不再顶 IOPS。Webshell 查杀如要保留,建议改为每天凌晨一次并排除 uploads/缓存/日志目录,不要长期全关。

五、journald 上限配置(防复发)

采用 drop-in,不改动原配置文件,撤销时删除该文件重启即可:

mkdir -p /etc/systemd/journald.conf.d
cat > /etc/systemd/journald.conf.d/99-size.conf <<'EOF'
[Journal]
SystemMaxUse=200M
EOF
systemctl restart systemd-journald

六、重装防坑清单

  • 网站监控报表(monitor):不常用不装。
  • 资源管理器(resource_manager):默认高频,停用。
  • Nginx 防火墙 Webshell 查杀:勿用默认每 20 分钟全盘扫,改低频或手动。
  • 磁盘分析、网站统计:按需,勿设定时全盘扫。
  • 日志切割:面板「高级设置」开启,每站设保留天数(7~15 天)+ 压缩。
  • 备份任务:放低峰、少留份数,大站优先只备数据库。
  • 内存:建议 ≥2G,内存宽裕可显著降低冷读放大;swap 仅兜底防 OOM,换页同样吃 IO。

七、应急

再次卡顿时,先跑第一节命令定位进程,在面板停用其计划任务或 systemctl stop 对应服务顶过去,确认后再决定长期停用还是降频。平时每周看一次云监控 IOPS 曲线是否逼近上限。

删除日志、改配置、重启服务前务必确认影响范围!