learn-tech/专栏/周志明的架构课/46_容器的崛起(上):文件、访问、资源的隔离.md
2024-10-16 06:37:41 +08:00

8.4 KiB
Raw Blame History

                        因收到Google相关通知网站将会择期关闭。相关通知内容
                        
                        
                        46 _ 容器的崛起(上):文件、访问、资源的隔离
                        你好,我是周志明。接下来的两节课,我会以容器化技术的发展为线索,带你从隔离与封装两个角度,去学习和了解容器技术。

今天我们就先来学习下Linux系统中隔离技术的发展历程以此为下节课理解“以容器封装应用”的思想打好前置基础。

隔离文件chroot

首先要知道,人们使用容器的最初目的,并不是为了部署软件,而是为了隔离计算机中的各类资源,以便降低软件开发、测试阶段可能产生的误操作风险,或者是专门充当蜜罐,吸引黑客的攻击,以便监视黑客的行为。

容器的起点呢可以追溯到1979年Version 7 UNIX系统中提供的chroot命令这个命令是英文单词“Change Root”的缩写它所具备的功能是当某个进程经过chroot操作之后它的根目录就会被锁定在命令参数所指定的位置以后它或者它的子进程就不能再访问和操作该目录之外的其他文件。

1991年世界上第一个监控黑客行动的蜜罐程序就是使用chroot来实现的那个参数指定的根目录当时被作者被戏称为“Chroot监狱”Chroot Jail而黑客突破chroot限制的方法就叫做Jailbreak。后来FreeBSD 4.0系统重新实现了chroot命令把它作为系统中进程沙箱隔离的基础并将其命名为FreeBSD jail。

再后来苹果公司又以FreeBSD为基础研发出了举世闻名的iOS操作系统此时黑客们就把绕过iOS沙箱机制以root权限任意安装程序的方法称为“越狱”Jailbreak当然这些故事都是题外话了。

到了2000年Linux Kernel 2.3.41版内核引入了pivot_root技术来实现文件隔离pivot_root直接切换了根文件系统rootfs有效地避免了chroot命令可能出现的安全性漏洞。咱们课程后面要提到的容器技术比如LXC、Docker等等也都是优先使用pivot_root来实现根文件系统切换的。

不过时至今日chroot命令依然活跃在Unix系统以及几乎所有主流的Linux发行版中同时也以命令行工具chroot(8)或者系统调用chroot(2) 的形式存在着但无论是chroot命令还是pivot_root它们都不能提供完美的隔离性。

其实原本按照Unix的设计哲学一切资源都可以视为文件In UNIXEverything is a File一切处理都可以视为对文件的操作在理论上应该是隔离了文件系统就可以安枕无忧才对。

可是哲学归哲学现实归现实从硬件层面暴露的低层次资源比如磁盘、网络、内存、处理器再到经操作系统层面封装的高层次资源比如UNIX分时UNIX Time-SharingUTS、进程IDProcess IDPID、用户IDUser IDUID、进程间通信Inter-Process CommunicationIPC等等都存在着大量以非文件形式暴露的操作入口。

所以我才会说以chroot为代表的文件隔离仅仅是容器崛起之路的起点而已。

隔离访问namespaces

那么到了2002年Linux Kernel 2.4.19版内核引入了一种全新的隔离机制Linux名称空间Linux Namespaces

名称空间的概念在很多现代的高级程序语言中都存在它主要的作用是避免不同开发者提供的API相互冲突相信作为一名开发人员的你肯定不陌生。

Linux的名称空间是一种由内核直接提供的全局资源封装它是内核针对进程设计的访问隔离机制。进程在一个独立的Linux名称空间中朝系统看去会觉得自己仿佛就是这方天地的主人拥有这台Linux主机上的一切资源不仅文件系统是独立的还有着独立的PID编号比如拥有自己的0号进程即系统初始化的进程、UID/GID编号比如拥有自己独立的root用户、网络比如完全独立的IP地址、网络栈、防火墙等设置等等此时进程的心情简直不能再好了。

事实上Linux的名称空间是受“贝尔实验室九号项目”一个分布式操作系统“九号”项目并非代号操作系统的名字就叫“Plan 9 from Bell Labs”充满了赛博朋克风格的启发而设计的最初的目的依然只是为了隔离文件系统而不是为了什么容器化的实现。这点我们从2002年发布时Linux只提供了Mount名称空间并且其构造参数为“CLONE_NEWNS”即Clone New Namespace的缩写而非“CLONE_NEWMOUNT”就能看出一些端倪。

到了后来要求系统隔离其他访问操作的呼声就愈发强烈从2006年起内核陆续添加了UTS、IPC等名称空间隔离直到目前最新的Linux Kernel 5.6版内核为止Linux名称空间支持了以下八种资源的隔离内核的官网Kernel.org上仍然只列出了前六种从Linux的Man命令能查到全部八种

阅读链接补充:- Hostname- Domain names

如今对文件、进程、用户、网络等各类信息的访问都被囊括在Linux的名称空间中即使一些今天仍有没被隔离的访问比如syslog就还没被隔离容器内可以看到容器外其他进程产生的内核syslog在以后也可以跟随内核版本的更新纳入到这套框架之内。

现在,距离完美的隔离性就只差最后一步了:资源的隔离。

隔离资源cgroups

如果要让一台物理计算机中的各个进程看起来像独享整台虚拟计算机的话,不仅要隔离各自进程的访问操作,还必须能独立控制分配给各个进程的资源使用配额。不然的话,一个进程发生了内存溢出或者占满了处理器,其他进程就莫名其妙地被牵连挂起,这样肯定算不上是完美的隔离。

而Linux系统解决以上问题的方案就是控制群组Control Groups目前常用的简写为cgroups它与名称空间一样都是直接由内核提供的功能用于隔离或者说分配并限制某个进程组能够使用的资源配额。这里的资源配额包括了处理器时间、内存大小、磁盘I/O速度等等具体你可以参考下这里给出的表格

cgroups项目最早是由Google的工程师主要是Paul Menage和Rohit Seth在2006年发起的当时取的名字就叫做“进程容器”Process Containers不过“容器”Container这个名词的定义在那时候还没有今天那么清晰不同场景中常有不同的指向。

所以为了避免混乱到2007年这个项目才被重新命名为cgroups在2008年合并到了2.6.24版的内核后正式对外发布这一阶段的cgroups就被称为“第一代cgroups”。

后来在2016年3月发布的Linux Kernel 4.5中搭载了由Facebook工程师主要是Tejun Heo重新编写的“第二代cgroups”其关键改进是支持Unified Hierarchy这个功能可以让管理员更加清晰、精确地控制资源的层级关系。目前这两个版本的cgroups在Linux内核代码中是并存的不过在下节课我会给你介绍的封装应用Docker就暂时仅支持第一代的cgroups。

小结

这节课我给你介绍了容器技术和思想的起源chroot命令这是计算机操作系统中最早的成规模的隔离技术。

此外你现在也了解到了namespaces和cgroups对资源访问与资源配额的隔离它们不仅是容器化技术的基础在现代Linux操作系统中也已经成为了无可或缺的基石。理解了这些基础性的知识是学习和掌握下节课中讲解的容器应用即不同封装对象、封装思想的必要前提。

一课一思

请你思考一下Docker的起源依赖于Linux内核提供的隔离能力那Docker就是Linux专属的吗Windows系统中是否有文件、访问、资源的隔离手段是否存在Windows版本的容器运行时呢

提示你可以搜索关于Window Server Contianer的信息与LXCLinux Container对比一下。

欢迎在留言区分享你的思考和见解。如果你觉得有收获,也欢迎把今天的内容分享给更多的朋友。感谢你的阅读,我们下一讲再见。