题记:最近一段时间在做Kubernetes容器引擎接口(Container Runtime Interface, CRI)的重构,并支持以插件的方式引入外部容器引擎。CRI还在紧张有序的开发中,预计在v1.5发布第一个alpha版。
什么是CRI
CRI是Kubelet(负责管理容器生命周期的服务)与容器引擎之间的接口。为了适应多种不同的容器引擎,Kubelet在加入rkt的时候就已经在docker API的基础上抽象了一个Runtime接口,只是由于一些特定的缺陷,在这个接口上不太容易引入其他新的容器引擎:
- Runtime接口的抽象度太高,导致一些原本该在Kubelet控制的逻辑被放到了Runtime实现里面。比如在当前的实现中,rkt和docker的
SyncPod
(负责Pod创建的接口)存在大量重复的逻辑,每次修改docker部分的时,都有可能需要同时修改rkt部分。这样,如果再加入新的容器引擎的话,同时修改多个Runtime部分的代码是没法维护的。 - Runtime接口是集成在Kubelet内部的,集成容器引擎相关的代码需要放到Kubernetes代码库里面,这同样带来了维护的问题:代码维护麻烦,任何一个容器引擎修改了代码都需要发布新的kubelet;集成测试麻烦,要为每个不同的容器引擎部署不同的集成测试环境。
- 没有提供容器创建的接口,无法直接在Kubelet里面做到对容器的精细控制。
- 耦合了镜像和容器管理,而它们的生命周期本来就是独立的。
既然Runtime接口有很多问题,并且有很多容器引擎想要集成到Kubernetes中,所以有必要重新定义CRI,并且提供一种插件机制,允许容器引擎以外部独立进程的方式接入。所以,Brendan Burns在Hyper集成的时候就提供了一种以客户端/服务器方式接入外部容器引擎的思路。在大量的社区讨论后,Node team重新抽象了容器引擎接口(也就是CRI),并决定以gRPC的方式接入外部容器引擎。
CRI是如何工作的
CRI比Runtime接口提供了更细粒度的抽象,解耦了镜像管理和容器管理,并为Pod和Container提供了独立的操作接口。CRI以gRPC的方式接入,Kubelet是gPRC API的客户端,而容器引擎则是gRPC API的服务端。gRPC已经自动实现了它们之间交互的细节,容器引擎只需要实现每个具体的API。
一个典型的启动Pod的流程为
而停止Pod的流程为
CRI带了什么
CRI解决了上述提到的Runtime接口的问题,使得新的容器引擎可以更方便的集成到Kubernetes中来,这必将给Kubernetes社区带来新一轮的变革,并促进Kubernetes走入更多的应用场景中。比如,Redhat借助OCI容器引擎runc摆脱对docker依赖,Hyper以虚拟化的方式解决多租户场景下的容器隔离问题,甚至Mirantis直接用Kubernetes来管理原生的虚拟机。
CRI也解耦了容器和镜像的管理,可以方便的扩展其他镜像格式,比如ACI等。
CRI还在着力解决一些很有挑战的问题,比如
- 容器日志的管理,包括日志格式化规范、日志文件rotate、日志文件磁盘IO控制以及日志的统一收集处理等。
- 解除streaming API(exec、attach、logs等)对kubelet的网络压力。当前所有的streaming API都是从
apiserver->kubelet->runtime
,apiserver是无状态的,可以水平扩展,但kubelet和runtime则是每台机器只能有一个,streaming API有可能会给他们带来处理的瓶颈。所以在CRI中,将会考虑使用一个独立进程(需要对apiserver开放端口)来单独处理这些请求apiserver->newStreamProcess
,释放kubelet来做更核心的事情。 - 更灵活的网络配置,将Pod网络的配置完全交给容器引擎,而Kubernetes只需要最终的网络状态。
CRI的未来
虽然CRI还在持续开发中(目前还没有任何release),但已经有很多厂商已经开始了引入新容器引擎的进程:
- Frakti:为解决多租户场景下的容器隔离问题,Hyper以虚拟化的方式运行容器。关于frakti的更多细节见https://github.com/kubernetes/frakti。
- OCI-O:为解耦对docker的依赖,Redhat提供对OCI容器引擎的支持(目前主要是runc)。关于oci-o的更多细节见https://github.com/kubernetes-incubator/oci-o。
- Rktlet:为了加速rkt容器引擎的开发维护,CoreOS提议将rkt集成的代码独立出Kubelet(vendor到kubelet,同集成到kubelet内部便于发布),并重构rkt以适应CRI的变化。关于rktlet的更多细节见https://github.com/kubernetes-incubator/rktlet。
- Virtlet:为了支持原生的虚拟机管理,Mirantis提议直接用Kubernetes来管理原生的虚拟机(需要将docker镜像替换成qcow2镜像)。关于virtlet的更多细节见https://github.com/Mirantis/virtlet。
- 当然,docker相关的代码还会继续保留在kubelet内部,只不过要重构到CRI上面来。
CRI预计在Kubernetes v1.5发布第一个alpha版。届时,上面各个容器引擎的实现也将会发布第一个release。