容器技术之容器引擎与江湖门派(外宣版)

本文涉及的产品
容器镜像服务 ACR,镜像仓库100个 不限时长
简介: 来来来,搬好小板凳我们继续开聊容器技术。读过本系列第一篇文章“容器技术之发展简史”的读者,可能已经理解了容器和云原生的关系,以及容器技术恒等式: 我们今天先聊执行引擎,后续将有一篇关于容器镜像的专题文章具体聊镜像格式和镜像加速。 从集装箱革命说起 有一本非常有名的书,叫《集装箱改变世界》,说的是看起来平淡无奇的铁箱子,如何从二十世纪起永久性的改变了这个世界,并促进

来来来,搬好小板凳我们继续开聊容器技术。读过本系列第一篇文章“容器技术之发展简史”的读者,可能已经理解了容器和云原生的关系,以及容器技术恒等式:

image.png

我们今天先聊执行引擎,后续将有一篇关于容器镜像的专题文章具体聊镜像格式和镜像加速。

从集装箱革命说起

有一本非常有名的书,叫《集装箱改变世界》,说的是看起来平淡无奇的铁箱子,如何从二十世纪起永久性的改变了这个世界,并促进了全球化和全球分工。集装箱的出现和发展是实体货物包装、运输、交付方式的一次革命。

image.png

《经济学家》杂志曾经评价说“没有集装箱,不可能有全球化”。集装箱为什么具有革命性?经济全球化的基础就是现代运输体系,而一个高度自动化、低成本和低复杂性的货物运输系统的核心就是集装箱。集装箱最大的成功在于其产品的标准化及由此建立的一整套运输体系。能够让一个载重几十吨的庞然大物实现标准化,并且以此为基础逐步实现全球范围内的船舶、港口、航线、公路、中转站、桥梁、隧道、多试联运相配套的物流系统,这的确堪称人类有史以来创造的伟大奇迹之一,而撬动这个系统的理念就是标准化和系统化

改变世界的不仅仅是集装箱本身,还有一整套货物处理的新方法,包括港口、货船、起重机、卡车,还有发货人的自身操作方式等。容器技术对于IT领域的意义非常类似于集装箱,只是里面装载的不再是实体货物,而是虚拟世界的二进制代码和软件。

制作集装箱可以采用不同的材料与工艺流程,只需要符合相应的标准。同理,容器技术也有不同架构和实现,只要遵循相应的技术规范,就是合格的容器技术。在具体介绍容器执行引擎方案及技术路线之前,先上一张容器引擎技术江湖门派概览图,以飨读者。

提到容器引擎(Container Engine)、容器运行时(Container Runtime)这些名称,总是有点容易让人犯晕。为了让事情简化一些,我们关注在云原生、K8S场景下的定义吧。从CNCF Cloud Native Interactive Landscape可以发现,容器引擎领域是一个很活跃的技术领域,该领域的大致发展(战争)史如右下图。

image.pngimage.png

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

  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。

image.png

下文将分别从容器引擎(High-level container runtime)和容器运行时(Low-level container runtime)两个纬度讨论容器执行引擎相关技术。

容器引擎

容器引擎的核心是准备运行容器所需要的资源以及管理容器生命周期。在K8S生态圈中,容器编排系统通过CRI接口来调用容器引擎。支持CRI接口的容器引擎主要有docker、rkt、pouch、containerd和cri-o等,其中活跃度比较高的是containerd和CRI-O。

containerd

Containerd是从dockerd中抽离出来的容器管理的核心功能,是在社区影响下dockerd模块化的结果,也是现在最热门的容器引擎。由于containerd是从dockerd演化出来的,使用接口是针对容器管理而设计,内置管理对象是Image和Container。K8S CRI的管控对象是Image/Pod/Container,为了让containerd支持Pod对象以及实现CRI接口,引入了CRI-containerd组件来粘合Kubelet和containerd两个子系统。现在cri-containerd组件已经作为一个功能模块内置到containerd。Containerd依赖后端container runtime来具体管理容器,最常见的container runtime是runC。

image.png

CRI-O

而CRI-O则是专门支持K8S CRI接口而设计实现的容器引擎,它抛弃了对docker的支持而专注于支持K8S CRI,所以架构相对containerd要简洁不少。但是,虽然架构简洁优雅,但是从实际使用体验看CRI-O在成熟度、可扩展性方面相对cantainerd还是有一定差距。今年CRI-O也增加了对shimv2接口的支持,从而可以支持runC之外其它容器运行时,但是实际测试发现功能还不成熟。

进一步看CRI-O的架构,一个CRI实现需要实现的核心功能包括:镜像管理(Image service)、运行管理(runtime service,管理Pod、container生命周期)、容器网络(CNI)和对接OCI兼容的容器运行时。这儿有一个非常重要的细节,虽然cri-containerd和CRI-O都是同时实现CRI的image service和runtime service,但是CRI规范其实允许用不同的组件来分别实现image service和runtime service

   image.png   image.png

容器运行时

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

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

image.png

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

内核形态

隔离机制

应用内核类型

容器运行时

共享内核

Cgroup/namespace

Linux

基于runC的原生容器

Windows

Windows Server Containers

独享内核

硬件虚拟化

Linux

Kata containers,Alibaba Cloud Sandbox - runD,firecracker-containerd,Project Pacific CRX

Windows

Hyper-V containers

Sentry

gvisor

libOS

NetBSD

Nabla containers

Linux

Nabla containers

runC

runC的介绍,为了节省读者的时间,此处省略一万字。。。

Kata Containers

出于对传统容器安全性的担忧,Intel 在 2015 年启动了它们以虚拟机为基础的容器技术:Clear Container。Clear Container 依赖 Intel VT 的硬件虚拟化技术以及高度定制的 QEMU-KVM(qemu-lite)来提供高性能的基于虚拟机的容器。在 2017 年,Clear container 项目加入了 Hyper RunV,这是一个基于 hypervisor 的 OCI 运行时,从而启动了 Kata 容器项目。Kata containers的核心思路是:

  1. 操作系统本身的容器机制没办法解决安全性问题,需要一个隔离层;
  2. 虚拟机是一个现成的隔离层,云服务已经让全世界相信,对户来说,"*secure of VM*" 是可以满足需求的;
  3. 虚机里面只要有个内核,就可以支持 OCI 规范的语义,在内核上跑个 Linux 应用这并不太难实现;
  4. 虚机可能不够快,阻碍了它在容器环境的应用,那么可不可以拥有 "speed of container" 呢?

所以,Kata containers核心之一是把VM变得轻快稳,使之能满足容器高密弹性的需求。同时,作为一个容器运行时,必须深度融入生态,支持相关规范。

image.png

Kata containers 最大的特点是它专注于实现一个开放的符合OCI标准的安全容器runtime实现,对于对接什么样的虚拟化方案,它抽象了一套hypervisor接口,如今已经对接了多种虚拟化实现,比如qemu、nemu、firecracker、cloud-hypervisor等。

2019年,Kata containers有个非常重要的技术进步,和containerd社区共同制定了shimv2接口规范,并率先在Kata containers支持了该规范。通过containerd-shim-v2和vsock技术,kata精简了大量的组件,配合轻量级hypervisor和精简内核,kata可以大幅降低内存开销和容器启动时间。更关键的是,降低系统部署复杂度还大幅提高了稳定性,特别是在系统重载情况下的稳定性。从实际使用体感看,阿里云沙箱容器1.0从shimv1升级到shimv2后,稳定性得到大幅提升,缺陷数量大幅下降。一个技术,同时服务于“”、“”、“”三个目标,当之无愧重要的技术进步!

image.png

第二个热点则是Kata containers 2.0架构。从2019年8月开始,阿里云、蚂蚁和intel三方共同推动Kata containers 2.0架构定义及设计,核心是进一步提升多租隔离能力及可观测性。现在蚂蚁可信原生团队、阿里云容器团队和阿里云操作系统团队三方正在合力推进Kata containers 2.0架构。

回头再聊聊Kata Containers和runC的关系吧!Kata Containers和runC不是替代与被替代,而是青出于蓝而胜于蓝。Kata Containers把runC一层基于OS虚拟化的隔离机制扩展为三层隔离:Guest OS 虚拟化(等效于runC),硬件虚拟化和Host OS虚拟化。所以Kata Containers通过引入更多的间接层来提升系统的隔离能力,但是需要付出“更多间接层”的代价。

image.png

Firecracker-containerd

Firecracker-containerd是firecracker和containerd的合体。Firecracker是AWS基于Google crosvm开发的、配合KVM使用的一个轻量级安全VMM,用以支持和实现MicroVM。Firecracker MicroVM 同时具备传统虚拟机的安全性和工作负载隔离能力以及容器的速度和资源利用率。Firecracker具有如下一些特色:

  1. 抛弃 QEMU 使用的 C 语言,选择内存安全的 Rust 作为开发语言。
  2. 基于 crosvm 使用极简设备模型,模拟尽可能少的必要设备,减小暴露的攻击面。
  3. 高性能和低开销:得益于极简的设备模型, Firecracker 取消了 SeaBIOS (开源的 X86 BIOS),移除了 PCI 总线,取消了 VGA 显示等等硬件模拟,严格的说它甚至不是一台完整的虚拟计算机。而 Firecracker 运行的 GuestOS 使用的也是 AWS 定制过的精简  Linux 内核,同样裁剪掉了对应的设备驱动程序、子系统等等。因此叫它 MicroVM,其启动步骤和加载项要远远少于传统虚拟机。因此 Firecracker 目前已经能提供小于125ms 的 MircroVM 启动速度,每秒150台的启动能力,小于5MiB 的内存开销,并发运行4000台的极限承载容量(AWS i3.metal EC2 作为宿主机),以及热升级能力等。这些都是传统虚拟机所遥不可及,但现代化弹性工作负载又有强烈需求的性能指标。

但是,Firecracker毕竟只是一个VMM,还必须配合上containerd才能支持容器生态。所以,AWS又开源了firecracker-containerd项目,用于对接K8S生态。本质上Firecracker-containerd是另外一个私有化、定制化的Kata containers,整体架构和Kata containers类似,只是放弃了一些兼容性换取更简化的实现。

image.png

gVisor

Google gVisor 是 GCP App Engine、Cloud Functions Cloud Run和 CloudML 中使用的沙箱技术,正式商用名称是Google Sandbox。Google 意识到在公有云基础设施中运行不受信容器的风险,以及虚拟机沙箱的低效,因此开发了用户空间的内核作为沙箱来运行不受信应用。gVisor是沿着libdune的系统调用拦截思路发展而来的用户态内核或进程虚拟化技术。gVisor 通过拦截所有从应用到主机内核的系统调用,并使用用户空间中 gVisor 的内核实现来处理这些调用。

image.png

本质上来说,gVisor 是 VMM 和客户内核的组合,或者说gVisor是syscall虚拟化。基于lock-in-pop理论,假设Linux内核被高频访问的syscall是安全的,这部分可以开放给容器进程直接使用而不会导致严重的安全风险;对于冷僻Linux syscall则需单独处理,要不就是sentry模拟实现,要不就是在一个专用受限环境中执行(gofer)。sentry实现了多数的 Linux 系统调用,尤其是内核功能,例如信号分发、内存管理、网络栈以及线程模型。gVisor 和 Nabla 有很相似的策略:保护主机。它们都使用了不到 10%的系统调用来和主机内核通信。gVisor 创建通用内核,而 Nabla 依赖的是 Unikernel,它们都是在用户空间运行特定的客户内核来支持沙箱应用的运行。

gVisor 还在婴儿期,也一样有一些限制。gVisor 要拦截和处理沙箱应用中的系统调用,总要有一定开销,因此不适合系统调用繁重的应用。gVisor 没有直接的硬件访问(透传),所以如果应用需要硬件(例如 GPU)访问,就无法在 gVisor 上运行。最后,gVisor 没有实现所有的系统调用,因此使用了未实现系统调用的应用是无法在 gVisor 上运行的。

出于对使用C语言开发系统软件导致的安全风险和软件缺陷的担忧,Google开创了使用安全语言开发系统软件的先河。2013年开发的gVisor选择了Golang,2017年开源的crosvm则使用Rust。从目前状态看,Rust更适合开发底层系统软件,Golang则更适合开发上层便应用管理的系统软件。也许Rust早成熟几年gVisor就会有不同的选择啦!

Nabla Containers

Nabla Containers的核心思想是用libOS作为容器运行时的隔离机制。通过增加一个隔离层,libOS kernel,把容器应用和host OS给隔离开来。nabla是继承于unikernel的隔离方式,应用采用rumprun打包成一个unikernel镜像,直接运行在一个专为运行unikernel定制虚拟机(ukvm)中。应用直接打包首先可以降低很多内核态和用户态转换的开销,另外通过ukvm暴露非常有限的主机上的syscall(只剩7个),可以大大缩小主机的攻击面。它是这些安全容器实现中,最安全的。

image.png

这条技术路径从学术理论角度看是很好的路线,但是libOS一二十年发展不起来是有原因的。它要求应用打包成unikernel镜像,因此和当前docker的镜像标准是不兼容的。另外,unikernel应用在诸如支持创建子进程等一些常规操作上都有很难解决的问题。核心原因是应用侵入性没法解决,需要修改应用来适配容器运行时,和K8S部分语义也是冲突。

最近Nabla containers项目发生了一个有意思的转变,从采用rumpkernel切换到user model linux。估计背后的原因是rumpkernel已经有6年没有更新了,背后的NetBSD活跃度也不高,Linux compatibility layer的质量有限。但是,即使切换到UML解决部分syscall ABI兼容兼容问题,这条路前途也很渺茫。

我的观点是用libOS做容器运行时是条死路,我们在这个上面有血的教训!2018年5月加入阿里云就开始unikernel,基本思路和软件架构和Nabla基本一摸一样,rumpkernel + miniOS + ukvm + OCI接口实现。搞了四五个月之后rumpkernel + miniOS + ukvm的核心架构基本ready,但是当我们计划支持OCI时,发现模拟Linux namespace、支持多进程难度太大,如果一步一步做下去最后就会做成另外一个简化版的KVM + linux实现。进一步评估发现解决OS ABI兼容或应用改造的代价都很大,所以这条技术路线不具有广泛落地生产的可能性。所以,当IBM宣布Nabla Containers项目时,我们已经基本放弃这条路线了。

Windows容器

受Windows操作系统的限制导致Windows容器天然有臃肿及生态的问题,所以Windows容器一直相对比较小众。但是从软件架构上看,Windows容器架构反而是一个非常优秀的案例,值得探讨一番。Windows 2016开始支持Windows Containers,具有两种形态:Windows Server Containers和Hyper-v Containers,其具体架构如下图。

image.png   image.png

直观的理解,Windows Server Container相当于runC,而Hypver-V Containers则相当于Kata Containers。也就是从诞生的一天开始,Windows就提供了两种不同的Container Runtime,以提供不同的特性来满足不同场景的需求。

image.png

具体到Windows Server Containers的架构细节,基本上和Linux容器技术类似,没有太多的惊喜。内核支持容器技术的关键子系统名称都是一致的:Control Groups、Namespaces、Layer Capabilities。比较特殊的是Windows内核子系统Host Compute Service实现了containerd + runc的能力,也就是说Windows内核内置支持容器对象。

image.png     image.png

为了更好地与K8S生态融合,Windows 2019在docker之外增加了对Containerd/CRI的支持,以及相关组件runhcs(run Host Computer Service,对应Linux runC)。Windows 容器技术整体架构升级为下图的架构。至此,Windows容器通过支持OCI规范基本无缝融入了K8S生态。

image.png

Windows容器技术架构中有两个很有意思的组件。一是Host Compute Service(hcs),这个是专门为容器服务的service。相对Linux直接暴露支撑容器的底层技术(cgroup,namespace,seccomp等),Windows选择了对底层基础技术进行一层封装由内核直接容器暴露容器兑现而不暴露底层技术。阿里云操作系统团队内部也进行过类似的技术探讨,Linux kernel是否应该内置支持container object,目前还没结论。二是轻量化的Hyper-V虚拟机,Microsoft基于轻量化的Hyper-V虚拟机长出了Hyper-V container,Windows Subsystem for Linux 2和Windows Sandbox三个技术。最近Redhat基于rust-vmm搞的runK类似Windows Sandbox的思路,值得关注。

VMware Project Pacific

相对其它家的技术路线,VMware Project Pacific走了一条与众不同的路线来融入K8S生态。Project Pacific没有采用常规路线实现一个runP之类的容器运行时,而是选择了全链路技术改造。Project Pacific通过spherelet、CRX等组件完全重构kubelet、containerd、runc等组件,直接对接到K8S API server。从下图的架构可以看出,Project Pacific核心是在节点上实现容器和虚拟机的混合部署,同时支持虚拟机管理系统vCenter和容器编排系统K8S。

image.png

进一步展开Project Pacific节点级的架构细节。为了支持K8S容器生态,ESXi节点上增加了Spherelet、Image Service、Spherelet Agent等组件。ESXi上同时部署了hostd(相当于pync + libvirt)和Spherelet(相当于Kubelet)两种管控系统以支持容器虚拟机混合部署,同时还为容器专门部署了Image Service用以管理容器镜像。

VMware  Project Pacific和ECI使用场景和部署形态有很多共通之处,部分设计理念值得借鉴

image.png

Alibaba Cloud Sandbox - runD

敬请期待下回分解!

小结

结尾一张图,功法全靠悟!

image.png

敬请期待

本文是容器技术系列文章的第二篇文章,系列文章请参考:

容器技术之发展简史

容器技术之阿里云沙箱容器发展历程

容器技术之镜像格式与镜像加速

参考文献

云原生时代——投资人视角下的云原生趋势思考

Kata Containers: 面向云原生的虚拟化

深度解析 AWS Firecracker 原理篇 – 虚拟化与容器运行时技术

为什么说2019,是属于容器技术的时代?

Container platform tools on Windows

Introducing the Host Compute Service (HCS)

Project Pacific – Technical Overview

 

相关实践学习
深入解析Docker容器化技术
Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。Docker是世界领先的软件容器平台。开发人员利用Docker可以消除协作编码时“在我的机器上可正常工作”的问题。运维人员利用Docker可以在隔离容器中并行运行和管理应用,获得更好的计算密度。企业利用Docker可以构建敏捷的软件交付管道,以更快的速度、更高的安全性和可靠的信誉为Linux和Windows Server应用发布新功能。 在本套课程中,我们将全面的讲解Docker技术栈,从环境安装到容器、镜像操作以及生产环境如何部署开发的微服务应用。本课程由黑马程序员提供。     相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
相关文章
|
3月前
|
存储 容器
46.[HarmonyOS NEXT RelativeContainer案例三] 打造自适应容器:内容驱动的智能尺寸调整技术
在HarmonyOS NEXT的UI开发中,创建能够根据内容自动调整尺寸的容器是实现灵活布局的关键。RelativeContainer结合自适应尺寸设置,可以实现内容驱动的智能尺寸调整,使UI更加灵活且易于维护。本教程将详细讲解如何创建自适应尺寸的RelativeContainer,帮助你掌握这一实用技术。
127 5
|
1月前
|
安全 持续交付 Docker
Docker:重塑现代软件交付的容器引擎
Docker:重塑现代软件交付的容器引擎
|
1月前
|
Kubernetes Cloud Native 持续交付
Docker:轻量级容器化技术解析
Docker:轻量级容器化技术解析
|
1月前
|
运维 测试技术 Docker
Docker:轻量级容器化技术革命
Docker:轻量级容器化技术革命
|
9月前
|
Kubernetes Cloud Native 微服务
探索云原生技术:容器化与微服务架构的融合之旅
本文将带领读者深入了解云原生技术的核心概念,特别是容器化和微服务架构如何相辅相成,共同构建现代软件系统。我们将通过实际代码示例,探讨如何在云平台上部署和管理微服务,以及如何使用容器编排工具来自动化这一过程。文章旨在为开发者和技术决策者提供实用的指导,帮助他们在云原生时代中更好地设计、部署和维护应用。
|
5月前
|
弹性计算 Java Maven
从代码到容器:Cloud Native Buildpacks技术解析
Cloud Native Buildpacks(CNB)是一种标准化、云原生的容器镜像构建系统,旨在消除手动编写Dockerfile,提供可重复、安全且高效的构建流程。它通过分层策略生成符合OCI标准的镜像,实现应用与基础镜像解耦,并自动化依赖管理和更新。阿里云应用管理支持通过CNB技术一键部署应用至ECS,简化构建和运行流程。
|
6月前
|
存储 虚拟化 Docker
|
6月前
|
开发工具 虚拟化 git
自学软硬件第755 docker容器虚拟化技术youtube视频下载工具
docker容器虚拟化技术有什么用?怎么使用?TubeTube 项目使用youtube视频下载工具
|
9月前
|
Unix Linux Docker
CentOS停更沉寂,RHEL巨变限制源代:Docker容器化技术的兴起助力操作系统新格局
操作系统是计算机系统的核心软件,管理和控制硬件与软件资源,为用户和应用程序提供高效、安全的运行环境。Linux作为开源、跨平台的操作系统,具有高度可定制性、稳定性和安全性,广泛应用于服务器、云计算、物联网等领域。其发展得益于庞大的社区支持,多种发行版如Ubuntu、Debian、Fedora等满足不同需求。
277 5
|
10月前
|
运维 Kubernetes Docker
深入理解容器化技术:Docker与Kubernetes的协同工作
深入理解容器化技术:Docker与Kubernetes的协同工作
254 14

相关产品

  • 容器服务Kubernetes版