4.4 内核容器技术
除了传统的Docker容器技术,内核容器技术在一定意义上解决了Docker安全隔离性的问题。下面提到的Kata、Firecracker和gVisor都是拥有独立内核的安全容器,简称“内核容器”。
4.4.1 Kata
2015 年,Intel OTC和国内的HyperHQ团队同时开源了基于虚拟化技术的容器实现,分别为Intel Clear Container和runV项目。2017年,这两个相似的容器运行时项目在OpenStack基金会的撮合下合并,变成了现在的Kata Containers。由于Kata Containers的本质就是一台精简后的轻量级虚拟机,所以它的特点是“像虚拟机一样安全,像容器一样敏捷”。
在启动Kata Containers之后,Kata通过一个容器运行时来控制远程服务器上的Hypervisor (如QEMU),同时Kata提供一个超轻量级的虚拟机镜像,专门用于在虚拟机内部署容器。在Kata Containers 运行起来之后,虚拟机里的用户进程(容器),实际上只能看到其中被裁剪过的GuestOS,以及通过Hypervisor虚拟出来的硬件设备,如图4-3所示。
图 4-3
Kata Containers 使用传统的虚拟化技术,通过虚拟硬件模拟出一台“小虚拟机”,然后在这台小虚拟机里安装一个裁剪后的Linux内核来实现强隔离。Kata为容器进程分配了一个独立的 GuestOS,从而避免了让容器共享宿主机内核。这样,容器进程能够看到的攻击面,就从整台宿主机内核变成了一个极小的、独立的、以容器为单位的内核,从而有效解决了容器进程发生“逃逸”或者夺取整台宿主机的控制权的问题。
4.4.2 Firecracker
2018年,AWS发布了一个名为 Firecracker 的安全容器项目,它的核心其实是一个用Rust语言重新编写的虚拟机监视器。Firecracker 和 Kata Containers 的本质原理相同,只不过 Kata Containers默认使用的虚拟机监视器是QEMU,而Firecracker则使用自己编写的虚拟机监视器。Firecracker机制如图4-4所示。
图 4-4
4.4.3 gVisor
2018 年,Google发布了gVisor,gVisor为容器进程配置了一个用Go语言实现的运行在用户态、极小的“独立内核”。这个内核对容器进程暴露了 Linux 内核 ABI(Application Binary Interface),扮演着GuestOS的角色,从而达到了将容器和宿主机隔离开的目的。
gVisor 是一个用户态内核,为上层容器提供了一个安全隔离的环境,容器所有的系统调用都会被gVisor执行。这个用户态内核是一个名为Sentry的进程,而Sentry进程的主要职责就是提供一个传统操作系统内核所能提供的能力,即运行用户程序、执行系统调用。所以Sentry并不是使用Go语言重新实现的一个完整的Linux内核,而只是一个模拟内核的系统组件。Sentry会使用KVM进行系统调用的拦截,Sentry自身就扮演着GuestOS的角色,负责运行用户程序、发起系统调用,而这些系统调用被KVM拦截下来后继续交给Sentry进行处理。只不过这时候,Sentry 被切换成一个普通的宿主机进程的角色,向宿主机发起它所需的系统调用。在这个实现中,Sentry并不会真的像虚拟机那样虚拟出硬件设备、安装GuestOS,它只是借助KVM进行系统调用的拦截,以及处理地址空间切换等细节,如图4-5所示。
图 4-5
4.4.4 Unikernel
Unikernel是一个精简的、专属的库操作系统(LibraryOS),它能够使用高级语言编译并直接运行在商用云平台虚拟机管理程序之上。Unikernel 与开发语言紧密相关,在一个特定的Unikernel上只能运行使用特定语言编写的程序,这个LibraryOS 加上自主定制的程序最终被编译成一个操作系统,在这个操作系统中只运行定制的程序,且里面只有这一个程序,没有其他冗余的东西,所以不需要多应用进程切换,系统很简单,开销也很小。简单来说,Unikernel就是一个容器应用定制化的内核,如图4-6所示。
图 4-6