kubelet和CRI设计
kubelet组件
Pod调度完成后,Kubernetes就需要负责将这个调度成功的Pod在宿主机上创建出来,并把它所定义的各个容器启动起来.这些,都是kubelet 这个核心组件的主要功能
kubelet本身也是按照“控制器”模式来工作的 就是一个控制循环.驱动控制循环(主循环)运行的事件
1.Pod更新事件
2.Pod生命周期变化
3.kubelet本身设置的执行周期
4.定时的清理事件
kubelet维护着很多子控制循环 这些子控制循环的责任就是通过控制器模式完成kubelet的某项具体职责
1.Volume Manager
2.Image Manager
3.Node Status Manager
CRI介绍
ContainerRuntimeInterface容器运行时接口
kubelet创建和管理容器的时候并不是直接调用Docker API而是通过一组叫做CRI的gRPC接口来间接执行的 kubelet -> dockershim ->docker daemon
CRI机制能够发挥作用的核心,就在于每一种容器项目现在都可以自己实现一个CRI shim自行对CRI请求进行处理.这样Kubernetes就有了一个统一的容器抽象层,使得下层容器运行时可以自由地对接进入Kubernetes当中,这里的CRI shim就是容器项目的维护者自由发挥的"场地"
可以在每个节点上单独安装一个负责响应CRI的组件,这个组件被称为CRI shim.CRI shim的作用就是实现CRI规定的每个接口 然后把kubelet发送的请求转换成对后端容器项目的请求或者操作
除docker shim默认被安装之外,其他容器运行时的CRI shim,都是需要额外部署在宿主机上的
CRI实现原理
CRI接口定义和调用流程分析
将Kubernetes发出的CRI请求,转换成对containerd的调用,然后创建出 runC容器.而runC项目,才是负责执行我们前面讲解过的设置容器Namespace、Cgroups 和chroot等基础操作的组件
CRI两组待实现的接口定义:
第一组: 是RuntimeService.它提供的接口,主要是跟容器相关的操作.比如,创建和启动容器、删除容器、执行 exec 命令等等
第二组: 是ImageService.它提供的接口,主要是容器镜像相关的操作,比如拉取镜像、删除镜像等等
CRI设计的一个重要原则,就是确保这个接口本身只关注容器,不关注 Pod
后端容器项目实现自己的Pod模型:
当我们执行 kubectl run 创建了一个名叫foo 包括了A、B 两个容器的Pod之后.这个Pod的信息最后来到 kubelet,kubelet就会按照图中所示的顺序来调用CRI接口
在具体的CRI shim中这些接口的实现是可以完全不同的.如果是Docker项目,dockershim就会创建出一个名叫foo的Infra容器(pause容器),用来“hold”住整个Pod 的Network Namespace
如果是基于虚拟化技术的容器,比如Kata Containers项目,它的CRI实现就会直接创建出一个轻量级虚拟机来充当Pod
在RunPodSandbox这个接口的实现中,还需要调用networkPlugin.SetUpPod(…) 来为这个Sandbox设置网络.这个 SetUpPod(…) 方法,实际上就在执行CNI插件里的 add(…) 方法,也就是调用CNI插件为Pod创建网络,并且把Infra容器加入到网络中的操作
接下来kubelet继续调用CreateContainer和StartContainer接口来创建和启动容器 A、B.对应到dockershim里就是直接启动 A,B两个Docker容器,所以最后,宿主机上会出现三个Docker 容器组成这一个Pod
如果是Kata Containers 的话CreateContainer 和 StartContainer接口的实现,就只会在前面创建的轻量级虚拟机里创建两个 A,B容器对应的Mount Namespace.所以,最后在宿主机上,只会有一个叫作foo的轻量级虚拟机在运行
以上是CRI shim对容器生命周期的实现
CRI shim实现长连接
CRI shim对容器生命周期的实现之外还有一个重要的工作,就是如何实现exec、logs等接口.这些接口跟前面的操作有一个很大的不同就是这些gRPC接口调用期kubelet需要跟容器项目维护一个长连接来传输数据.这种 API,我们就称之为Streaming API
CRI shim里对Streaming API 的实现,依赖于一套独立的Streaming Server机制
1.对一个容器执行kubectl exec命令的时候,这个请求首先交给API Server,然后API Server就会调用kubelet的Exec API
2.kubelet就会调用CRI的Exec 接口,而负责响应这个接口的,自然就是具体的CRI shim
3.CRI shim并不会直接去调用后端的容器项目来进行处理,而只会返回一个 URL 给 kubelet.这个URL就是该CRI shim对应的Streaming Server 的地址和端口
4.而kubelet在拿到这个URL之后,就会把它以Redirect的方式返回给 APIServer.这时APIServer就会通过重定向来向Streaming Server发起真正的/exec请求,与它建立长连接
5.这个Streaming Server本身是需要通过使用SIG-Node为你维护的Streaming API库来实现的.并且Streaming Server会在CRI shim启动时就一起启动
本文来自博客园,作者:不懂123,转载请注明原文链接:https://www.cnblogs.com/yxh168/p/12255774.html