【云原生】容器技术发展

“云原生技术有利于各组织在公有云、私有云和混合云等新型动态环境中,构建和运行可弹性扩展的应用。云原生的代表技术包括容器、服务网格、微服务、不可变基础设施和声明式API。”

聊容器技术避不开云原生,聊云原生也避不开容器技术。容器技术和云原生就是一对双螺旋体,容器技术催生了云原生思潮,云原生生态推动了容器技术发展。从2013年docker(container)技术诞生,到2015年CNCF这个云原生领域重量级联盟便成立,这不是历史的巧合而是历史的必然。作为云原生关键技术之一的容器,从2013年诞生以来一直是行业关注的焦点之一。

1. 容器与容器编排系统的发展

在OS虚拟化这条技术路线上,最大的技术贡献来源于Google。2003-2006年,Google陆续发布的“三驾马车”,奠定了大数据计算的框架,随后进一步创造了“云”的概念。也是从这时期开始,进程隔离技术进入了一个更高级的阶段。在 Google 提出的云计算框架下,被隔离的进程不仅仅是一个与外界隔绝但本身却巍然不动的 Jail,它们更需要像一个个轻便的容器,除了能够与外界隔离之外,还要能够被控制与调配,从而实现分布式应用场景下的跨平台、高可用、可扩展等特性。2006年,Google推出Process Containers,用来对一组进程进行限制、记账、隔离资源(CPU、内存、磁盘 I/O、网络等)。由于技术更加成熟,Process Container 在 2006 年正式推出后,第二年就进入了 Linux 内核主干,并正式更名为 cgroups,标志着 Linux 阵营中“容器”的概念开始被重新审视和实现。

在 2008 年,通过将 cgroups 的资源管理能力和 Linux Namespace (命名空间)的视图隔离能力组合在一起,一项完整的容器技术 LXC (Linux Container)出现在了 Linux 内核中,这就是如今被广泛应用的容器技术的实现基础。

2013年容器引擎Docker推出之后迅速席卷全球,容器技术进入迸发期,相对于容器虚拟化技术,Docker真正核心的创新是容器镜像(docker image),一种新型的应用打包、分发和运行机制。容器镜像将应用运行环境,包括代码、依赖库、工具、资源文件和元信息等,打包成一种操作系统发行版无关不可变更软件包。

  • 容器镜像打包了整个容器运行依赖的环境,以避免依赖运行容器的服务器的操作系统,从而实现“build once,run anywhere”。
  • 容器镜像一但构建完成,就变成read only,成为不可变基础设施的一份子。
  • 操作系统发行版无关,核心解决的是容器进程对操作系统包含的库、工具、配置的依赖,但是容器镜像无法解决容器进程对内核特性的特殊依赖。这个在实际使用容器的过程中也经常跳进这个大坑

Docker的宣传口号是“Build,Ship and Run Any App,Anywhere”。我们已经理解了docker通过container image解决“Run Anywhere”的机制,那么“Run Any App”是如何实现的呢?其实也是依赖container image,用户可以打包任何容器进程所依赖的环境,而不用改造应用来适配PaaS定义的运行环境。真是“Run Any App”一举打破了PaaS行业面临的困境,创造出了无限的可能性,大力推动了云原生的发展,定义:容器 = 镜像 + 执行引擎

2014年Google基于内部使用的Borg系统创建了开源项目Kubernetes(简称K8S),用于解决大规模集群的容器部署、运行、管理等问题。Kubernetes在容器的基础上增加了一层的新的管理抽象Pod,以便更好地利用容器进行应用的功能模块切分。得益于 Google 在大规模集群基础设施建设的强大积累,脱胎于 Borg 的 K8S 很快成为了行业的标准应用,堪称容器编排的必备工具。

容器编排托管服务节点级的典型架构是利用IaaS系统生成VM,然后在VM里面部署kubelet、docker、containerd、runC等容器服务组件,也就是VM + 容器的技术架构。一个VM可以承载同一个用户的多个容器/Pod实例。而Serverless容器实例服务的节点级架构更直接,在一个VM里面只部署一个容器/Pod实例,从而实现Serverless。这种短平快的打法快速推进了商用模型的探索,起到了非常重要的历史作用,但是其在弹性能力、部署密度、资源成本方面的历史局限性还是很大的。

【云原生】容器技术发展_基础设施

到2019年,容器服务的商业形态以及市场趋势已经很明显了,行业整体进入了商业拓展阶段,对外宣传吸引更多的客户群体,对内苦练内功提升产品技术竞争力,行业正在经历从“有”到“优”的技术升级。到现在为止,我们大体上可以把容器引擎技术划分为两代:

  1. Container on VM。也就是按照分层设计思路,通过IaaS + PaaS的架构构建容器服务,这个是商用探索阶段的典型架构。基于各大云厂商成熟的IaaS基础设施生产虚拟机,在虚拟机里面部署容器服务组件。这种架构采用的是lift and shift策略,把容器服务的运维责任从用户转移到云厂商。采用和用户相同的软件组件,只是转移运维责任,有利于引导客户逐步上云、接受云原生思维。但是这个时期云厂商提供的服务是单纯的运维托管,相对用户自建容器服务并没有太明显的技术优势,甚至受多租户隔离的限制部分使用体验还不如用户自建容器服务。
  2. **Container with hardware virtualization。**如果沿用Container on VM的分层设计架构,云厂商很难构建独有的技术优势。对于Serverless容器实例服务,服务交付平面已经从IaaS的硬件接口上移到OS Syscall,所以不要遵循VM + 容器的分层设计思路。我们需要从需求本源出发,容器服务需要高性能、强隔离、够安全和低成本的容器引擎。

2. 容器引擎技术

在具体介绍容器执行引擎方案及技术路线之前,先上一张容器引擎技术江湖门派概览图,以飨读者。

【云原生】容器技术发展_容器_02

提到容器引擎(Container Engine)、容器运行时(Container Runtime)这些名称,总是有点容易让人犯晕。为了让事情简化一些,我们关注在云原生、K8S场景下的定义吧。

相对较为正式的术语定义如下图,可以把容器管理系统分为三层:

  1. High-level Container Management:容器管控的UI层。直接实现容器的管控和使用界面,也是用户最熟悉的子系统。
  2. High-level Container Runtime:容器状态及资源供给。包括镜像管理、网络接入、容器状态、调用Low Level Runtime执行容器等功能。习惯上这层称之为容器引擎(Container Engine)。
  3. Low-level Container Runtime:容器执行层。负责具体构建容器运行环境并执行容器进程。习惯上这层直接简称为容器运行时(Container Runtime)。

High-level Container Management和Container Engine之间的接口规范是CRI,Container Engine和Container Runtime之间的接口规范是OCI。

【云原生】容器技术发展_基础设施_03

3. 容器运行时

runC是目前使用最广泛的容器运行时,但是runC也不是完美的。业界对runC的担心主要集中在runC的隔离能力,众所周知runC容器共享一个host内核,利用cgroup和namespace机制来构建相互隔离的容器执行环境。Docker、LXC、RKT和runC这类原生容器都是基于共享主机操作系统的,这些技术的优点是资源利用率高、弹性能力强,缺点则是受攻击面大和攻击后果严重。特别是在多租户的云环境中,不同客户的容器会被编排部署到同一个服务器系统,这种威胁就变得尤其明显了。

其实,容器引擎技术领域也存在类似CAP理论的三边关系:资源效率、安全隔离和标准通用。目前所有的容器运行时技术最多都只能满足资源效率、安全隔离和标准通用中的两项,还没有一个技术能做到同时满足三项。比如:runC在资源效率和标准通用方面最强,但是在安全隔离方面却最弱。Kata containers/firecracker-containerd/runD在安全隔离和标准通用上有优势,但是在资源效率方面却有不足。

【云原生】容器技术发展_容器_04

基于共享内核的OS虚拟化技术总是让人不放心,“安全容器”便应运而生了。安全容器的核心思路是摒弃共享内核,为每个Pod/Container实例配置一个专用的容器OS,再辅以硬件虚拟化、应用内核等技术以获得更好的隔离性。我们可以按是否使用共享内核、是否使用硬件虚拟化、是否使用Linux Kernel作为容器内核几个纬度来对容器运行时进行分类。从下面的分类表可以看出,基于硬件虚拟化+Linux分离内核是目前行业的主流技术路线。

【云原生】容器技术发展_基础设施_05

安全容器与传统容器虚拟机的关系发展

【云原生】容器技术发展_linux_06

参考文章

​容器技术之发展简史(刘奖)​​​​容器技术之容器引擎与江湖门派(刘奖)​