前情提要:unionFS和layer: juejin.cn/post/724403…
不限制容器的写操作,宿主机的磁盘可能被写满,需要限制它写入的数据量,比如只允许一个容器写 100MB 的数据。
不过 OverlayFS 没有直接限制文件写入量的特性。OverlayFS 是通过 lowerdir 和 upperdir 两层目录联合挂载来实现的,lowerdir 是只读的,数据只会写在 upperdir 中。
那可以通过限制 upperdir 目录容量的方式,来限制容器 OverlayFS 根目录的写入数据量吗?
upperdir 在宿主机上也是一个普通的目录,那宿主机上的文件系统是否可以支持对一个目录限制容量?
对于 Linux 上最常用的两个文件系统 XFS 和 ext4,它们有一个特性 Quota,以 XFS 为例
XFS Quota
这个特性可以为 Linux 里的一个用户(user),一个用户组(group)或者一个项目(project)来限制它们使用文件系统的额度(quota),即限制它们可以写入文件系统的文件总量。
我们的目标是限制一个目录中总体的写入文件数据量,显然给用户和用户组限制文件系统的写入数据量并不适合我们的需求。
同一个用户或者用户组可以操作多个目录,多个用户或者用户组也可以操作同一个目录
再来看看 Project 模式。
要使用 XFS Quota 特性,必须在文件系统挂载的时候加上对应的 Quota 选项,比如需要配置 Project Quota,挂载参数就是"pquota"。
对于根目录来说,这个参数必须作为一个内核启动的参数"rootflags=pquota",这样可以保证根目录在启动挂载时,带上 XFS Quota 的特性并且支持 Project 模式。
根目录带"prjquota"字段,就可以确保文件系统已经带上了支持 project 模式的 XFS quota 特性。
下一步,给目录打上一个 Project ID。
mkdir -p /tmp/xfs_prjquota
xfs_quota -x -c 'project -s -p /tmp/xfs_prjquota 101'/
xfs_quota -x -c 'limit -p bhard=10m 101'
新建的目录 /tmp/xfs_prjquota,对它做 Quota 限制,需要对它打上一个 Project ID。
通过 xfs_quota 命令(要下载),给 /tmp/xfs_prjquota 打上 Project ID 值 101, 101 是随便选的。
使用 xfs_quota 命令,对 101 做 Quota 限制。"-p bhard=10m 101"代表限制 101 这个 project ID 的数据块写入量不能超过 10MB。
尝试往 /tmp/xfs_prjquota 写入 20MB 的数据。
执行 dd 写入命令,返回信息"No space left on device"。 表示已经不能再往目录写入数据了,而最后写入数据的文件 test.file 大小也停留在了 10MB。
# ff if=/dev/zero of=/tmp/xfs_prjquota/test.file bs=1024 count=20000
dd: error writing '/tmp/xfs_prjquota/test.file': No space left on device
10241+0 records in
10240+0 records out
10485760 bytes (10 MB, 10 MiB) copied, 0.0357122 s, 294 MB/s
# ls -l /tmp/xfs_prjquota/test.file
-rw-r--r-- 1 root root 10485760 Oct 31 10:00 /tmp/xfs_prjquota/test.file
使用 XFS Quota 的 Project 模式可以限制目录的写入数据量
第一步,给目标目录打上一个 Project ID,这个 ID 最终是写到目录对应的 inode 上。
一旦目录打上 ID 后,目录下的新建的文件和目录也都会继承这个 ID。
第二步,在 XFS 中给 project ID 设置一个写入数据块的限制。
有了 ID 和限制值之后,文件系统就可以统计所有带这个 ID 文件的数据块大小总和,并且与限制值进行比较。一旦所有文件大小的总和达到限制值,文件系统就不再允许更多的数据写入了。
docker的做法
Docker 也是用 XFS Quota 来限制容器的 OverlayFS 大小。
docker run 启动容器时,加上参数 --storage-opt size= ,就能限制容器 OverlayFS 可写入的最大数据量了。
而限制的目录就是"/var/lib/docker/overlay2/<docker_id>"下的 upperdir 目录中对应的"diff"目录