容器化技术并不是由Docker引入,而是有其发展历程。容器有效地将由单个操作系统管理的资源划分到孤立的组中,以更好地在孤立的组之间平衡有冲突的资惊使用需求。容器可以在核心CPU运行指令,而不需要任何专门的解释机制。容器避免了准虚拟化(para-virtualization)和系统调用替换中的复杂性。
容器技术演进
容器技术并不是一蹴而就,而是有其演进过程。1982年合入到Unix BSD分支的chroot可以被看做是最早的容器化技术。chroot通过限制进程的文件访问权限,实现了进程在文件系统层面的隔离。随后,FreeBSD 4.0版本增加的jail功能、Linux内核新增Linux VServer、SUN公司新增的操作系统虚拟化功能Container、SWsoft发布的基于Linux平台的操作系统级服务器虚拟化解决方案——Open VZ、Google推出的Process Container,在2.6.24版本合并到Linux内核中,同时为了避免和Linux内核上下文中的"Container"一词混淆,改名为Control Groups,简称为Cgroups,都使容器技术得到了不同程度的发展。在2008年,随着Cgroups合并到Linux内核,社区开发者将Cgroups和Linux Namespace的能力组合在一起,形成了完整的容器技术LXC。LXC在被集成到Linux内核后,逐渐成为Linux系统上轻量级容器技术的事实标准。从技术层面来看,LXC已经趟过了绝大部分的"坑",完成了容器技术实用化的大半历程。
到2013年,Docker的发布,解决了应用组件的"一次封装,到处运行"问题。Docker的出现,首次为应用的开发、运行和部署提供了"一站式"的实用解决方案。
在2014年10月,Google开源了Kubernetes。Kubernetes可以看做是云原生时代的操作系统,是让复杂软件在云计算下获得韧性、弹性、可观测性的最佳路径,也是为云厂商推动云计算时代加速到来的关键引擎之一。Kubernetes已成为容器编排的事实标准。
chroot系统调用
1979年,贝尔实验室在Unix V7的开发过程中,由于当时计算资源匮乏(如一块64K的内存条就要卖419美元),想要通过快速销毁和重建基础设施来解决测试环境污染问题几乎不可能。为隔离出可供软件进行构建和测试的环境,chroot(change root)系统调用被正式引入。chroot为每个进程提供一个独立的磁盘空间,将一个进程及其子进程的根目录改变到文件系统中的新位置,让这些进程只能访问到该目录。chroot实现了将一个进程的文件系统隔离起来,为进程构建一个独立的虚拟文件系统视图。这个被隔离出来的新环境被叫做chroot jail。chroot在1982年被新增到了Unix BSD的分支中。
chroot的出现标志着进程隔离的开始,隔离每个进程的文件访问权限。直到今天,主流的Unix、Linux等操作系统仍然支持和带有chroot系统调用。chroot被认为是最早的容器化技术,实现了进程在文件系统层面的隔离。
早期容器实现技术
在2000年,一家共享主机托管商在FreeBSD 4.0版本增加了jail功能。FreeBSD Jail就是将系统划分为几个独立的较小的系统,称之为Jail,并且这些小的系统均有独立的配置和IP地址。FreeBSD Jail中,程序实现了文件系统、进程、网络等隔离。可以使用jail(8)这个命令来调用这个服务。FreeBSD Jail隔离环境,真正意义上实现进程的沙箱化。
在2001年,Linux内核新增Linux VServer(虚拟服务器,系统级别的虚拟化功能),为Linux系统提供虚拟化功能。Linux VServer采取的也是一种jail机制,它能够对计算机系统上的文件系统、网络地址和内存进行分区。每个分区被称为一个安全上下文。最后的一个稳定的补丁在2006年发布。Linux VServer实现了Linux操作系统上的隔离环境。
在2004年,SUN公司在类Unix操作系统Solaris的10 beta版本上,新增一个用于 X86 和 SPARC 处理器的操作系统虚拟化功能Container。Solaris Container由系统资源控制和Zone提供的边界分离实现进程隔离。Solaris Zone能够帮助应用在隔离的环境中运行,并实现有效的资源管理。每一个Zone拥有自己的文件系统,进程空间,防火墙,网络配置等等。Zone为应用程序创建了虚拟的一层,可以将一个Zone称之为一个沙箱,Solaris Container的发布标志着Solaris操作系统上的虚拟化功能的引入,并在之后的Solaris 10正式版中进一步完善。
在2005年,SWsoft发布了Open VZ(Open Virtuzzo)。OpenVZ是基于Linux平台的操作系统级服务器虚拟化解决方案。OpenVZ可以在单个物理服务器上创建多个隔离的虚拟专用服务器(VPS)并以最大效率共享硬件和管理资源。每个VPS的运行和独立服务器完全一致,因其自身的用户、应用程序都可以独立重启。OpenVZ中的VPS都有一套隔离的文件系统、用户及用户组、网络、内存、处理器、文件、应用服务、系统库文件和配置文件等。Open VZ也有一些自身限制。因为容器共享相同的体系结构和内核版本,当客户需要不同于主机的内核版本情况下,这种缺点就会显现出来。Open VZ并未作为正式 Linux 内核的一部分发布。
在2006年,Google推出Process Container。Process Container是"容器"技术的雏形,用来对一组进程进行限制、记录、隔离资源(CPU、内存、磁盘 I/O、网络等)。2008年在2.6.24版本合并到Linux内核中,同时为了避免和Linux 内核上下文中的"Container"一词混淆,改名为Control Groups,简称为Cgroups。作为在容器中控制容器的资源配额,Cgroups是极其重要的一个控制功能,标志着Linux阵营中"容器"的概念开始被重新审视和实现。
LXC集成到Linux内核
在LXC(Linux Container,Linux容器)发布之前,容器相关技术经过多年的演化已经十分成熟和稳定,但是由于种种原因,这些技术并没有被很好地集成到主流的Linux内核中,使用起来并不方便。如果用户要使用Open VZ技术,需要先给操作系统打上特定的内核补丁方可使用,而且不同版本并不一致。
在2008年,随着Cgroups合并到Linux内核,社区开发者将Cgroups和Linux Namespace的能力组合在一起,形成了完整的容器技术LXC。LXC在被集成到Linux内核后,逐渐成为Linux系统上轻量级容器技术的事实标准。从技术层面来看,LXC已经趟过了绝大部分的"坑",完成了容器技术实用化的大半历程 。
Docker
在2013年,在LXC的基础上,结合Union File System(联合文件系统)等技术,Docker发布。Docker的构想是要实现"Build, Ship and Run Any App, Anywhere",即通过对应用的封装(Packaging)、分发(Distribution)、部署(Deployment)、运行(Runtime)生命周期进行管理,达到应用组件级别的"一次封装,到处运行"。Docker首次为应用的开发、运行和部署提供了"一站式"的实用解决方案。
Docker进一步优化了容器的使用体验,降低其使用门槛。首先,Docker提供了各种容器管理工具(如分发、版本、移植等),让用户无须关注底层的操作,更加简单明了地管理和使用容器;其次,Docker通过引入分层文件系统构建和高效的镜像机制,降低了迁移难度,极大地改善了用户体验。Docker的一大创新就是引入容器镜像。容器镜像是Docker生命周期中的"构建"部分。也可把容器镜像当做容器的"源代码"。通过容器镜像,就可在任何地方得到完全一致的内容。这就是容器技术"强一致性"的重要体现。
早期的Docker实现是直接基于LXC的。自0.9版本开始,Docker开发了libcontainer项目来替换LXC。libcontainer是一个容器管理库,它提供了直接与Linux内核交互的API来创建和管理容器,实现了容器的核心功能。
2015年6月,OCI组织成立,旨在制定并维护容器镜像格式和容器运行时的正式规范,以便在不同的操作系统和平台之间移植。Docker公司为其捐赠了容器镜像格式和运行时的草案及相应的实现代码。原来属于Docker的libcontainer项目被捐赠给OCI,成为独立的容器运行时项目runc。runc是轻量级的通用运行时容器,它遵守OCI规范,是实现OCI接口的最低级别的组件,它与内核交互创建并运行容器。
Kubernetes
如果说以Docker为代表的容器引擎,是把软件的发布流程从分发二进制安装包,转变为了直接分发虚拟化后的整个运行环境,让应用得以实现跨机器的绿色部署。那么以Kubernetes为代表的容器编排框架,就是把大型软件系统运行所依赖的集群环境也进行了虚拟化,让集群得以实现跨数据中心的绿色部署,并能够根据实际情况自动扩缩。
在2014年10月,Google开源了Kubernetes,并在2015年捐赠给CNCF。Kubernetes可以看做是云原生时代的操作系统,是让复杂软件在云计算下获得韧性、弹性、可观测性的最佳路径,也是为云厂商推动云计算时代加速到来的关键引擎之一。Kubernetes已成为容器编排的事实标准。
容器化关键技术
在容器化技术中涉及核心技术概念是:Cgroups、Namespace和rootfs(根文件系统)。其中Cgroups(control groups)能够限制、核算和隔离一组进程所使用的系统资源(如CPU、内存、磁盘I/O、网络等)。Namespace可以对内核资源进行分区,实现进程间资源隔离。rootfs则是系统的主要文件系统,包含所有的文件和目录。rootfs是一个虚拟的文件系统,它由内核挂载并提供给用户空间。
Cgroups
Cgroups(control groups)是Linux内核提供的一种特性,它能够限制、核算和隔离一组进程所使用的系统资源(如CPU、内存、磁盘I/O、网络等)。实现Cgroups的主要目的是为不同用户层面的资源管理提供一个统一化的接口。从单个任务的资源控制到操作系统层面的虚拟化,Cgroups提供了四大功能:
(1) 资源限制:Cgroups可以对任务使用的资源总额进行限制。比如设定任务运行时使用的内存上限,一旦超出就发出OOM。
(2) 优先级分配:通过分配的CPU时间片数量和磁盘IO带宽,实际上就等同于控制了任务运行的优先级。
(3) 资源统计:Cgoups可以统计系统的资源使用量,如CPU使用时长、内存用量等。
(4) 任务控制:Cgroups 可以对任务执行挂起、恢复等操作。
Namespace
Namespace是Linux内核提供的一种特性,它可以对内核资源进行分区,实现进程间资源隔离的一种技术。这种隔离机制和chroot很类似,只是chroot是实现了文件系统的隔离,而Namespace则在此基础上,提供了对UTS、IPC、Mount、PID、Network、User等的隔离机制。加上Cgroups,构成如下八种元素:
其中PID Namespace用来隔离进程,UTS Namespace用来隔离主机名和域名,MNT Namespace用来隔离文件系统,IPC Namespace用来隔离进程间通信,NET Namespace用来隔离网络访问,USR Namespace用来隔离用户和用户组,chroot用来控制文件系统根目录的位置,Cgroups则用来限制和保护系统资源。
rootfs(根文件系统)
容器在启动时其内部进程可见的文件系统就是rootfs。rootfs只是一个操作系统所包含的文件、配置和目录,并不包括操作系统内核。rootfs让容器的一致性成为可能。由于rootfs里打包的不只是应用,而是整个操作系统的文件和目录,也就意味着,应用以及它运行所需要的所有依赖,都被封装在了一起。
上图中,bootfs是指Linux系统启动时使用的文件系统,通常包含操作系统内核、启动加载程序和其他引导文件。Linux刚启动时会加载bootfs文件系统。这一层包含boot加载器和内核。当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs。
rootfs则是指Linux系统的根文件系统,是系统的主要文件系统,包含所有的文件和目录(对于上图,则是Base Image这层),如Linux系统中的/dev,/proc,/bin,/etc等标准目录和文件。rootfs是一个虚拟的文件系统,它由内核挂载并提供给用户空间。在Linux系统启动时,内核会将 rootfs挂载为基础文件系统,并将其作为所有其他文件系统的基础。
参考
《Docker技术入门与实战》 杨保华 戴王剑 曹亚仑 著
https://blog.daocloud.io/4001.html 容器与虚拟机
https://www.cnblogs.com/charlierorop/9259675.html chroot的用法
https://developer.aliyun.com/article/775778 容器技术之发展简史
https://zhuanlan.zhihu.com/p/358548091 容器技术发展简史
https://zhuanlan.zhihu.com/p/567119260 浅谈容器技术发展史
https://www.infoq.cn/article/SS6SItkLGoLExQP4uMr5 一文读懂容器发展史
https://cloud.tencent.com/developer/article/1435910 容器技术
https://blog.csdn.net/qq_56444564/article/details/134702884 容器技术发展史,编排与容器的技术演进之路
https://www.redhat.com/zh/topics/containers/whats-a-linux-container 什么是 Linux 容器?
https://zhuanlan.zhihu.com/p/662691635 容器技术
https://zhuanlan.zhihu.com/p/345100482 容器技术发展趋势
https://www.sohu.com/a/745364810_121841668 阿里云:2023智算时代的容器技术演进与实践报告
https://skyao.io/learning-cloudnative/docs/introduction/history.html 云计算的历史
https://zhuanlan.zhihu.com/p/438352784 Docker、Containerd、RunC分别是什么
https://www.infoq.cn/article/2017%2F02%2FDocker-Containerd-RunC Docker、Containerd、RunC
https://www.docker.com/blog/runc/ Introducing runC
https://blog.csdn.net/Dream1248120122/article/details/136400565 Docker为容器化做了什么
https://zhuanlan.zhihu.com/p/490585683 Docker,containerd,CRI,CRI-O,OCI,runc
https://kubernetes.io/zh-cn/docs/concepts/architecture/cgroups/ 关于 cgroup v2
https://developer.aliyun.com/article/786448 cgroup性能优化
https://zhuanlan.zhihu.com/p/603780174 Docker 容器的核心基石 Cgroups
https://zhuanlan.zhihu.com/p/434731896 一篇搞懂容器技术的基石:cgroup
https://zhuanlan.zhihu.com/p/433327341 Namespace 和 cgroup 的简介及其工作原理
https://zhuanlan.zhihu.com/p/388101355 linux cgroups 详解
https://www.cnblogs.com/KubeExplorer/p/17927408.html 深入理解 Docker 核心原理:Namespace、Cgroups 和 Rootfs
https://blog.csdn.net/Urbanears/article/details/134070119 Docker 镜像读写层核心概念:rootfs、Union mount、image以及layser原理详解
https://blog.csdn.net/qq_62344659/article/details/131844959 Docker File 镜像的创建