容器可写层空间占用过大怎么办?先把来源和边界说清楚
容器可写层空间占用过大的本质是运行时增量数据没有被限制或及时清理,解决办法就是定位写入来源、设置容量上限、把数据挪出可写层。
很多人发现宿主机磁盘越用越满,第一反应是删镜像、删容器,结果空间只回来一点点,问题往往不在镜像,而在那个容易被忽略的“可写层”,它就像容器运行时自带的一张便签纸,所有没有落到卷里的写入都堆在上面,它不会自动消失,也不会主动通知你。
容器镜像层和可写层空间区别:一个是底片,一个是便签
要治理空间,得先分清两个东西:镜像层和可写层,它们虽然都住在同一个目录里,但行为完全不一样。
Overlay2是当前主流存储驱动,它把镜像层放在下层,全部只读;容器启动时会在最上面加一个可写层,容器内发生的文件创建、修改、删除,默认都发生在这层,镜像层像底片,永远不变;可写层像便签,每次写入都会增加厚度,而且每个容器独享一张。
| 对比项 | 镜像层 | 可写层 |
|---|---|---|
| 读写属性 | 只读 | 可读写 |
| 生命周期 | 镜像存在期间一直保留 | 容器删除后立即消失 |
| 共享性 | 多个容器共享同一层 | 每个容器独占 |
| 空间增长原因 | 镜像构建产生 | 运行时日志、临时文件、缓存 |
| 清理方式 | 删除镜像或清理悬空层 | 删除容器或定期清理容器内数据 |
理解这个区别后,就不会再干“删镜像解决可写层膨胀”这种事了,镜像删得再干净,正在运行的容器该写还是会写。
可写层空间占用从哪里来?三个典型场景
写进可写层的数据,大多数来自下面几类操作,它们很常见,但很少有人把账算到可写层头上。
- 应用日志直接输出到标准输出:Docker默认用json-file驱动把日志写到宿主机
/var/lib/docker/containers/目录,但这份日志并不在可写层里,真正占可写层的是容器内部应用自己写到/var/log/或工作目录下的文件日志。 - 临时文件与缓存:很多程序会在运行时往
/tmp、/var/cache、/root/.cache写入数据,这些路径如果没挂载成tmpfs或卷,就全落在可写层。 -
误把容器当虚拟机用
:在容器里安装软件、下载数据集、生成报表文件,忘记提交成新镜像或挂载卷,数据只存在于当前容器,容器运行越久,可写层越厚。
生产环境中还有一种隐蔽情况:健康检查、探针脚本频繁写临时文件,或者定时任务把备份先写到本地再上传,这类零散写入叠加起来,可写层膨胀速度比想象中快得多。
如何定位可写层空间占用?三条命令直接看
别猜,先看数据,以下命令按顺序执行,基本能定位问题。
docker system df -v:显示所有镜像、容器、卷、构建缓存的磁盘占用,找到最右边一列SIZE,容器的大小就是该容器可写层的当前占用,也可以加--format过滤输出。docker container ls -s:列出正在运行的容器,并附带SIZE字段,这个大小包含可写层内容,但不包含镜像层,如果一个容器的SIZE特别大,基本可以确定就是它在疯狂写可写层。- `du -sh /var/lib/docker/overlay2//diff
:直接查看overlay2目录下每个层diff的大小,对于正在运行的容器,对应的可写层diff目录会明显增长,如果不确定哪个diff属于哪个容器,可以用docker inspect <容器ID> –format ‘{{.GraphDriver.Data.UpperDir}}’`拿到路径。
定位之后别急着删容器,先进入容器看一眼:docker exec -it <容器ID> sh,然后用du -sh /var/log /tmp /var/cache之类的命令找出哪些目录在变大,这一步很重要,因为盲目清理治标不治本。
docker容器可写层空间占用对比:卷、tmpfs和可写层
同样是往容器里写100MB数据,写到不同位置,对宿主机磁盘的影响和性能差异很大,这个对比能帮你决定生产环境到底该用哪种方式。
| 写入位置 | 是否占可写层 | 是否随容器删除 | 磁盘性能 | 适用场景 |
|---|---|---|---|---|
| 可写层 | 是 | 是 | 一般 | 一次性运行、调试 |
| 命名卷 | 否 | 否 | 好 | 数据库、持久化数据 |
| 绑定挂载 | 否 | 否 | 最好 | 日志、配置文件、代码目录 |
| tmpfs挂载 | 是内存 | 是 | 极快 | 临时缓存、会话文件 |
从空间治理角度看,只有“命名卷”和“绑定挂载”能把数据从可写层里抽离出去,让容器删除时宿主机磁盘不被连带填满,tmpfs虽然不写磁盘,但占内存,只适合小体积高并发文件。
生产环境容器磁盘空间占用优化:可写层治理路径
生产环境不能靠人肉盯着,要把可写层治理做成一套固定动作。
限制单个容器的写入量
Docker在较新版本里支持通过storage-opt size=10G来限制容器可写层大小,但前提是存储驱动使用overlay2,并且底层文件系统启用了pquota项目配额(通常指xfs),可以用以下命令验证:
docker run -d --storage-opt size=2G --name test nginx
docker inspect test --format '{{.HostConfig.StorageOpt}}'
不是所有环境都满足这个条件,如果文件系统不支持项目配额,这个参数会直接报错,行业共识认为,与其强行开启配额,不如把写入路径改造掉更稳妥。
把数据从可写层挪出去
这是最有效的长期方案,根据数据类型选择不同挂载方式:
- 应用日志:绑定挂载宿主机目录
-v /data/logs:/var/log/app,并在宿主机侧配置logrotate轮转。 - 临时文件:用tmpfs挂载
--tmpfs /tmp:size=512M,避免写磁盘。 - 数据库、队列数据:使用命名卷
-v db_data:/var/lib/postgresql/data,不要留在可写层。 - 下载、上传目录:绑定挂载到独立数据盘,方便单独扩容和备份。
Kubernetes环境同理,Pod里频繁写入的目录,要么挂emptyDir并设置sizeLimit,要么挂PVC,emptyDir虽然还是临时存储,但可以限制容量,并且Pod删除后自动回收,比裸可写层好管理得多。
定期清理与监控
写个定时任务,每周执行一次:
docker system prune -f --filter "until=168h"
docker container prune -f --filter "until=72h"
docker volume prune -f
注意docker system prune会删除所有停止的容器、悬空镜像和未使用的网络,但不删除命名卷,生产环境执行前务必确认没有需要保留的停止容器。
监控侧可以采集宿主机/var/lib/docker目录的磁盘使用率,再结合每个容器docker inspect出来的可写层大小,设置阈值告警,北京这类一线城市机房,通常系统盘和数据盘分开挂载,容器目录所在分区往往比较小,更需要在日常巡检里单列出来。
北京服务器容器磁盘空间清理:地域性注意事项
在北京机房的服务器上,常见配置是把系统盘做成较小容量的SSD,数据盘做成大容量HDD或NVMe,Docker默认目录/var/lib/docker
落在系统盘,如果容器大量写可写层,很快会把系统盘塞满,导致宿主机无法创建新文件,甚至kubelet异常。
处理这类问题时,先确认目录挂载点:df -h /var/lib/docker,如果发现它和是同一个分区,且使用率持续上升,优先做两件事:第一,把Docker数据目录迁移到数据盘;第二,检查是否有容器把日志或备份写到可写层,迁移数据目录可以参考Docker官方的daemon.json配置"data-root": "/data/docker",迁移前需要停止Docker服务并复制原目录。
地域差异本身不改变可写层机制,但运维习惯和硬件配置比例会影响问题爆发速度,北京机房由于成本较高,小系统盘搭配大容器负载的情况更常见,所以清理动作要更提前。
常见误区
- 删除已停止容器一定能释放可写层空间? 不一定,如果容器还有关联的镜像层被其他容器引用,删除容器只释放它自己的可写层,镜像层不会释放,而且如果容器未被删除,只是停止,可写层依然占着磁盘。
- 把容器重启一下能缩小可写层? 不能,重启不会重置可写层,删除再创建才会,想要一个干净的可写层,只能
docker rm后重新docker run。 - 镜像体积大必然导致容器可写层也大? 不是,镜像层和可写层是分开计量的,一个10GB的镜像启动后,可写层初始可能只有几KB,可写层大小只取决于容器运行后写了多少数据。
容器可写层空间占用相关问答
问:容器可写层空间占用过大,直接删除容器能释放空间吗?
答: 能释放该容器的可写层,但不会释放镜像层和其他容器共享的层,如果容器已经停止且不再需要,删除后空间会立即归还给宿主机,删除前需要确认容器内没有未导出的数据,因为可写层一旦随容器删除,里面没有落到卷里的文件就永久丢失了。
问:生产环境中怎样限制单个容器的可写层空间占用?
答: 在Docker中可使用storage-opt size参数,但需要存储驱动为overlay2且底层文件系统支持项目配额(如xfs pquota),Kubernetes里则为Pod的emptyDir设置sizeLimit或使用ResourceQuota限制可写层总量,更通用的做法是把频繁写入的路径挂载成数据卷,并在卷级别设置配额,这样既不受限于Docker存储驱动能力,也便于独立监控容量,可写层膨胀不会反过来修改镜像层,只会让宿主机的磁盘占用增加。
首发原创文章,作者:王坚,如若转载,请注明出处:https://idctop.com/article/641460.html





