暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

容器技术原理:文件系统

一叶扁舟 2021-10-22
1593

image.png

Namespace 和 Cgroups 做了容器的资源限制与隔离,把进程“装”在了一个与世隔绝的房间里。这个房间四周虽然有了墙,但是如果容器进程低头一看地面,又是怎样一副景象呢?

一、Mount Namespace

Mount Namespace负责让被隔离的进程只能看到当前Namespace里挂载目录的文件。并且可以重新挂载指定目录,让挂载的宿主机目录在容器中是空的目录。避免在容器中访问到宿主机的文件。

创建容器时,直接为进程启用Mount Namespace,会发现容器中看到的文件系统也跟宿主机完全一样。原因是创建容器时,会直接继承宿主机的各个挂载点。

我们可以修改启用Mount Namespace时的参数做到重新挂载指定的目录,如果我们重新挂载根目录“/”,那么在容器中看到的整个根目录都是空的。

那,我不想挂载根目录,而是想挂载别的目录怎么办?

二、chroot

chroot负责把任意目录变为根目录,这样容器就能挂载宿主机上任意目录当做根目录了

在 Linux 操作系统里,有一个名为 chroot 的命令,它的作用就是帮你“change root file system”,即改变进程的根目录到你指定的位置。这样容器随意挂载任意目录,chroot 负责将该目录转化为根目录,这样容器的根目录就挂在了指定的宿主机的指定目录了。

但是,真实地操作系统根目录是有很多文件的,怎么实现呢?

三、rootfs

rootfs负责将系统文件挂载到容器的根目录

rootfs 只是一个操作系统所包含的文件、配置和目录,并不包括操作系统内核。同一台机器上的所有容器,都共享宿主机操作系统的内核。

docker镜像是分层的rootfs

为了能够让容器的这个根目录看起来更“真实”,我们一般会在这个容器的根目录下挂载一个完整操作系统的文件系统,比如 Ubuntu16.04 的 ISO。这样,在容器启动之后,我们在容器里通过执行 “ls /” 查看根目录下的内容,就是 Ubuntu 16.04 的所有目录和文件。

而这个挂载在容器根目录上、用来为容器进程提供隔离后执行环境的文件系统,就是所谓的“容器镜像”。它还有一个更为专业的名字,叫作:rootfs(根文件系统)。

rootfs 只是一个操作系统所包含的文件、配置和目录,并不包括操作系统内核。在 Linux 操作系统中,这两部分是分开存放的,操作系统只有在开机启动时才会加载指定版本的内核镜像。

所以说,rootfs 只包括了操作系统的“躯壳”,并没有包括操作系统的“灵魂”。

同一台机器上的所有容器,都共享宿主机操作系统的内核。这就意味着,如果你的应用程序需要配置内核参数、加载额外的内核模块,以及跟内核进行直接的交互,你就需要注意了:这些操作和依赖的对象,都是宿主机操作系统的内核,它对于该机器上的所有容器来说是一个“全局变量”,牵一发而动全身。

但是,各个容器间文件系统可能会有很多重合,如何有效利用宿主机存储空间呢?

四、UnionFS

Union File System 也叫 UnionFS,最主要的功能是将多个不同位置的目录联合挂载(union mount)到同一个目录下。(相同的文件进行复用)

比如,我现在有两个目录 A 和 B,它们分别有两个文件:

$ tree . ├── A │ ├── a │ └── x └── B ├── b └── x

然后,我使用联合挂载的方式,将这两个目录挂载到一个公共的目录 C 上之后:

$ tree ./C ./C ├── a ├── b └── x
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论