文章目录
OverlayFS
OverlayFS是一种现代的联合文件系统,与AUFS类似,但是速度更快且实现更简单。Docker为OverlayFS提供了两个存储驱动程序:原始的overlay
,更新的和更稳定的overlay2
。
前提条件
- overlay2驱动程序支持Docker Engine - Community和Docker EE 17.06.02-ee5及以上,是推荐的存储驱动程序。
- Linux内核4.0或更高版本,或使用内核3.10.0-514或更高版本的RHEL或CentOS。如果使用一个旧的内核,需要使用overlay驱动程序,这是不推荐的。
- xfs支持的文件系统支持overlay和overlay2驱动程序,但只有启用了d_type=true。
使用xfs_info验证ftype选项是否设置为1。要正确格式化xfs文件系统,使用-n ftype=1标志。 - 更改存储驱动程序会使本地系统上无法访问现有的容器和镜像。在更改存储驱动程序之前,使用docker save来保存已经构建的任何镜像,或者将它们推入docker Hub或私有注册表,这样就不需要在以后重新创建。
使用overlay或overlay2存储驱动程序配置Docker
- 停止Docker。
systemctl stop docker
- 编辑
vim /etc/docker/daemon.json
,切记,如果不止一项配置,需要,
隔开{ "storage-driver": "overlay2" }
如果daemon.json文件包含格式错误的JSON,则Docker无法启动。
- 启动Docker。
systemctl start docker
- 验证守护程序正在使用overlay2存储驱动程序。使用docker info命令并查找Storage Driver和 Backing filesystem。
docker info Containers: 0 Images: 0 Storage Driver: overlay2 Backing Filesystem: xfs Supports d_type: true Native Overlay Diff: true <output truncated>
overlay2驱动程序是如何工作的
在一个Linux主机上覆盖两个目录,并将它们表示为一个目录。
这些目录称为层,统一过程称为联合挂载。
OverlayFS将下面的目录称为lowerdir
,上面的目录称为upperdir
。统一视图通过其自己的目录merged
公开。
overlay2驱动程序本身最多支持128个较低的OverlayFS层。该功能为与层相关的Docker命令(如Docker build和Docker committ)提供了更好的性能,并且消耗支持文件系统上的更少的inode。
当镜像层和容器层包含相同的文件时,容器层“胜出”并掩盖了镜像层中相同文件的存在
。
创建一个容器,overlay
驱动程序将代表镜像顶层的目录和容器的新目录组合在一起。镜像的顶层是覆盖层中的下层,并且是只读的。容器的新目录是upperdir,并且是可写的。
磁盘上的镜像和容器层
镜像层
每个镜像层在磁盘上都有自己的目录,镜像的ID和目录ID不对应。
镜像层目录包含该层独有的文件以及与较低层共享的数据的硬链接。这样可以有效利用磁盘空间。
容器层
容器也存在于Docker主机文件系统下的磁盘上 /var/lib/docker/overlay/I。
容器如何使用overlay或overlay2进行读写
文件读取
考虑三种情况
该文件在容器层中不存在:
文件在容器中还不存在(upperdir),则从镜像(lowerdir)中读取该文件。这只会带来很少的性能开销。该文件仅存在于容器层中:
文件存在于容器中(upperdir),而不在镜像中(lowerdir),则直接从容器中读取该文件。该文件同时存在于容器层和镜像层:
文件存在于镜像层和容器层中,则读取该文件在容器层中的版本。容器层中的文件(upperdir)掩盖了与镜像层(lowerdir)同名的文件。
修改文件或目录
考虑容器中的文件被修改的一些场景。
-
第一次写入文件:
容器第一次写入现有文件时, 该文件在容器中不存在(upperdir)。overlay/overlay2
驱动程序执行copy_up操作, 将文件从镜像(lowerdir)复制到容器(upperdir)。然后容器将更改写入容器层中文件的新副本。但是,OverlayFS是在文件级别而不是块级别工作的。这意味着所有的OverlayFS
copy_up
操作都会复制整个文件,即使文件非常大,并且只有一小部分被修改。这对容器写性能有明显的影响。然而,有两件事值得注意:copy_up
操作只在第一次将给定文件写入时发生。对同一个文件的操作后续都是在复制到容器层的副本上进行操作。OverlayFS只适用于两层。这意味着性能应该优于AUFS,后者在搜索多层镜像中的文件时可能会出现明显的延迟
。这一优势适用于overlay
和overlay2
驱动程序。在初始读取时,overlayfs2的性能略低于overlayfs,因为它必须遍历更多的层,但是它会缓存结果,所以这只是很小的损失。
-
删除文件和目录 :
- 当在容器中删除文件时,将在容器中创建一个whiteout文件(upperdir)。镜像层(lowerdir)中的文件的版本没有被删除(因为lowerdir是只读的)。但是,whiteout文件阻止容器使用它。
- 当在容器中删除目录时,将在容器中创建一个不透明的目录(upperdir)。这与whiteout文件的工作方式相同,可以有效地阻止对目录的访问,即使它仍然存在于镜像(lowerdir)中。
重命名目录:
仅当源和目标路径都位于顶层时,才允许对目录调用rename(2)。否则,它将返回EXDEV错误(“不允许跨设备链接”)。应用程序需要设计成处理EXDEV并退回到“复制并断开链接”策略。
OverlayFS和Docker性能
与aufs
和devicemappe
r相比,overlay2
和overlay
驱动程序的性能更好。在某些情况下,overlay2
也可能比btrfs
表现得更好。但是,请注意以下细节。
- 页面缓存。OverlayFS支持页面缓存共享。访问同一文件的多个容器共享该文件的单个页面缓存条目。这使得
overlay
和overlay2
驱动程序在内存方面非常高效,对于高密度的用例(比如PaaS)是一个很好的选择。 - copy_up。与AUFS一样,每当容器第一次写入文件时,OverlayFS都会执行复制操作。这可能会增加写操作的延迟,特别是对于大型文件。但是,一旦文件被复制,对该文件的所有后续写操作都发生在上层,不需要进一步的复制操作。
OverlayFS的copy_up
操作比使用AUFS的相同操作要快,因为AUFS支持比OverlayFS更多的层,如果搜索多个AUFS层,可能会导致更大的延迟。overlay2
也支持多层,但是通过缓存可以降低任何性能损失。 - Inode的限制。使用旧的
overlay
存储驱动程序会导致过多的inode消耗。在Docker主机上存在大量的镜像和容器时尤其如此。增加文件系统可用inode数量的惟一方法是重新格式化它。为了避免遇到这个问题,强烈建议尽可能使用overlay2。