事故简述
一早上来到公司,看到报警有大量报警信息。
云服务器实例ID=xxxx,device=/dev/vda1] /dev/vda1 ,磁盘使用率(100%>=97% )(100%>=97%),持续时间5小时46分钟
这个服务主要有2个功能 1.作为定时任务的主要执行机器。 2.部署了archery这个sql审核平台。
一开始怀疑是某个定时任务产生了大量日志文件,问了周围同事,最近并没有新增定时任务。
靠经验判断不行,那只能去定位大文件的位置,然后再继续分析问题了。
磁盘满了,定位大文件的通常步骤
- 1.使用df -h查看磁盘空间占用情况。
可以发现是/dev/vda1
磁盘占用较多,对应/
根目录
aplum@task:/ df -h
Filesystem Size Used Avail Use% Mounted on
/dev/vda1 99G 93G 2G 95% /
/dev/vdb1 985G 322G 618G 35% /data
- 2.使用
du -s /* | sort -nr
命令查看那个目录占用空间大
因为没有权限,所以我这里给出示意结果。
/data/aplum/Archery-1.7.10/src/docker-compose 占用很大
du -lh –max-depth=1 | sort -n |
- 3.然后看哪个目录占用多,再通过
du -s 怀疑的路径 | sort -nr
一层层排查,找到占用文件多的地方。
我今天发现的问题是/data/aplum/Archery-1.7.10/src/docker-compose/mysql/datadir/
- 4.查看archery的docker-compose.yaml文件,发现mysql容器挂载到了该目录。
archery应该执行某种操作,导致archery的mysql插入了大量的数据.
version: '3'
networks: 略
services:
redis:略
mysql:
image: mysql:5.7
container_name: mysql
restart: always
ports:
- "3306:3306"
volumes:
- "./mysql/my.cnf:/etc/mysql/my.cnf"
- "./mysql/datadir:/var/lib/mysql" # mysql容器挂载到了该目录
environment:
MYSQL_DATABASE: archery
MYSQL_ROOT_PASSWORD: xxx
networks:
- cow-cow
inception: 略
goinception: 略
archery: 略
- 5.因为昨天同事通过archery平台提交了一个大表的删除语句,该表一共3000w+的数据,此次删除2000w+,按照id拆分为十多个如下删除语句:
DELETE FROM 某个大表 where user_id = 0 and id BETWEEN 0 and 5000000;
- 6.结合阿里云的云盘监控可以看到
2021-07-08 04:30:00
左右,云盘使用空间从75%猛增为100%。 这个sql执行时间为2021-07-08 04:05:00
,正好接近磁盘分区(/dev/vda1)的使用空间陡增的时间,
发现到大文件后,不能删除,需要移动到/dev/vdb1
这个大磁盘中
因为这是archery的docker集群的一个挂载文件,所以只能把archer整体迁移。
正好这个机器还有1个空间充足的磁盘/dev/vdb1
,mv过去即可。
迁移docker-compose部署的archery的一些问题
1.首先,Archery的安装方式设计的比较方便迁移, 解压Archery-1.7.10.tar.gz后,所有东西都在里面了.
尤其是docker-compose.yaml中的volumes挂载都是相对路径
,这样我只需要把解压后的目录整体移动,其中的数据也会一起迁移,因为mysql的挂载目录也在里面。
2.实际处理问题的时候,因为对于docker-compose的up,down,start,stop命令不够熟悉,导致没有及时解决问题,这里记录一下。
- 我们错误的迁移步骤
1.我们执行了stop命令
2.然后执行mv迁移解压后Archery目录到/dev/vdb1
3.然后切入到docker-compose的目录,执行docker start,发现启动不了,【报错信息说原来的挂载路径找不到】
//原因是:stop命令只是停止容器,而我们已经移动了挂载的目录,重写删除容器,重新挂载。
4.所以执行down命令删除容器和挂载关系。
5.然后执行docker-compose up命令,archery就在迁移后成功重启了,且其中mysql的挂载目录也切换到了新的磁盘空间。
aplum@task:/data/aplum docker-compose -h
Define and run multi-container applications with Docker.
Usage:
docker-compose [-f <arg>...] [options] [COMMAND] [ARGS...]
docker-compose -h|--help
Options:
Commands:
down Stop and remove containers, networks, images, and volumes # 停止和删除容器、网络、卷、镜像,这些内容是通过docker-compose up命令创建的. 默认值删除 容器 网络,可以通过指定 rmi 、volumes参数删除镜像和卷。
start Start services # 启动已经存在的服务容器。
stop Stop services # 停止已经处于运行状态的容器,但不删除它。通过 docker-compose start 可以再次启动这些容器
up Create and start containers # 它尝试自动完成包括构建镜像,(重新)创建服务,启动服务,并关联服务相关容器的一些列操作。链接的服务都将会被自动启动,除非已经处于运行状态。多数情况下我们可以直接通过该命令来启动一个项目。
总结
- linux磁盘已满,查看哪个文件占用多。
- 如何知道哪个磁盘增长最多. 一般来说,就是文件最大的那个增长最多,有时也需要结合经验判断。
- 对于大文件,要么删除,要么移动。我们对于此次问题,因为我们的大文件是mysql容器挂载的数据文件,所以不能删除,需要移动。
archery删除大表时的回滚机制是怎么做的,为什么会占用大量的磁盘空间?
// 附录5 archery每执行一个sql,就会在备份库里生成对应的sql语句,而且产生的回滚语句都是针对一行的, 所以今天的大表的删除语句产生的回滚sql应是2千多万行,导致磁盘占用从75G变为100G,基本对得上。
附录6:
统计当前文件夹(目录)大小,并按文件大小排序: du -sh * | sort -n du -lh –max-depth=1 |sort -n
2022-02-28更新
// 附录7,8
-
背景 也是磁盘报警,然后我们发现是日志切割问题导致产生了一个超大的日志文件。 然后我们删除了这个文件,但是df -lh查看的Avail空间并没有减少 和
du -sh *
去日志目录统计磁盘占用, 发现并没有减少。 TODO 这里好像可以说明磁盘文件并没有被释放。需要理解磁盘原理后明确这点。 -
现象 rm删除,但是发现并没有释放磁盘空间。需要重启进程才能真的释放磁盘空间
通过lsof命令查找运行中的进程占用已经删除的文件:
lsof | grep delete |sort -nrk 7|more
- 原因
因为某个服务的日志切割方法,是很早之前实现,没有经过严格测试。 存在某些情况,某个日志文件无法切割,逐渐变成大文件。
猜测:日志切割流程中存在重命名和删除操作,某个操作会导致进程持有fd。即使导致我们在命令行删除文件时,该文件fd还一般被进程占用,不能真正被删除?
可以使用
lsof | grep delete |sort -nrk 7|more
查看
参考
1.linux磁盘已满,查看哪个文件占用多 2.goInception Docs-TODO回滚机制 3.docker compose 几个命令 4.docker compose down命令的作用 5.Inception 备份功能说明 6.Linux查看文件或文件夹大小: du命令 7.lsof 命令用法:查看已删除空间却没有释放的进程 8.利用lsof命令查找已经删除的文件来释放磁盘空间
原创文章转载请注明出处: 【线上事故处理】磁盘满了的处理步骤复盘总结