OverlayFS也是一种联合文件系统,与AUFS类似,但是速度更快且实现更加简单。Docker为OverlayFS提供了两个存储驱动程序:即overlay,以及更新和更稳定的overlay2。
在这里将Linux内核驱动程序称为OverlayFS和,将Docker存储驱动程序称为overlay或overlay2。
1、使用条件
只有在满足以下条件的情况,才支持使用OverlayFS:
- Docker社区版和Docker企业版17.06.02-ee5及更高的版本支持overlay2驱动程序,并且是推荐的存储驱动程序。
- 在Linux内核版本为4.0或更高时,或使用内核的版本为3.10.0-514或更高版本的RHEL或CentOS。如果使用较旧的内核,则需要使用overlay驱动程序。
- 在d_type=true时,overlay和overlay2驱动程序支持xfs格式的文件系统。使用xfs_info
验证ftype选项设置为1。请使用标志-n ftype=1,以正确的格式化xfs文件系统,。
- 在变更存储驱动时,本机上现有的容器和镜像将会失效。可以通过docker save或将这些镜像上传至镜像仓库进行保存。
2、配置docker使用overlay存储驱动
建议overlay2尽可能使用驱动程序,而不要使用overlay驱动程序。Docker EE 不支持该overlay驱动程序。要将Docker配置为使用overlay存储驱动程序,Docker主机必须运行Linux内核的3.18版本(最好是更新的)并加载了覆盖内核模块。对于overlay2驱动程序,内核版本必须为4.0或更高版本。
以下步骤概述了如何配置overlay存储驱动程序。
1)通过执行下面的命令,停止Docker。
$ sudo systemctl stop docker
2)备份docker根目录下(默认为/var/lib/docker)的数据。
$ cp -au /var/lib/docker /var/lib/docker.bk
3)编辑/etc/docker/daemon.json。如果此文件尚不存在,则请创建它。在这里假设此文件为空,添加以下内容。
{
“storage-driver”: “overlay”
}
4)通过下面的命令启动Docker。
$ sudo systemctl start docker
5)通过执行docker info,查看验证守护程序正在使用overlay存储驱动。
$ docker info
3、overlay工作方式
OverlayFS在Linux主机上分为两个目录,并将它们显示为单个目录。这些目录称为层,统一过程称为联合挂接。OverlayFS将较低的目录称为lowerdir,将较高的目录称为upperdir。统一视图被成为merged。
下图显示了如何将Docker镜像和Docker容器镜像分层。镜像层是lowerdir,容器层是upperdir
,统一视图merged是实际上容器的挂接点。该图显示了Docker构造是如何映射到OverlayFS构造。
overlayfslowerdir,upperdir,合并
在镜像层和容器层包含相同文件的情况下,容器层“获胜”并覆盖了镜像层中相同文件的存在。
overlay驱动程序仅适用于两层。这意味着不能将多层镜像实现为多个OverlayFS层。而是将每个镜像层实现为自己的目录/var/lib/docker/overlay。然后,将硬链接用作节省空间的方式来引用与较低层共享的数据。硬链接的使用会导致索引节点的过度使用,这是对传统overlay存储驱动程序的已知限制,并且可能需要对备份文件系统进行其他配置。
为了创建一个容器,overlay驱动程序将代表镜像顶层的目录与该容器的新目录结合在一起。镜像的顶层lowerdir位于叠加层中,并且是只读的。容器的新目录是upperdir且可写。
在操作系统中对应的目录:
- lower-id:文件包含容器所基于顶层镜像的ID,即OverlayFS lowerdir
- upper:目录包含容器读写层的内容,该层对应于OverlayFS upperdir
- merged:目录是联合挂接的lowerdir和upperdir,包括正在运行容器内的文件系统视图。
- work:OverlayFS内部的目录。
4、容器使用overlay进行读写
4.1 读取文件
考虑三种情况,其中容器打开文件以进行覆盖访问。
- 文件在容器层中不存在:如果容器打开文件进行读取访问,并且该文件在容器(upperdir)中尚不存在,则将从镜像中读取该文件(lowerdir)。这将导致很少的性能开销。
- 该文件仅存在于容器层中:如果容器打开文件进行读取访问,并且该文件存在于容器(upperdir)中,而不存在于镜像(lowerdir)中,则直接从容器中读取文件。
- 文件在容器层和图像层中均存在:如果容器打开文件以进行读取访问,并且文件在镜像层和容器层中存在,则将读取容器层中文件的版本。容器层(upperdir)中的文件会使镜像层(lowerdir)中具有相同名称的文件被忽略。
4.2 修改文件或目录
- 首次写入文件:容器第一次写入现有文件时,如果该文件在容器(upperdir)中不存在。overlay/
overlay2驱动器会执行一个copy_up操作将文件从镜像(lowerdir)复制到容器(upperdir)。然后,容器将更改写入容器层中文件的新副本。但是,OverlayFS在文件级别而不是块级别工作。这意味着所有OverlayFS copy_up操作都会复制整个文件,即使该文件非常大且只有一小部分正在被修改。这会对容器写入性能产生明显影响。但是,有两点值得注意:
–copy_up操作仅在第一次写入给定文件时发生。随后对同一文件的写入将对已经复制到容器的文件副本进行操作。
–OverlayFS仅适用于两层。这意味着性能应该比AUFS更好,后者在多层镜像中搜索文件时会出现明显的延迟。这一优点适用于 overlay和overlay2驱动程序。与初次读取相比,它的overlayfs2性能稍差overlayfs,因为它必须遍历更多的层,但是会缓存结果,因此这只是一个小小的代价。
- 删除文件和目录:
当在容器中删除一个文件时,在容器(upperdir)中会创建一个中断文件。lowerdir不会删除镜像层(lowerdir)中文件的版本(因为lowerdir是只读)。但是,中断文件会阻止容器使用它。
当在容器中删除一个一个目录时,在容器(upperdir)内生产一个不透明目录。这与中断文件的工作方式相同,也可以有效地防止该目录被访问,即使该目录仍然存在于镜像(lowerdir)中。
- 重命名目录:
rename(2)仅当源路径和目标路径都位于顶层时,才允许调用目录。否则,它将返回
EXDEV错误(“不允许跨设备链接”)。应用程序需要设计为处理EXDEV并退回到“复制和取消链接”策略。
5、性能
overlay2和overlay驱动程序比aufs和 devicemapper具有更高的性能。在某些情况下,overlay2
的性能可能会好于 btrfs:
- 页面缓存。OverlayFS支持页面缓存共享。访问同一文件的多个容器共享该文件的单个页面缓存条目。这使得overlay和overlay2驱动程序可以有效地利用内存,并且是高密度用例(例如PaaS)的不错选择。
- copy_up:与AUFS一样,每当容器第一次写入文件时,OverlayFS都会执行复制操作。这会增加写入操作的延迟,尤其是对于大文件。但是,一旦文件被复制,对该文件的所有后续写入都将在上层进行,而无需进行进一步的复制操作。OverlayFS copy_up操作比使用AUFS进行的操作要快,这是因为AUFS支持的层数比OverlayFS还要多,并且如果搜索许多AUFS层,可能会产生更大的延迟。overlay2也支持多层,但是可以减轻缓存对性能的影响。
- 索引节点限制:使用overlay存储驱动程序可能会导致过多的inode消耗,在Docker主机上存在大量镜像和容器的情况下尤其如此。增加文件系统可用的索引节点数量的唯一方法是对其进行重新格式化。为避免遇到此问题,强烈建议尽可能使用overlay2。
5.1 性能最佳实践
以下通用性能最佳实践也适用于OverlayFS。
- 使用快速存储:固态硬盘驱动器(SSD)能够提供更好的读写速度。
- 使用数据卷:数据卷可为繁重的写工作负载提供最佳和最可预测的性能。这是因为它们绕过了存储驱动程序,并且不会产生任何精简配置和写时复制所带来的潜在开销。
作者简介:
季向远,北京神舟航天软件技术有限公司。本文版权归原作者所有。微博:ik8s