本节简单介绍Kata Containers项目的基本架构。

Overview

Kata Containers是MicroVM类型的安全容器方案,它支持QEMU和Firecracker作为hypervisor,运行VM来替代传统基于namespace、cgroup的容器。

docker-kata

Kata Containers包含runtime、proxy、shim、agent等多个组件,其中kata-runtime可以与containerd-shim配合使用,也可以直接和dockerd配合。1.5.0版本后,社区提供了将containerd-shim、kata-runtime、kata-proxy、kata-shim三者整合的版本,containerd-shim-kata-v2,简化了Kata在K8s上使用的控制链路。

用户可以在K8s、Docker上切换使用runc或者kata作为容器运行时方案,Kata能为每个Pod或Container创建QEMU/KVM的VM,以更安全的MicroVM替代sharing kernel的传统容器。

Components

k8s-kata

kata-runtime:

在设计上,kata-runtime兼容OCI (Open Container Initiative) runtime spec,支持类似runC的create、delete、exec等CLI命令,同时;它也支持K8s CRI (Container Runtime Interface),支持CNI (Container Networking Interface)标准。
你可以直接使用kata-runtime CLI作为Kata Containers的entrypoint,也支持用K8s和Docker切换使用runc或Kata,创建不同类型的container runtime。

kata-agent:

Kata-agent运行在kata创建的VM内部,它负责在VM内以runc的方式去创建容器,也就是说,Kata方案下还是包含了传统容器的,host上(即运行kata-runtime的OS环境)原本的传统容器会以VM per Pod或VM per Container的形式被替代,但它们还是会运行在Kata的创建的VM内部。

Kata-agent会在VM内运行一个gRPC server,然后借助QEMU、以VIRTIO serial或VSOCK interface的形式在host上暴露一个socket file。Kata-runtime会通过gRPC来与kata-agent通信(不过一般二者之间还有kata-proxy作为中介),以管理VM内的容器。
同时,gRPC server也携带了容器和container engine之间的I/O streams,比如stdin、stdout、stderr。处理这类资源就是kata-proxy和kata-shim的事情了。

kata-proxy:

Kata VM内的容器与container engine(比如Docker Engine)之间的I/O streams是借助QEMU以VIRTIO serial或者VSOCK interface的形式暴露到host的。使用VIRTIO serial方案时,kata会为每个VM运行一个kata-proxy,以实现容器执行命令和streams的multiplexing和demultiplexing。
一般情况下,kata-runtime会通过kata-proxy来与VM内的kata-agent通信,以控制VM内容器进程的管理。

kata-shim:

Kata-shim的出现主要是考虑了VM内有多个容器的情况。每个容器进程的移除由外层的一个reaper负责,在Docker或者containerd中就是containerd-shim,在cri-o中则是conmon。而Kata方案中,多个容器可能运行在一个VM内,host上原有的reaper无法监控、控制和回收这些VM内的容器,所以就设计了位于kata-proxy和reaper之间的kata-shim,kata-runtime会为每个container创建一个对应的kata-shim,每个Pod sandbox也会有一个kata-shim。
Kata-shim会向VM内的容器进程转发signals和stdin streams,也会通过reaper将容器的stdout、stderr streams返回给CRI shim或者Docker。这样docker exec之类的OCI指令就可以作用于VM内的某个容器。

containerd-shim-kata-v2:

Containerd-shim-kata-v2可以替换kata-runtime,作为Kata的另一个entrypoint。它集成了原本的kata-runtime、kata-shim、kata-proxy以及reaper的功能。
在runtime+shim+proxy+agent的方案中,每个Pod需要2N+1个shim,即每个容器对应一对containerd-shim+kata-shim,而每个Pod Sandbox也会有一个kata-shim。而containerd-shim-kata-v2实现了Containerd Runtime V2 (Shim API),K8s只需要为每个Pod、包括其内部的多个容器创建一个shimv2就够了。除此之外,无论是否kata-agent的gRPC server是否使用VSOCK暴露到host上,都不再需要单独的kata-proxy。

Networking

Kata受限于hypervisor的功能,没有直接采用docker默认的bridge网络方案,而是采用的MACVTAP方案。
不过Kata本身是支持CNM和CNI来做组网的,网络方面相比容器,虽有额外开销但兼容性不差。

我们知道,docker默认采用的容器网络方案是基于netns+bridge+veth pairs的,即在host上创建一个network namespace,在docker0 bridge上连接veth pairs的一端,再去netns中连上另一端,打通容器和host之间的网络。
这种方案集中于namespace技术,而许多hypervisor比如QEMU不能处理veth interfaces。所以Kata为VM创建了TAP interfaces来打通VM和host之间的网络。传统的container engine比如Docker,会为容器创建netns和veth pair,然后Kata-runtime会将veth pair的一端连上TAP,即MACVTAP方案。

macvtap

Reference

  1. kata-containers/runtime
  2. Architecture - Kata Containers