05 | 白话容器基础(一):从进程说开去

本文仅作为学习记录,非商业用途,侵删,如需转载需作者同意。

一、进程

容器本身没有价值,有价值的是容器编排。

进程:一个程序运行起来后的计算机执行环境的总和。 一个程序被执行起来,它就从磁盘上的二进制文件,变成了计算机内存中的数据,寄存器里的值,堆栈中的指令,被打开的文件,以及各种设备的状态的信息集合。

容器的核心技术:通过约束和修改进程的动态表现,从而为其创造出一个边界。

Cgroups 技术是用来制造约束的主要手段;
Namespace 技术用来修改进程视图的主要手段

==

在容器中可以看到进程的PID 是从1开始的,这种技术就是Linux 里的Namespace 机制。

Namespace的使用方式:它只是Linux 创建进程的一个可选参数,Linux中的创建进程的可选参数是clone() ,比如:

int pid = clone(main_function, stack_size, SIGCHLD, NULL);

这个系统调用就会为我们创建一个新的进程,并且返回它的进程号pid。

而当我们用clone() 系统调用创建一个新的进程时,就可以在参数中指定CLONE_NEWPID参数,比如:

int pid = clone(main_function, stack_size, CLONE_NEWPID | SIGCHLD, NULL); 

这时新创建的进程将会看到一个全新的进程空间,在这个进程空间里,它的PID 是1 。
之所以说看到,因为这是个障眼法,在宿主机真实的进程空间里,这个进程的PID还是真实的数值,比如100。

我们还可以多次执行上面的clone() 调用,这样会创建出多个PID Namespace,而每个Namespace里的进程都会认为自己是当前容器里的 1 号进程。每个容器中的进程既看不到宿主机里真正的进程空间,也看不到其他Namespace里的具体情况。

除了刚才用到的PID Namespace,Linux操作系统还提供了Mount、UTS、IPC、Network 和User 这些Namespace,用来对各种不同的进程上下文进程障眼法操作。

比如:
Mount Namespace 用来让隔离的进程只看到当前 Namespace 里的挂载点信息;
Network Namespace 用于让被隔离进程看到当前Namespace里的网络设备和配置。

这就是Linux 容器最基本的实现原理了。

所以实际是在创建容器进程时,指定了这个进程所需要启动的一组Namespace参数。
这样容器就只能看到当前Namespace 所限定的资源,文件,设备,或者配置等信息。
对于宿主机和其他不相关的信息就看不到了。

容器只是一种特殊的进程

二、总结

在这里插入图片描述

上图中的左边是虚拟机:
Hypervisor 是虚拟机最主要的部分,通过硬件虚拟化功能,模拟出了运行一个操作系统所需的各种硬件,比如CPU,内存,I/O设备等,在虚拟的硬件上安装了一个新的操作系统 Guest OS。

这样用户的进程就可以运行在这个虚拟的机器中,能看到的只有Guest OS的文件和目录,以及这个机器里的虚拟设备,这样就能将不同的应用程序隔离。

上图中的右边,使用Docker Engine 替换了Hypervisor,这也是为什么很多人把Docker 项目称为轻量级虚拟化技术的原因。

这样的说话并不严谨

理解了Namespace的工作方式之后,在使用Docker 的时候,并没有一个真正的Docker 容器运行在宿主机里面,Docker 项目帮助用户启动的,还是原来的应用程序,只不过在创建这些进程的时候,Docker 为他们加上了各种各样的Namespace参数。

这时,这些进程就会觉得自己是各自 PID Namespace 里的第1号进程,只能看到各自Mount Namespace 里挂载的目录和文件,只能访问到各自Network Namespace 里的网络设备,就仿佛运行在一个个容器里面,与世隔绝。

这种解释说话,用障眼法形容就很贴切了。

三、评论

1、
问题:
为什么clone()时 还有线程呢 是写错了吗 还是有线程的启动啊

回复:
严格说,clone()是线程操作,但linux 的线程是用进程实现的

2、
问题:
老师有个问题一直困扰,容器是一个单进程,那比如我有一个镜像里面集成了jdk, netstat, ping等,虽然这个容器启动时里面是一个java进程,但是我可以进到容器里面执行各种命令,比如netstat等,那这些命令在容器的运行过程中是在运行的吗?

回复:
是在运行的。但它们不受docker的控制,就像野孩子。所以单进程意思不是只能运行一个进程,而是只有一个进程是可控的。

3、
问题:
1 用 namespace 框住app。
2 PID, UTS, network, user, mount, IPC, cgroup

虽然本质上理解,namespace 和 cgroup 是内核特性,容器本质上就是一个加了限定参数的进程,效果上看,图画的也没毛病。
这么看,是不是说容器的安全性,也就是隔离性,就是没办法达到虚拟机的级别呢?

回复:
没错,已经进门了哈

4、
问题:
进一步,1. 如果容器镜像os支持某硬件的驱动,但是宿主机os如果不支持该硬件驱动的话,是否也白搭
2. 是否可以理解为 镜像只是提供了一套镜像文件系统中的各种文件,而各种内核相关的模块或者特性支持,完全依赖于宿主机?

回复:
说的没毛病。

5、
问题:
第一个问题,我感觉docker engine 最好虚线标识,表示他只是一种启动时用,运行时并不需要,真实进程是直接run在host os上

回复:
听起来不错哦

6、
问题:
在容器内,除了pid=1的进程,其他进程是不受docker控制的。
这个控制具体指什么呢?其他进程和pid=1的进程关系又是什么呢?

回复:
是你通过exec进去之后启动的后台进程,不受控制。控制指的是它们的回收和生命周期管理。

7、
问题:
镜像的运行对host os有要求吗? 比如打包的镜像原来的kernel和运行时的kernel不一致,又或者镜像的发行版是centos,能运行在host为ubuntu的机器上吗

回复:
只要应用本身对内核没要求,那就完全没问题

8、
问题:
有一个问题 所以通过pid 可以判断自己是在docker里面还是在宿主机上。怎么通过命令行知道自己现在是在container里面还是在外面?

回复:
有很多种方法。比如查看/proc/1/cgroup下的文件结构

9、
问题:
如果运行的容器是一个os ubuntu,那么在这ubuntu里面运行的进程,和这个ubuntu是什么关系 和主机OS是什么关系?谢谢

回复:
使用ubuntu里的文件,使用宿主机上的内核。

10、
问题:
老师有个问题一直困扰,容器是一个单进程,那比如我有一个镜像里面集成了jdk, netstat, ping等,虽然这个容器启动时里面是一个java进程,但是我可以进到容器里面执行各种命令,比如netstat等,那这些命令在容器的运行过程中是在运行的吗?

作者回复
是在运行的。但它们不受docker的控制,就像野孩子。所以单进程意思不是只能运行一个进程,而是只有一个进程是可控的。

老师接着这个问题有几个问题

  1. 这些不被docker管理的进程在哪里能看得到?这些进程是否会很占用硬件资源?比如netstat
  2. 关于mac上运行的docker,比如容器进程依赖linux内核的版本4.2才能正确运行(镜像的内核版本是4.2的),那么既然docker只是用资源隔离的形式运行的。那我在mac起的这个容器时是否能正确运行?他会加载完整的linux操作系统吗?

回复: ps同样可以看到。win mac docker上跑其实都是个虚拟机

11、
问题:
虚拟化和容器的最大区别可以理解这个吗:1:虚拟化是同一台物理机不同的操作系统隔离应用进程2:但是容器是同一个操作系统的不同进程隔离。 简单来说就是:一个是操作系统级别隔离,一个是进程间隔离。

回复:
实际上是 硬件级别 的隔离 VM可是有虚拟硬件的。

12、
问题:
张老师我再追问一问题:在容器内,除了pid=1的进程,其他进程是不受docker控制的。那么如果在一个pod(容器,单pod单容器场景)中以CMD方式启动脚本(该脚本封装了多个启动程序,实测脚本自身的pid=1)。并且还配置了pod的prestop,poststart(是为了执行类似注册的脚本,一次执行而已,不是后台进程)。想请问这种方式下pod的prestop,poststart是如何控制的?实测是生效的,想知道其中的缘由?

回复:
它们当然都是pid 1进程的子进程

13、
问题:
可以理解为虚拟机虚拟的是硬件,docker虚拟的是操作系统吗?

回复:
docker啥都没虚拟。

14、
问题:
老师提到win mac docker上跑其实都是个虚拟机,可以运行不同平台的容器,如mac上运行ubuntu的容器。那么容器所需要的内核在哪里?是虚拟机的内核吗?还有这个虚拟机是不是这个正在运行的docker软件,也就是使用docker的虚拟机的内核?

回复:
容器用的就是这个虚拟机的内核。docker软件负责给你启动这个虚拟机。

15、
问题:
在docker出来之前是怎么用容器的,有想到把操作系统包进去吗?容器技术又是基于什么原因出现的呢?

回复:
那时候各家有各家的方法,也打包操作系统,叫rootfs,请关注后面镜像部分的讲解。

16、
作者回复:
咱们这里默认都说的是linux容器。资源分配是内核统一管理的,不管你的pid是几。

17、
问题:
docker是一个基于内核提供的资源隔离机制而开发实现的客户端管理工具,这样理解没错吧?

回复:
docker本身是有daemon的,但你说的没错,你完全可以开发一个操作runc的没daemon的docker

18、
问题:
在容器内,除了pid=1的进程,其他进程是不受docker控制的,如果这样的话,请问pod生命周期中poststart,prestop这些钩子还能用吗?

回复:
所以不要把hook写成后台进程

19、
问题:
如果容器中跑的是4.x的虚拟kernel环境,宿主机真实是3.x的内核,那么是否有些4.x的内核新功能如果要用到的话是不可行的?

回复:
用不了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值