V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
mayooot
V2EX  ›  Docker

使用 Ballast 文件解决 Docker 容器磁盘占满无法启动的问题

  •  
  •   mayooot · 87 天前 · 1071 次点击
    这是一个创建于 87 天前的主题,其中的信息可能已经有所发展或是发生改变。

    使用 Ballast 文件解决 Docker 容器磁盘占满无法启动的问题

    背景

    在容器开发工作中,售卖算力容器是一个很常见的需求,不管是用 Docker 容器还是 K8s Pod 交付。

    其中有一个问题是:我们提供给用户的容器默认是没有限制 / 目录的,虽然说这些都是临时文件,真正需要持久化的文件我们可以提供分布式存储,然后挂载到用户容器的某个目录。

    一个简单而有效的方式是使用 XFS 文件系统配合 --storage-opt 参数就能限制用户容器的 / 目录,也可以说是限制用户容器的系统盘大小。

    问题

    但是当用户长期使用一个容器,比如在容器里进行模型训练,会导致系统盘空间越来越小,当系统盘空间已经非常接近我们设置的大小时,例如限制系统盘大小为 20Gi ,用户已经使用了 19.9999Gi ,这时候当用户 Stop 了容器(关机),再次 Restart/Start 容器(开机)时很可能会失败。

    报错信息如下:

    Error response from daemon: mkdir /localData/docker/overlay2/7adae703b531d3e114cd171999e5502fe685e13835569b6f1d9fb31ab812773b/merged: disk quota exceeded 
    

    这好像没什么好的解决办法,因为造成问题的原因是用户把容器当成了虚机来用,一般情况下我们也不会持久化用户容器的临时文件。

    但目前确实遇到了这个问题,所以和朋友一番讨论后,想出来了一个思路。

    实现思路

    前段时间研究了一下 Golang 控制 GC 频率的方法,其中使用的是 ballast ,就像下面代码中: 初始化了一个生命周期贯穿整个 Go 应用的超大 Slice ,保证 GC 在 10G 的一倍时才被触发。

    详情参考这篇文章 性能优化 | Go Ballast 让内存控制更加丝滑

    package main
    
    import "runtime"
    
    func main() {
    	ballast := make([]byte, 10*1024*1024*1024) // 10G
    
    	// do something
    
    	runtime.KeepAlive(ballast)
    }
    

    所以脑洞大开,我们能不能也用 ballast 的思想来为容器提供一个 ballast ,当容器磁盘不足时,我们手动减少这个 “压舱石” 的大小,这样就能能保证容器关机后,再次重启时,不会因为磁盘不足,导致失败了。

    当然这样的操作是基于一个前提的,就是:

    无论如何都不应该删除用户容器里的任何东西,即使是日志或者垃圾文件。

    所以使用一个人畜无害的压舱石,可能是比较优雅的方式。

    坏处也很明显,就是用户可以删除这块压舱石,并且用户 df -h 看到的空间是和实际购买的不一样。

    具体实现

    用户开通容器时

    当用户开通一个容器,我们会限制用户容器的系统盘大小,比如说默认 20Gi 的空间,但是通过程序开通容器时,我们使用 --storage-opt size 限制时会把系统盘大小设置为 20Gi + 5Gi ,5Gi 的文件作为一个 ballast (压舱石)存在于用户的容器中。

    当用户使用了 19.9Gi (实际情况下要比这个数字更接近 20Gi ) 的空间后,df -h 显示如下内容:

    $ df -h
    Filesystem                             Size    Used   
    /                                      25Gi    24.9Gi
    

    用户关机时

    重点在 Stop 时,如果说 Used 已经很接近 Size 了,那么我们就调整 ballast 的大小,保证用户容器正确启动。

    举个例子,当 Used 已经为 24.9Gi ,限制的大小为 25Gi ,我们 Stop 时,把 ballast 的大小减小 0.5Gi, 保证用户容器正确启动。

    源码地址

    ballast-docker-container

    如果对你有帮助,请给我一个 Star ⭐️

    目前尚无回复
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1063 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 19ms · UTC 19:53 · PVG 03:53 · LAX 11:53 · JFK 14:53
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.