ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

阿里云ECS磁盘使用率过高怎么办?从排查到扩容的完整指南

阿里云ECS磁盘使用率过高怎么办?从排查到扩容的完整指南 阿里云ECS磁盘使用率过高处理方案磁盘写满这件事几乎每个用过阿里云ECS的人都会碰到。轻则服务报错、网站打不开重则数据库直接挂掉连SSH都登不进去。我之前就有一次凌晨两点被报警电话叫醒起因就是一台ECS的数据盘使用率到了98%MySQL写入直接卡死日志文件疯狂滚动把最后一点空间也吃掉了。那次之后我花了整整一个下午梳理了一套完整的排查和处理流程后面再遇到类似问题基本都能在半小时内搞定。今天就把这套方案完整写出来从排查、清理到扩容、预防所有步骤都经过实际验证照着操作你也能处理大部分磁盘告警。这篇文章适合谁看如果你是刚接手阿里云ECS的运维新人或者项目里跑着业务却总担心磁盘突然爆满那这篇内容值得你花十五分钟读完。我会先教你怎么快速定位空间被什么东西占掉再给出几种立竿见影的清理手段然后详细讲清楚在线扩容的正确姿势最后是防止磁盘又满了的监控思路。哪怕你只有基础Linux命令行知识跟着一步步执行也能操作。1. 先搞清楚磁盘是真满还是假满1.1 第一反应不要慌先看整体状态收到磁盘使用率过高告警时我最常看到的现象是人一着急直接跑到服务器上随便删文件结果删了半天使用率纹丝不动。所以第一步不是动手清理而是把系统的真实状态看清楚。登录ECS后先执行两条最基本的命令df -h df -i第一条看的是块设备的使用率也就是我们日常理解的磁盘空间第二条看的是inode使用率这个很多人容易忽略。inode是什么简单说它是文件系统用来记录文件元数据的存储结构每个文件或目录都要占用一个inode。如果小文件特别多可能出现磁盘空间还有剩余但inode已经耗尽的情况表现就是明明df -h显示还有空间却创建不了新文件、报no space left on device。我见过一个实际案例某台服务器上部署了定时任务每天生成几万个几KB的小日志文件跑了大半年磁盘空间用了60%但inode使用率到了100%系统直接拒绝写入。所以看到磁盘告警先两条命令一起跑确认是空间问题还是inode问题方向不对后面的努力全白费。1.2 用du找出真正的空间大户确认是块设备空间不足后接着就要定位是哪个目录吃了空间。这里我有一个固定套路df -h du -sh /* 2/dev/null | sort -hr | head -10第一行先看挂载点情况确认哪个分区告警第二行统计根目录下一级目录的大小把最大的十个列出来。du执行时会读磁盘上所有文件如果磁盘文件特别多这个命令可能会跑几分钟耐心等它跑完期间不要中断中断了反而要重新扫。2/dev/null是屏蔽权限不足的报错信息避免刷屏。如果告警的是数据盘挂载在比如/data目录那就把第二行命令改成du -sh /data/* 2/dev/null | sort -hr | head -10这样一层层往下钻很快就能锁定问题目录。我遇到的情况里空间被占的大头往往是这几种应用日志、数据库数据文件、用户上传文件、备份文件、docker容器日志、core dump文件。前三种属于业务真实数据不能乱删后面的基本都在可以清理的范围。2. 清理磁盘空间的手段从安全到激进排序2.1 日志文件清理的三种姿势日志是最常见的磁盘杀手尤其是那些日积月累不打折的nginx访问日志、Java应用日志、系统journal日志。清理方式分三种我按安全性从高到低排一下。第一种是清理systemd journal日志这是系统自身的管理日志。很多服务器跑着跑着/var/log/journal目录能涨到好几个GB。在CentOS 7或Ubuntu 18.04系统上执行journalctl --vacuum-size200M这条命令会把journal日志压缩清理到200MB以内非常安全不会影响系统运行。如果你希望以后限制journal日志的最大体积可以编辑/etc/systemd/journald.conf找到SystemMaxUse选项改成SystemMaxUse200M保存后重启systemd-journald服务生效。第二种是清理应用日志和nginx访问日志。对于应用日志正确的做法不是直接rm删除因为如果Java进程还开着那些日志文件句柄直接删掉文件后磁盘空间并不会释放这就是很多人觉得删了日志空间没变化的原因。我一般用truncate方式清空 /var/log/app/app.log # 或者用 truncate -s 0 /var/log/app/app.log清空后文件大小为0磁盘空间立刻释放进程写日志也不受影响。对于老的日志文件比如nginx的access.log.20240101.gz这类滚动备份确认不需要了可以删除或者用find /var/log/nginx -name *.gz -mtime 30 -delete只删30天前的压缩日志。第三种是配置logrotate自动化日志轮转这才是治本的办法。在/etc/logrotate.d/目录下为应用日志创建配置比如/var/log/app/*.log { daily rotate 7 compress delaycompress missingok notifempty copytruncate }这段配置的含义是每天轮转一次保留7份旧日志旧日志压缩存储copytruncate方式适合那些不重新打开日志文件的进程。配置好后可以执行logrotate -f /etc/logrotate.d/app强制测试一次。2.2 系统包缓存和临时文件yum、apt这些包管理器在安装软件时会下载很多rpm包或deb包这些缓存用完之后就躺在那积少成多也是几个GB的量。CentOS系统执行yum clean all rm -rf /var/cache/yum/*Ubuntu系统执行apt clean rm -rf /var/cache/apt/archives/*.deb临时目录/tmp和/var/tmp下面的文件也值得看一眼有些程序运行时会往这里写临时文件退出后没清理干净。可以查看哪些文件比较大确认不是正在使用的再删除du -sh /tmp/* 2/dev/null | sort -hr | head -20还有一类容易被忽略的是core dump文件进程崩溃时生成的核心转储文件一个可能就好几个GB。检查系统有没有开启core dump以及已有的core文件cat /proc/sys/kernel/core_pattern find / -name core.* -type f -size 100M 2/dev/null如果确认不需要分析崩溃现场直接删除即可并在/etc/sysctl.conf里加上fs.suid_dumpable0或调整core_pattern路径限制生成。2.3 docker日志清理的特殊处理如果你的ECS上跑着docker容器那docker日志占用空间的速度可能远超你的想象。docker的日志驱动如果是json-file默认情况下不会自动切割一个容器能写几百MB甚至上GB的日志。查看各个容器日志大小find /var/lib/docker/containers -name *-json.log -exec ls -lh {} \; | sort -k5 -hr | head -10清理方式有两种。临时方案是清空日志文件truncate -s 0 /var/lib/docker/containers/*/*-json.log治本方案是给docker配置日志轮转创建/etc/docker/daemon.json写入{ log-driver: json-file, log-opts: { max-size: 10m, max-file: 3 } }这个配置的意思是单个日志文件最大10MB最多保留3个文件。改完后需要重启docker服务才能生效注意重启会中断容器务必要在业务低峰期操作。2.4 大文件定位与删除决策清理完上面这些常规项目后如果使用率还是高那就必须用工具全盘扫描大文件了。我常用的命令是find / -xdev -type f -size 100M -exec ls -lh {} \; 2/dev/null | sort -k5 -hr | head -30这条命令会找出根文件系统下所有超过100MB的文件按大小排序。处理这些文件时要非常谨慎我的决策逻辑是这样的扩展名带.log、.tmp、.core的基本可以清理路径在/tmp、/var/tmp下的基本可以清理应用目录下的数据文件不要动数据库目录下的ibd文件绝对不要动那是数据文件本体。有一个案例我记得很清楚某个用户自己写的一个导出程序每次运行都会在/data/export下生成一个几GB的CSV文件跑了几十次空间就满了。这种情况光删文件不够得找到生成源在程序里加上定期清理逻辑。3. 清洁不掉了直接扩容3.1 扩容前必须搞清楚的三种情况清理完垃圾后使用率还是高比如数据盘本身容量就小业务增长又快那就得扩容了。阿里云ECS扩容操作本身不复杂但有几个前置条件必须搞清楚否则会出现控制台点了扩容但系统里看不到新空间的情况。第一种情况系统盘满了。系统盘扩容在控制台上操作但有一个前提——系统盘必须是包年包月实例按量付费的实例不支持直接扩容系统盘。而且系统盘扩容只支持升配不支持降配操作前要谨慎确认。第二种情况数据盘满了而且数据盘是单独购买的标准云盘或高效云盘。这种扩容在控制台直接操作就行。第三种情况数据盘是随实例创建的并且数据盘和实例是同生命周期的关系。这种盘扩容前需要先在控制台把云盘从实例上卸载再执行扩容操作否则按钮是灰的。这里特别提醒一句卸载数据盘前一定要先在服务器内部执行umount命令卸载挂载点否则数据可能损坏。3.2 在线扩容完整步骤阿里云大部分云盘类型支持在线扩容也就是不停机扩容。操作流程分两大步控制台扩容、系统内扩展文件系统。控制台部分的操作路径是登录阿里云控制台进入ECS实例列表点击实例ID进入详情页找到云盘标签页。在目标云盘的操作列点击扩容填写期望的容量比如从40GB扩到60GB。确认费用后提交工单扩容任务一般几秒到几分钟完成。注意扩容后的容量需要下一次重启或者内部操作后才对系统可见。系统内部操作才是最关键的。扩容完成后回到服务器上执行df -h lsblkdf -h看到的还是旧容量因为文件系统还没有扩展。lsblk会显示块设备的真实容量如果看到/dev/vdb已经是60GB说明云盘扩容已在底层完成。接下来要扩展分区和文件系统这里分两种情况。情况一云盘只有一个分区且分区占满整个盘。执行growpart /dev/vdb 1 resize2fs /dev/vdb1growpart命令的作用是把分区扩展到整个磁盘大小。如果没有安装growpart先执行yum install -y cloud-utils-growpartCentOS或apt install -y cloud-guest-utilsUbuntu。resize2fs用于扩展ext4文件系统。情况二文件系统是xfs。ext4用resize2fsxfs必须用xfs_growfs命令是xfs_growfs /dev/vdb1 # 如果xfs挂在/data目录可以 xfs_growfs /dataxfs和ext4在扩容时不能混用命令我就见过有人用resize2fs去扩xfs文件系统结果报错说Filesystem has unsupported feature(s)。执行完后再次df -h确认容量应该已经刷新。3.3 系统盘扩容的额外坑系统盘扩容相比数据盘多一个步骤扩容后需要在控制台重启实例而且系统盘的扩容只能在离线状态下操作也就是说实例必须处于已停止状态。在停止实例前务必到阿里云控制台确认一下当前实例是不是节省停机模式如果是停止后可能涉及公网IP变化或磁盘快照计费的变化。我之前在一个生产环境上忘记确认这个重启后IP变了一堆白名单和客户端配置全部要改。系统盘扩容的具体操作先停止实例然后在云盘列表里找到系统盘对应的那块盘点扩容输入目标容量。扩容完成后启动实例再到系统内执行文件系统扩展。系统盘扩容同样遵循前面的文件系统类型匹配原则看清楚是ext4还是xfs再动手。4. 各种疑难杂症与避坑指南4.1 为什么删除文件后空间没释放这个坑我前前后后踩了三次。现象是你明确删除了一个大文件文件也确实不在目录里了但df -h显示使用率一点没降。原因是有一个进程还持有这个文件的句柄文件被删除了但进程还在写入或锁定它占用的空间不会被系统回收只有进程退出或关闭文件句柄后才释放。验证方法lsof | grep deleted查到持有句柄的进程PID后确认这个进程可以重启再执行kill -HUP pid或者重启服务。停掉进程后你会发现磁盘空间瞬间就吐出来了。还有一种相对少见的情况日志文件被删除后进程重启时又重新创建了新文件但老文件句柄还在空间一样不释放。所以处理占用空间的日志文件优先用truncate而不是rm。4.2 扩容后在系统里看不到新容量怎么办控制台操作扩容成功lsblk也能看到新容量但df显示的还是老容量。这种一般是文件系统扩展步骤没执行或者执行失败。排查步骤# 1. 确认分区表大小 cat /sys/block/vdb/size # 2. 查看分区信息 fdisk -l /dev/vdb # 3. 重新执行分区扩展 growpart /dev/vdb 1如果growpart报错unexpected output多半分区不是以标准方式开始的这时需要手动用fdisk删除分区再重建操作非常危险非专业人员不建议尝试直接提交工单给阿里云售后处理更稳。顺便说一句阿里云工单里面磁盘扩容这类问题售后支持响应很快不要不好意思提工单。4.3 数据盘没分区直接格式化怎么扩容有些用户买完数据盘后直接mkfs整块盘没有分区比如直接格式化/dev/vdb而不是/dev/vdb1。这种情况下growpart无从下手正确的处理方式是先扩充云盘容量然后直接扩展文件系统。对ext4resize2fs /dev/vdb对xfsxfs_growfs /dev/vdb不需要走分区扩展的步骤因为整块盘就是一个超级大分区。这一点很多人不知道跟着网上的教程非要给无分区的盘做growpart结果报错才开始找别的路。4.4 磁盘IO和空间不足的区别最后补充一个常被混淆的概念磁盘使用率过高和磁盘IO过高不是一回事。磁盘使用率看的是空间磁盘IO看的是每秒读写次数和吞吐量。如果空间充足但服务还是很卡检查IOPSiostat -x 3重点看%util、await、svctm这几列。%util接近100%说明磁盘一直在满负荷运转这时候扩容反而正确如果%util不高但await很高可能是磁盘性能不足或者有随机读写冲突这种情况要换ESSD或者优化业务读写模式不是扩容能解决的。查询阿里云控制台上的实例监控可以看到磁盘IOPS和BPS的历史曲线判断性能瓶颈很直观。5. 一劳永逸的监控预防方案5.1 设置云监控告警处理完一次磁盘告警后如果不做监控下次业务量增长时肯定还会爆。阿里云自带云监控服务不需要额外部署agent就能采集ECS的磁盘使用率指标。打开云监控控制台创建告警规则告警规则名称ECS磁盘使用率告警关联资源选择你的ECS实例指标磁盘使用率触发条件使用率超过85%持续3个周期1个周期5分钟通知方式邮件短信钉钉机器人阈值我建议设两个85%为警告95%为紧急。85%是提醒你开始排查95%是亮红线提醒你必须马上处理。间隔太短容易误报5分钟一个周期比较合理既不会漏掉快速增长的场景也不会被瞬时波动干扰。5.2 定期巡检脚本思路云监控负责实时告警我还要搭配一个定时巡检脚本每周跑一次自动输出磁盘使用Top10目录发到运维群里。写一个简单的Shell脚本放在/etc/cron.daily/下#!/bin/bash echo 磁盘使用情况 $(date) /var/log/disk_check.log df -h /var/log/disk_check.log echo 目录Top10 /var/log/disk_check.log du -sh /home/* /var/* /data/* 2/dev/null | sort -rh | head -10 /var/log/disk_check.log然后配合钉钉机器人的webhook把内容推送到群里。这种方式成本很低但能保证每周都有人注意到磁盘变化的趋势而不是等到告警响了才被动处理。5.3 容量规划经验根据我的经验数据盘的使用率长期维持在60%以下是比较健康的。超过70%就值得警惕超过85%基本要在两周内处理否则遇到业务高峰极易触发写满。如果业务数据增长明显处理时优先考虑扩容而不是反复清理因为清理只能解决眼前的问题业务在增长磁盘总会被吃完。扩容时有一个小技巧一次扩容的容量建议至少翻倍或者扩到当前容量的1.5倍以上不要50GB变55GB这种挤牙膏式扩容每次都要付人工成本不如一步到位。我个人在实际操作中还有一个心得所有涉及磁盘的操作特别是删除大文件、扩容文件系统这种操作前都必须确认快照已经打好或者至少确认备份可用。阿里云控制台给磁盘打快照很快一个40GB的盘做快照也就几分钟但万一操作失误快照就是唯一的后悔药。我见过因为没打快照直接fdisk删分区最后数据全没了的案例那种代价远大于几分钟的快照等待时间。最后说一个很多人不知道的功能阿里云控制台的磁盘分析工具可以针对每个云盘生成空间分析报告哪些目录占用大、哪些文件增长快都看得清清楚楚。这是阿里云售后工程师教我的比用命令行一个个翻高效得多。处理磁盘问题的第一原则就是先把情况看清楚再动手这句话你可能觉得啰嗦但绝大多数翻车现场都是因为没看情况就乱删东西。先把排查流程过一遍再根据实际占用来决定清理还是扩容你的ECS磁盘就不会再频繁亮红灯。
返回列表