安全容器

现在的安全容器用的是Kata containers。

它最主要的卖点就是一句话: The speed of containers, the security of VMs

可以看到这句话里面其实强调了安全容器的卖点与定位是: 介于容器和VM之间。

和容器比,它性能还算可以,同时操作体验差不多,兼容容器的这一套玩法。同时它和VM一样安全。

而与VM相比,它比VM轻量化许多,启动速度更好,开销更低。

安全体现在:用的是VM的硬件虚拟化支持,硬件隔离。没有共享kernel,不依赖于内核的namespace这种软件层面的隔离。

那容器体现在哪里: 兼容性上:支持OCI以及CRI接口,和容器一样操作。 性能上:启动速度达到百毫秒级,接近容器。 开销上:内存开销小,类似容器。

kata给容器设置密码 kata容器原理_虚拟化技术

几个关键问题

对照上面说的卖点,它自然就有几个关键问题。

如何做到lightweight VM

最最关键的性能优化来自Intel Clear Containers。 最最关键的优化其实就是VM的启动时间进行裁剪,优化。使用特定的Linux内核,使用简化的initrd以及rootfs。

怎样接上容器的生态

kata-containers它本质上就一个容器的runtime。用户根本不用知道底层的runtime是runC、rkt还是kata-containers,也不用管底层用的虚拟化技术。 只要实现了OCI的接口就可以接上那些容器管理工具,只要实现了CRI接口,就可以接上k8s。

所以kata-containers实现了OCI、CRI接口,就可以无缝衔接上容器生态。

设计实现

启动运行流程

  1. docker/kubelet通过接口调用containerd-shim-kata-v2创建pod/container,
  2. container-shim-kata-v2为每个容器/pod创建一个QEMU/KVM虚拟机。
  3. 虚拟机中启动一个极简的kernel,最终运行一个用户态程序kata-agent。kata-agent通过VSOCK向host上暴露一个gRPC接口,container-shim-kata-v2通过这个接口连接上kata-agent,进而实现对虚拟机内部的管理。这个gRPC接口既用于传输管理命令,也用于传输stdin,stdout,stderr等流。
  4. kata-agent在虚拟机中通过libcontainer管理container。启动container所需要的OCI bundle可以通过block device或者mount point的形式从host上挂上去。

关于虚拟机在host上的存在形式:

  • 一个QEMU/KVM虚拟机本质上就是host上的一个进程
  • 虚拟机的一个VCPU本质上是host的一个线程,虚拟机进程中除了VCPU线程还有IO管理等线程。 * 虚拟机使用的内存来自进程的虚拟地址空间。

这边的agent干的事情和runC基本上是差不多的,区别就在于它要知道自己是在一个VM里面,并且和再上一层的软件通信要走VSOCK。

guest asset

guest OS要准备的东西包括: 要launch的VM里面会包括一个minimal kernel以及minimal image。image里面只包含了systemd和kata-agent。

和传统的runC的区别

最大的区别就在于container是放在虚拟机里面运行的,中间多了一层kernel后,外面的容器管理软件就无法管理,监控里面的进程、容器,也无法和里面通信。 解决方案就是在VM里面放了一个agent,内外通过VSOCK通信,这样子内外就打通了。

实现

其实实现上最最主要的就是把容器管理的那些接口拿虚拟化的那一套东西来实现,github的文档里面给了一些对应关系的图。

CRI接口对应到construct:

kata给容器设置密码 kata容器原理_kata给容器设置密码_02

这些construct对应到虚拟化技术的concept:

kata给容器设置密码 kata容器原理_github_03

这些虚拟化的concept再对应到虚拟化技术:

kata给容器设置密码 kata容器原理_kata给容器设置密码_04

对资源管理的一些影响

  1. 无法进行container级别的控制 首先虚拟机本身就是host上的一个进程,仍然受host上的cgroup控制。所以仍然可以监控整个pod的资源使用数据,并控制pod的资源使用。 但是我们无法拿到container级别的数据,也无法直接通过host的cgroup来控制pod里面container的资源使用。
  2. 虚拟化技术的一些影响
  3. 虚拟化的overhead

在官方文档中提到了一些资源管理相关的问题:

vCPU sizing in Kata Containers

在有了虚拟机后,就多了一个可调的选项:多少个vCPU。 vCPU可以通过hotplug的方式动态增减。vCPU太多,会导致虚拟机的线程数太多,线程切换开销增大。虚拟机vCPU线程数太少,会导致虚拟机性能不够。 同时虚拟机中多了一层kernel,分配的计算资源要适当增加。

内存相关的问题

虚拟机也应用了一些内存管理技术:KSM,balloon,这些可能也会对内存管理有一些影响。

host-cgroups管理

现在容器运行在两层cgroup中。一个是host的cgroup,还有一个是VM中的cgroup。 kubelet在创建容器时,一般是自己估算资源使用,然后创建一个pod cgroup,然后再让具体的runtime在这个pod cgroup里面,为每个容器创建cgroup。 然后现在的问题是:kata-containers运行容器的代价太大,不可忽略,所以就有两种方法来解决这个问题: 1. kubelet在估算资源使用的时候,要考虑好kata-containers的overhead,并且合理地size pod cgroup。 2. kata containers不完全限制住VMM的资源使用,而是让它们的一部分不受pod-cgroup的控制。

这两种方法是可选的。 方法的对比:

kata给容器设置密码 kata容器原理_github_05