本节主要介绍container runtime、secure container两个概念。
因为介绍container runtime本身就会占据较大的篇幅,索性就把Kata的部分推到下一节。

Container Runtime

目前在Kubernetes上缺省使用的容器方案的调用链大概是Docker Engine -> containerd -> runC这样子,而很多人也知道,这里的容器实现机制实际上是Linux namespaces + cgroups (control groups),对应了runc所做的工作。Namespace和cgroup的具体机制不再详细介绍,此处更关注于container runtime的概念。

Docker的CLI对用户提供了容器创建、停止、删除等一系列功能,包括容器的隔离环境(namespace、cgroup)、网络、镜像、数据卷等多个方面的管控。实际上,具体各方面的实现,都是交给更下层组件去做的,我们使用的CLI是docker的一个client。

docker内的client/server架构中,client接收命令后,会通过一套REST API,向docker的server端发送对应的请求。

cri-call

下图引自《Docker源码分析》系列,提供了Docker较早版本的架构细节。
docker-arch

类似runc这样使用Linux namespace、cgroup所实现的容器运行时,它们根据entrypoint命令创建的进程们会各自运行在一个“看似隔离”的环境下,独有的进程树、独有的network、独有的文件系统。不过我们知道,它们实际上是共享了host——即docker命令执行的OS环境——的内核,这也是runc容器的启动、运行开销会比虚拟机小的原因之一;当然,除此了使用共享的kernel,UnionFS等容器文件系统的设计也功不可没。

$ docker run busybox uname -a
Linux 6ee0917c5b94 4.19.84-microsoft-standard #1 SMP x86_64 GNU/Linux

Secure Container

安全容器方案,区别于传统的使用runc作为container runtime的方案,其实是指更安全的容器运行时替代方案。

在考虑到安全性问题时,传统容器这种sharing kernel方式会变成一种累赘。一些场景下,容器内运行的代码是不可信的,交付容器的用户如果是恶意的,就存在利用内核漏洞对host与其他容器进行攻击和信息窃取的可能。安全容器方案,就是在这样的背景下诞生了。

安全容器方案大致分为4类:传统OS容器配合安全机制(runc + SELinux, AppArmor, ... + rootless mode)、用户态内核的容器(Google的gVisor)、Library OS(UniKernel、Nabla Containers)、轻量虚拟化的容器(Kata Containers、Firecracker)。

  • 传统容器,配合类似SELinux、AppArmor之类的辅助手段来增强安全性,最大程度保留了sharing kernel的低开销优势,但没有从根本上解决内核逃逸的安全问题。
  • gVisor这种用户态内核方案,是指在用户态实现了一部分内核调用,类似代理的方式来屏蔽掉不够安全的内核调用。在具体的用户态内核调用设计上,Google它们统计了近几年内核攻击使用的系统调用,发现安全漏洞主要都发生在那些“冷门”的系统调用上,而比较常用的系统调用反倒相对“安全”,所以便为这些冷门调用实现了用户态代理,解析不安全调用、做好安全封装后转发。这听起来即提升了安全性,又不会严重破坏常用调用的兼容性。不过实际上使用反馈上,gVisor的稳定性还是比较差,容易crash,代码上因为模拟了许多Linux系统调用,所以复杂度较高。
  • Library OS:代表项目是Nabla Containers,原理上和gVisor相似,是在将一些系统调用是实现成库,然后让应用程序在用户态使用这些链接库。
  • MicroVM:代表项目runV/ClearContainers/Kata Containers和Firecracker,其中前二者是Kata Containers的前身。Kata Containers和Firecracker这类方案采用轻量的虚拟机替代了“容器”,例如Kata采用的就是裁剪过的QEMU,Firecracker则是Amazon用Rust实现的一个更轻量的MicroVM。这二者的共同点是用虚拟机去替代容器,应用程序因为是在VM中的运行,所以可以达到更好的隔离,兼容性上相比上面两种方案更好,同时还提供了虚拟化层面的扩展能力;不过,这类方案引入了VMM、hypervisor的开销,启动速度比传统容器慢,VMM/hypervisor本身也会占用CPU、内存资源。

Tittle-Tattle

几个月前开始在字节实习,接手这边mentor的活,开始接触安全容器的技术方向。
最初我先从阿里在InfoQ上给出的《安全容器在边缘计算场景下的实践》那里了解了一下安全容器这个技术领域的来源和落地情况。后来就以mentor他们选好的Kata Containers项目开始学习和使用了。

不过这时我还没有意识到这个领域对我学习和深入的难度。。Orz,本菜鸡在这个领域上的基础不是很好,摸爬滚打后还是对一些底层技术一知半解,面试时被灵魂拷问过了几次才发现自己之前没有抓住学习的重点。自顶向下、快速迭代的学习方法不是银弹,现在重新回顾一遍文档,发现以前漏掉了不少重要细节。

Reference

  1. Docker Overview
  2. Architecture - Kata Containers
  3. 安全容器在边缘计算场景下的实践 - InfoQ
  4. Docker源码分析(一)