K8s——容器文件系统

了解容器文件系统

如果您在容器内运行 df 命令,您会发现根 (/) 文件系统类型是 overlay,而不是通常的 ext4 或 xfs 文件系统类型。

例如:

你可能会问,什么是 overlay 类型?为什么容器使用这种类型的文件系统?

在开始深入探讨之前,我们先想一想如果没有容器文件系统会怎样?假设一个场景,一台主机需要运行 50 个不同的容器。这意味着我们至少需要创建 50 个不同的镜像。并且每个镜像都会将容器中的应用程序运行需要的所有二进制文件、库文件、配置文件和其他依赖文件打包到一个镜像文件中。

如果没有专门的容器文件系统,只是普通 ext4xfs 文件系统,那么每次启动容器时,都需要下载一个镜像文件存储到宿主机上。

假设一个镜像文件的大小是 500MB,那么对于 50 个容器我们需要下载 500MB * 50 = 25GB 的文件。

25GB 现在看来还能接受,但是如果你查看每个镜像文件,你会发现大多数镜像使用相同的 lib 文件,并且大多数 libs 文件是 read only 在容器运行时,所以我们会有很多文件重复!

一个极端的用例是这 50 个容器都使用相同的基础操作系统映像,并假设操作系统基础映像占用 450MB 大小,那么在上面的示例中,我们有90%数据重复!!!



此时,聪明如你,大概已经有了解决方案,没错,我们只需要在宿主机上下载一份 ubuntu 18.04,让所有其他容器共享公共部分即可!

什么是 UnionFS

为了有效减少磁盘上的冗余镜像数据,减少运行容器的冗余镜像数据在网络上的传输,需要选择容器专用的文件系统,这种文件系统称为For UnionFS

UnionFS 的主要作用是将多个目录(在不同的分区)一起挂载到一个目录下。这种多目录挂载的方式可以完美解决我刚才提到的容器镜像问题。

例如,我们可以将基础镜像 ubuntu 18.04 的所有文件放入一个名为 ubuntu18.04/ 的目录,并将容器特定文件 app1_bin 放入另一个名为 app_1/ 的目录。

然后我们就可以将这两个目录(ubuntu18.04/app_1)挂载到container1,把 ubuntu18.04/app_2 挂载到 container2



在这种情况下,我们只需要保留一份ubuntu 18.04基础镜像。

什么是 OverlayFS

UnionFS 的类似实现有很多,包括最早在Docker中使用的AUFS,以及我们目前使用的OverlayFS。我们前面看到的overlay类型指的是OverlayFS

在 Linux 内核 3.18 版本中,OverlayFS代码被正式合并到 Linux 内核的主分支中。之后逐渐成为各种主流Linux发行版默认使用的容器文件系统。

让我们尝试一些示例命令来更好地理解 OverlayFS:

# Go into root home
$ pwd
/root# Display current FS
$ ls
$ df -h
Filesystem      Size  Used Avail Use% Mounted on
devtmpfs        2.0G     0  2.0G   0% /dev
tmpfs           2.0G     0  2.0G   0% /dev/shm
tmpfs           2.0G  500K  2.0G   1% /run
tmpfs           2.0G     0  2.0G   0% /sys/fs/cgroup
/dev/xvda1      8.0G  6.8G  1.3G  85% /
tmpfs           395M     0  395M   0% /run/user/1000# Create overlay FS and mount
$ mkdir upper lower merged work
$ echo "I'm from lower" > lower/in_lower.txt
$ echo "I'm from upper" > upper/in_upper.txt
$ echo "I'm from lower" > lower/in_both.txt
$ echo "I'm from upper" > upper/in_both.txt
$ mount -t overlay overlay -o lowerdir=./lower,upperdir=./upper,workdir=./work  ./merged# Check FS again
$ df -h
Filesystem      Size  Used Avail Use% Mounted on
devtmpfs        2.0G     0  2.0G   0% /dev
tmpfs           2.0G     0  2.0G   0% /dev/shm
tmpfs           2.0G  500K  2.0G   1% /run
tmpfs           2.0G     0  2.0G   0% /sys/fs/cgroup
/dev/xvda1      8.0G  6.8G  1.3G  85% /
tmpfs           395M     0  395M   0% /run/user/1000
overlay         8.0G  6.8G  1.3G  85% /root/merged

截屏:

OverlayFS: lower, upper, merged and work

从上面的例子我们可以看出,OverlayFSmount 命令有四种类型的目录:

  • lower:下层目录,只读。
  • upper:负责OverlayFS中的创建、修改、更新和删除操作,这一层是可写的。
  • merged:挂载点目录,也是用户看到的目录,是用户实际进行文件操作的地方。
  • work:只是一个存放临时文件的目录。如果OverlayFS中有文件修改,中途会把文件暂时存放在这里。

从上面的例子中我们可以看出,OverlayFS将挂载两个级别的目录,下层和上层。这两级目录中的文档将映射到装入点。

从挂载点的角度来看,上层的文档会覆盖下层的文档。例如,文档“in_both.txt”在下层和上层都可用,但在挂载点 merge/ 中只可以看到上层的in_both.txt文档。如下所示:

[root@devops101 ~]# cd merged/
[root@devops101 merged]# ls
in_both.txt  in_lower.txt  in_upper.txt
[root@devops101 merged]# cat in_both.txt
I'm from upper

OverlayFS File Operations

如果我们在 merged/ 目录中做一些文档操作,会发生什么?

  • 创建一个新文档,new_file.txt ,这个新文档将在上层目录中创建
  • 如果我们删除现有文档:in_upper.txt .此文档将从上层目录中删除
[root@devops101 merged]# rm in_upper.txt
rm: remove regular file ‘in_upper.txt’? yes
[root@devops101 merged]# ll
total 8
-rw-r--r-- 1 root root 15 Sep 15 00:56 in_both.txt
-rw-r--r-- 1 root root 15 Sep 15 00:56 in_lower.txt
[root@devops101 merged]# ll ../upper/
total 4
-rw-r--r-- 1 root root 15 Sep 15 00:56 in_both.txt
  • 如果我们删除in_lower.txt,该文档将不会从下层目录中删除,而是会在下层目录中创建一个特殊的文档来告诉 OverlayFS in_lower.txt不应该显示在 merged/ 中。
[root@devops101 merged]# ls
in_both.txt  in_lower.txt  in_upper.txt
[root@devops101 merged]# rm in_lower.txt
rm: remove regular file ‘in_lower.txt’? yes
[root@devops101 merged]# ls
in_both.txt  in_upper.txt
[root@devops101 merged]# ll ../upper/
total 8
-rw-r--r-- 1 root root   15 Sep 15 00:56 in_both.txt
c--------- 1 root root 0, 0 Sep 15 01:16 in_lower.txt
-rw-r--r-- 1 root root   15 Sep 15 01:16 in_upper.txt
[root@devops101 merged]# ll ../lower/
total 8
-rw-r--r-- 1 root root 15 Sep 15 00:56 in_both.txt
-rw-r--r-- 1 root root 15 Sep 15 00:56 in_lower.txt
  • 如果我们修改 in_lower.txt ,那么将在上层文档夹中创建一个名为 in_lower.txt 的新文档,其中包含更新的内容,下部目录中的原始in_lower.txt文档不会更改。

如何挂载 Docker 镜像?

现在我们知道了 OverlayFS 是如何工作的,我们可以很容易地知道 Docker 容器如何使用它。下面是一个示例:

可以看到容器镜像文档可以划分为多个层,每层可以对应 OverlayFS 中较低目录中的一个目录。LowerDIR 支持多个目录,这意味着它可以支持多层镜像文档。 容器启动后,对镜像文档的更改将保存在 upperdir 中。

总结

在本文中,主要重点是了解容器文档系统。为什幺容器有自己的文档系统?很重要的一点是减少同一节点上同一镜像文档的数据冗余,这样可以节省磁盘空间,减少镜像文档下载所占用的网络资源。

发布于 2023-02-08 15:05・IP 属地上海