深入剖析Kubernetes系列连载(六)容器

举报
skywalkerwty 发表于 2021/03/18 10:36:20 2021/03/18
【摘要】 深入剖析Kubernetes系列连载是学习《深入剖析Kubernetes》课程的笔记和总结,记录学习的过程,并且传递知识。

Kubernetes的学习往往让人摸不着头脑,很难理解其中的原理。

深入剖析Kubernetes系列连载是学习《深入剖析Kubernetes》课程的笔记和总结,记录学习的过程,并且传递知识。

之所以要强调 Linux 容器,是因为比如 Docker on Mac,以及Windows Docker(Hyper-V 实现),实际上是基于虚拟化技术实现的容器,就是未来云计算系统中的进程;容器镜像就是这个系统里的“.exe”安装包;k8s就是这个操作系统。

docker exec 是怎么做到进入容器里的呢?

这时,你可以通过查看宿主机的 proc 文件,看到这个 25686 进程的所有 Namespace 对应的文件:

可以看到,一个进程的每种 Linux Namespace,都在它对应的 /proc/[进程号]/ns 下有一个对应的虚拟文件,并且链接到一个真实的 Namespace 文件上

这也就意味着:一个进程,可以选择加入到某个进程已有的 Namespace 当中,从而达到“进入”这个进程所在容器的目的,这正是 docker exec 的实现原理

容器里进程新建的文件,怎么才能让宿主机获取到?

宿主机上的文件和目录,怎么才能让容器里的进程访问到?

$ docker run -v /test ...

$ docker run -v /home:/test ...

在第一种情况下,由于你并没有显示声明宿主机目录,那么 Docker 就会默认在宿主机上创建一个临时目录 /var/lib/docker/volumes/[VOLUME_ID]/_data,然后把它挂载到容器的 /test 目录上。而在第二种情况下,Docker 就直接把宿主机的 /home 目录挂载到容器的 /test 目录上

$ docker run -d -v /test helloworld
cf53b766fa6f

$ docker volume ls
DRIVER VOLUME NAME
local cb1c2f7221fa9b0971cc35f68aa1034824755ac44a034c0c0a1dd318838d3a6d

$ ls /var/lib/docker/volumes/cb1c2f7221fa/_data/

$ docker exec -it cf53b766fa6f /bin/sh
cd test/
touch text.txt

$ ls /var/lib/docker/volumes/cb1c2f7221fa/_data/
text.txt

宿主机上的文件系统,也自然包括了我们要使用的容器镜像。这个镜像的各个层,保存在/var/lib/docker/aufs/diff 目录下,在容器进程启动后,它们会被联合挂载在/var/lib/docker/aufs/mnt/ 目录中,这样容器所需的 rootfs 就准备好了

所以,我们只需要在 rootfs 准备好之后,在执行 chroot 之前,把 Volume 指定的宿主机目录(比如 /home 目录),挂载到指定的容器目录(比如 /test 目录)在宿主机上对应的目录(即 /var/lib/docker/aufs/mnt/[可读写层 ID]/test)上,这个 Volume 的挂载工作就完成了

更重要的是,由于执行这个挂载操作时,“容器进程”已经创建了,也就意味着此时Mount Namespace 已经开启了。所以,这个挂载事件只在这个容器里可见。你在宿主机上,是看不见容器内部的这个挂载点的。这就保证了容器的隔离性不会被 Volume 打破

注意:这里提到的 " 容器进程 ",是 Docker 创建的一个容器初始化进程(dockerinit),而不是应用进程 (ENTRYPOINT + CMD)。dockerinit 会负责完成根目录的准备、挂载设备和目录、配置 hostname 等一系列需要在容器内进行的初始化操作。最后,它通过 execv() 系统调用,让应用进程取代自己,成为容器里的 PID=1 的进程

而这里要使用到的挂载技术,就是 Linux 的绑定挂载(bind mount)机制。

这样,进程在容器里对这个 /test 目录进行的所有操作,都实际发生在宿主机的对应目录(比如,/home,或者 /var/lib/docker/volumes/[VOLUME_ID]/_data)里,而不会影响容器镜像的内容

Python 应用案例

这个容器进程“python app.py”,运行在由 Linux Namespace 和 Cgroups 构成的隔离环境里;而它运行所需要的各种文件,比如 python,app.py,以及整个操作系统文件,则由多个联合挂载在一起的 rootfs 层提供。

这些 rootfs 层的最下层,是来自 Docker 镜像的只读层。

在只读层之上,是 Docker 自己添加的 Init 层,用来存放被临时修改过的 /etc/hosts 等文件。

而 rootfs 的最上层是一个可读写层,它以 Copy-on-Write 的方式存放任何对只读层的修改,容器声明的 Volume 的挂载点,也出现在这一层。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。