docker存储驱动
一句话,docker 存储驱动用于管理docker 镜像和容器。
1. 镜像和层
在了解docker存储驱动之前,先了解下docker如何构建镜像,以及容器如何使用这些镜像。
下图为docker镜像的图形表示。
镜像为一系列只读层,当启动一个容器时,docker将读取只读镜像,并在顶部增加一个可读写层,如果正在运行的容器修改了现有文件,则该文件将从基础只读层复制到应用更改的最高读写层,读写层的版本会隐藏基础文件,但不会破坏它,它仍然处于基础层中。删除容器后,这些更改将丢失。
ps:读写层的读写速度都低于本机文件系统性能。因此,建议使用volume来持久化数据和提高性能(简单来说,volumes就是一些目录/文件,在unionfs之外,存储在宿主机的文件系统中。volumes就是被设计为对I/O有效,且不会增加容器可写层大小,且可以在容器中共享)。
Docker使用存储驱动程序来管理镜像层和可写容器层的内容。
每个存储驱动程序处理实现的方式不同,但是所有驱动程序都使用可分层镜像和即写即拷(CoW)策略。
1.1 分层镜像
当使用docker pull拉取一个镜像时,每一层都是单独拉取的,并存储在本地/var/lib/docker/<storage-driver>中。
注意,/var/lib/docker/<storage-driver>中的目录名与层id不对应(自Docker 1.10以来一直如此)。
ps:可以通过docker ps -s 查看磁盘上的容器大小。其中,size: 每个容器读写层的数据量。virtual size: 容器使用的所有只读镜像层 + 读写层的数据量。
注意,多个容器可能共享部分或全部只读镜像数据。因此,不能只计算虚拟大小的总数。这可能过高估计了磁盘的总使用量。
1.2 COW
如果一个文件或者目录处于只读层,而容器需要对其进行访问时,那么只使用现有文件。当容器需要修改文件时,那么文件被复制到读写层并修改,这将最小化IO和读写层的大小。
2. docker存储驱动分类
docker存储驱动分为两类,一类是overlays(覆盖),一类是Snapsshotting(快照)。
它们都使用可拔插的架构。
可以通过docker info查看当前使用的存储器驱动。
区别之处:
overlays文件系统,它们有多个目录,每层镜像都有不同的文件。
Snapsshottings包括devicemapper,btrfs和ZFS,它们在block级别上处理文件差异。
3. Docker所支持的存储驱动程序
○ overlay2是当前支持的所有Linux发行版的首选存储驱动程序,不需要额外配置。
○ 当运行在内核3.13上的Ubuntu 14.04上时,aufs是Docker 18.06和更老版本的首选存储驱动程序,因为内核3.13不支持overlay2。
○ 支持devicemapper,但是在生产环境中需要直接lvm,因为环回lvm虽然是零配置,但性能非常差。devicemapper是CentOS和RHEL推荐的存储驱动程序,因为它们的内核版本不支持overlay2。但是,CentOS和RHEL的当前版本现在支持overlay2,它现在是推荐的驱动程序。
○ 如果btrfs和zfs存储驱动程序是后备文件系统(安装Docker的主机的文件系统),则使用它们。这些文件系统允许高级选项,比如创建“快照”,但是需要更多的维护和设置。这些都依赖于备份文件系统的正确配置。
○ vfs存储驱动程序用于测试目的,并用于不能使用即写即拷文件系统的情况。这个存储驱动程序的性能很差,一般不推荐用于生产。
所有这些存储驱动程序,就是Union文件系统 的变体。
4. 存储驱动支持的后备文件系统
对于Docker,后备文件系统就是/var/lib/docker/所在的文件系统。有些存储驱动程序只与特定的后备文件系统(宿主机的文件系统)一起工作。
5. 各种存储驱动的性能特征
○ overlay2、aufs和overlay都在文件层而不是块层操作。这样可以更有效地使用内存,但是容器的可写层可能会在写量大的工作负载中增长得相当大。
○ 块级存储驱动程序(如devicemapper、btrfs和zfs)对于写量大的工作负载性能更好(尽管不如Docker卷)。
○ 对于许多小的写操作或具有许多层的容器或深度文件系统,overlay的性能可能比overlay2好,但是消耗更多的inode,这可能导致inode耗尽。
○ btrfs和zfs需要大量内存。
○ zfs对于高密度的工作负载(如PaaS)是一个很好的选择。
关于性能、适用性和最佳实践的更多信息可以在每个存储驱动程序的文档中找到。