Kata Containers创始人王旭:安全容器导论

从2015年5月初开始创业开发 HyperContainer (runV) 到如今,也快五年了,在这个时候还来写一篇什么是安全容器,显得略有尴尬。不过,也正是通过这五年,愈来愈多到人开始感到,我须要它却说不清它,这个时候来给你们从新解释 “安全容器” 也正是时候。

缘起:安全容器的命名

Phil Karlton 有一句名言——缓存

计算机科学界只有两个真正的难题——缓存失效和命名。安全

就容器圈而言,我相信命名绝对配得上这句话,这毫无疑问是一件让老开发者沉默,让新人落泪的事情。网络

仅就系统软件而言,咱们当今比较通行地称为 Linux 容器(LinuxContainer)的这个概念,曾经用过的名字大概还有——jail, zone, virtualserver, sandbox... 而一样,在早期的虚拟化技术栈里,也曾经把一个虚拟机环境叫作容器。毕竟这个词自己就指代着那些用来包容、封装和隔离的器物,实在是太过常见。以致于,以严谨著称的 Wikipedia 里,这类技术的词条叫作“系统级虚拟化”,从而回避了“什么是容器”这个问题。架构

当2013年 Docker 问世以后,容器这个概念伴随着“不可变基础设施”、“云原生”这一系列概念,在随后的几年间,以摧枯拉朽之势颠覆了基于“软件包+配置”的细粒度组合的应用部署困境,用简单地声明式策略+不可变容器就清爽地描述了软件栈。应用怎么部署彷佛离题了,咱们这里想要强调的是——app

云原生语境下的容器,实质是“应用容器”——以标准格式封装的,运行于标准操做系统环境(经常是Linux ABI)上的应用打包——或运行这一应用打包的程序/技术。框架

这个定义是我在这里写下的,可是它并非个人我的意志,这是基于 OCI (Open ContainerInitiative) 规范这一共识的,这个规范规定了容器之中的应用将被放置在什么环境中,如何运行,好比启动容器根文件系统上的哪一个可执行文件,用什么用户,须要什么样的 CPU、内存资源,有什么外置存储,有什么样的共享需求等等。运维

有了这一共识作基础,咱们来讲安全容器,这又是一段命名血泪史。当年,个人联合创始人赵鹏是用“虚拟化容器”命名的咱们的技术的,为了搏人眼球,用了“Secure as VM, Fast asContainer”的大字标语,自此,被容器安全性问题戳中心坎的人们马上用“Secure Container”来称呼这类东西,一发而不可收。而咱们的心里中,这项技术提供了一层额外的隔离,隔离可能意味着安全性中的一环,也意味着某些运维效率、某些优化可能或者其余的功能。实际上,给安全容器这样的定义更合理——ide

一种运行时技术,为容器应用提供一个完整的操做系统执行环境(经常是LinuxABI),但将应用的执行与宿主机操做系统隔离开,避免应用直接访问主机资源,从而能够在容器主机之间或容器之间提供额外的保护。性能

 

间接层:安全容器的精髓

安全问题的惟一正解在于容许那些(致使安全问题的)Bug发生,但经过额外的隔离层来阻挡住它们。优化

—— LinuxCon NA 2015, Linus Torvalds

为了安全,为何要引入间接层?由于以 Linux 之类的目前主流宿主机操做系统的规模,是没法从理论上验证程序是没有 Bug 的,而一旦合适的 Bug 被合适地利用,安全性风险就变成了安全性问题了,框架和修补并不能确保安全,因此,进行额外的隔离、缩减***面,就成了缓解安全问题的法宝——咱们不能确保没有漏洞,但咱们经过组合来减小漏洞被完全攻破的风险。


Kata: 云原生化的虚拟化

2017年12月,咱们在 KubeCon上对外发布了 Kata Containers 安全容器项目,这个项目的两个前身——咱们发起的的 runV 和Intel 发起的 Clear Container 都发布于2015年5月(是的,早于上面 Linus 的引语)。这组项目的思路很简单 ——

1. 操做系统自己的容器机制没办法解决安全性问题,须要一个隔离层;

2. 虚拟机是一个现成的隔离层,AWS这样的云服务已经让全世界相信,对户来讲,"secure of VM" 是能够知足需求的;

3. 虚机里面只要有个内核,就能够支持 OCI 规范的语义,在内核上跑个 Linux 应用这并不太难实现;

4. 虚机可能不够快,阻碍了它在容器环境的应用,那么可不能够拥有 "speed of container" 呢?

如今,若是最后一个问题能够解决,那么它就是咱们要的“安全的容器”了——这就是 Kata Containers。

目前 Kata Containers 一般是在 Kubernetes 环境中使用的,Kubelet 经过CRI 接口让 containerd 或 CRI-O 执行运行时操做,一般镜像操做由这些 CRI Daemon 来进行,而根据请求,把 Runtime 操做写成一个 OCI Spec 交给 OCI Runtime 执行。这里,对于 1.2 以上的 containerd 和 1.5 版本上后的 Kata Containers(对应 ),一般是利用 containerd 来完成的:

  • 每一个 Pod 会有一个 shim-v2 进程来为 containerd/CRI-O 执行各类运行时操做,这个进程和整个 Pod 的生命周期一致,经过一个 ttRPC 接口为 containerd/CRI-O 提供服务;

  • Shim-v2 会为 Pod 启动一个虚拟机做为 PodSandbox提供隔离性,其中运行着一个 Linux 内核,一般这个 Linux 内核是一个裁剪过的内核,不会支持没有必要的设备;

  • 这里用的虚拟机能够是 Qemu 或是 Firecracker,若是是 Firecracker,那么根本就没有模拟的设备,而若是是 Qemu,经过配置和补丁,也会让它尽可能小一些,支持的其余虚拟机还包括 ACRN 和 cloud-hypervisor,将来后者可能会被愈来愈多的用到;

  • 这个虚拟机在启动的时候可能根本就是一个 initrd 而没有完整操做系统,或者有个极小的操做系统,总之,它彻底不是按照一台模拟机的操做系统来配置的,它只是支撑容器应用运行的基础设施,以及相关的应用环境 Metrics 采集或应用跟踪调试须要的资源;

  • 容器自己的 rootfs 会在 Sandbox 启动以后,在收到 contaienrd/CRI-O 的建立容器的 OCI 请求以后,以热插拔的方式动态插入到虚机中,容器的 rootfs 准备和虚机自己的启动是能够并行的;

  • 依照 CRI 语义和 OCI 规范,Pod 里能够启动多个相关联的容器,它们被放在同一个虚机里,而且能够互相共享 namespace;

  • 外来的存储卷能够以块设备或文件系统共享的方式插入到 PodSandbox 中,但对于 Pod 里的容器来讲,它们都是加载好的文件系统,目前开始逐渐普及的文件系统方式是专为 Kata 这样的场景设计的 virtio-fs,它不只比传统的 9pfs 更快、有更完整的 POSIX 文件系统的支持,并且借由所谓 vhost-user 和 DAX 技术,它还能够在不一样的 Pod 之间共享相同存储内容的缓存页 (page-cache),让它们能够和普通的 runC 容器同样,节约宝贵的内存;

  • 对于网络,使用 tcfilter,能够直接支持各类 CNI 的插件来提供容器网络,这样的好处是无需作什么调整就天然的工做,可是效率上由于作一次桥接会有损失,在生产环境中,也能够考虑使用 enlightened 网络模式,用一个特制的 CNI 插件来高效接入容器网络。

能够看到,首先 Kata Containers 是个全功能的容器运行时引擎,它用起来彻底不像是传统虚机,分明就是个容器引擎,而且,经过“少用没必要要的内存”和“共享能共享的内存”来下降内存的开销,更小的内存不只开销更小,启动也更轻快,对于大多数场景来讲,这实现了"secure of VM, speed of container"。在安全性以外,它比起传统的虚机,更具备容器的弹性,更少了机器的那种物理操做手感,咱们把这种技术称为“云原生化虚拟化”或者“面向云原生的虚拟化”技术。

 

gVisor: 进程级虚拟化

在 Kata Containers 以后半年的哥本哈根KubeCon 上,Google 开源了他们内部开发了五年的 gVisor 安全容器做为回应。

若是说 Kata Containers 是对经过对有隔离技术进行组合和改造来构建容器间的隔离层的话,gVisor 的设计显然是更加简洁的——gVisor 是一个用 Go 语言重写的运行在用户态的操做系统内核,称为 Sentry,它并不依赖于虚拟机,相反,它借助“平台(Platform)”的能力,让宿主机把应用的全部访问都从新转交给 Sentry,在 Sentry 中处理后再将一些必要的操做请宿主机帮忙来完成。

能够说 gVisor 在作的是一个纯粹的面向应用的隔离层,从 Linux ABI 到 Linux ABI 的“过滤器”。全新写做的优点在于不须要迁就太多已有技术栈的桎梏,能够写得更轻,启动确定也会更快,事实上,资源的伸缩也更方便,或者说更容器一些。好多操做系统圈的朋友都绝不掩饰地说,他们更喜欢 gVisor 的架构,若是能解决一些目前不容易解决掉的问题的话。

gVisor 做为隔离层,它的安全性依据在于:

  • 首先是***面变小,宿主操做系统将只为沙箱里的应用执行大约20%的 Linux 系统调用。经过研究,gVisor 的做者们发现,大多数***都是经过一些不经常使用系统调用中的缺陷进行的,不经常使用的系统调用的实现路径通常也比较少被审阅,相对于那些热路径来讲,安全性要更差一些,gVisor 的设计让应用对那些不经常使用系统调用的访问根本不会落到宿主机操做系统内核上,从而避免了大部分的***;

  • 其次是他们发现了最最常被***到的系统调用是 open(),因而他们直接将真有必要的 open()调用交给了一个专门的称为 Gopher 的进程来执行,从而能够更容易被限制、审计和管控;

  • 最后,他们是用高级语言 Go 写的内核,优点固然是更加内存安全,固然,他们也坦诚,这个语言其实不太“系统级”,他们为此不得不作了不少手脚,也为 Go Runtime 贡献了不少修改。

固然,gVisor 的架构是很漂亮,但从新实现一个内核这件事情,除了 Google 这样的巨头恐怕也没有几家能够作(相似的基本作到的也就是微软的初代 WSL了),并且这个超前的设计仍是有些现实问题:

  • 首先,就是它不是 Linux,因此,在兼容性方面和 Kata 这样的解决方案尚有差距;

  • 其次,对于当前的 Linux 系统调用方式和 CPU 指令系统,每一个系统调用的拦截都会有至关的性能开销,尽管全栈优化能够有必定缓解,但对系统调用比较多的场景来讲,性能损失没法忽略。

因此,短期内 gVisor 方案并不能成为一个终极解决方案,固然,它不只能够适应一些特定的场景,并且带来的启示性可能对将来的操做系统乃至 CPU 指令集的演进发生做用,从而推进咱们能够拥有一个更完美的安全容器解决方案。

 

安全容器:不止于安全

安全容器的隔离层让应用的问题——不管是恶意***,仍是意外错误——都不至于影响宿主机,也不会在不一样的 Pod 之间相互影响。并且实际上,额外隔离层带来的影响并不只是安全,对于调度、服务质量和应用信息的保护都有好处。

传统的操做系统容器技术是内核进程管理的一个延伸,容器进程自己是一组关联的进程,对于宿主机的调度器来讲是彻底可见的,一个 Pod 里的全部容器或进程,同时也都被宿主机调度和管理。这就意味着,在有大量容器的环境下,宿主机内核的负担很重,在不少实际环境中已经能够观察到这个负担带来的开销了。而采纳安全容器以后,从宿主机上是看不到这些完整的信息的,隔离层同时也下降了宿主机的调度开销,减小了维护负担,避免了容器之间、容器和宿主机之间的服务质量干扰。从另外一个方向看,安全容器做为一道屏障,可让宿主机的运维管理操做不能直接访问到应用的数据,这样,把用户的应用数据直接保护在沙箱里就能够下降对用户的受权要求,保障用户的数据私密性。

当咱们的目光向投向将来,能够看到,安全容器不只仅是在作安全隔离,由于安全容器隔离层的内核,相对于宿主机的内核是独立的,专门对应用服务,从这个角度说,主机/应用的功能之间作合理的功能分配和优化,展示出让人期待的潜力,未来的安全容器,可能不只是隔离性开销的下降,甚至是提高应用的效能——

隔离,让云原生基础设施更完美。


Kata Containers开源地址:

https://katacontainers.io/

相关文章
相关标签/搜索