Kubernetes 容器运行时(CRI)
Kubernetes 容器运行时(CRI)
kubernetes各个组件
Master
Master 是整个集群的大脑,所有的编排、调度、API 访问等都由 Master 来负责
- etcd 保存了整个集群的状态
- kube-apiserver 提供了资源操作的唯一入口,并提供认证、授权、访问控制、API
- 注册和发现等机制。并且无论是集群内部还是外部的组件,都必须通过API Server来访问数据
- kube-controller-manager 负责维护集群的状态,包括很多资源的控制器,是保证 Kubernetes 声明式 API工作的大脑,比如故障检测、自动扩展、滚动更新等
- kube-scheduler 负责资源的调度,按照预定的调度策略将 Pod 调度到相应的 Node 上
Node
负责运行具体的容器,并为容器提供存储、网络等必要的功能
- kubelet 负责维持容器的生命周期,同时也负责 Volume(CSI)和网络(CNI)的管理
- Container runtime 负责镜像管理以及 Pod 和容器的真正运行。Kubelet 默认的容器运行时为 Docker
- kube-proxy 负责为 Service 提供 cluster 内部的服务发现和负载均衡
- Network plugin 也就基于 CNI(Container Network Internface)负责为容器配置网络
扩展
- 扩展(Addon),比如 dashboard、EFK、Prometheus、各种 Operator 等,这些扩展不需要 Kubernetes 提供标准的接口,但是都为 Kubernetes 增加了新的功能特性
- 插件(Plugin),比如 CNI、CRI、CSI、Device Plugin 等,这些都是 Kubernetes 各个核心组件提供了标准的内置接口,而外部插件则是实现这些接口,从而将 Kubernetes 扩展到更多的用例场景中
Kubelet中的CRI
- Kubelet Server 对外提供 API,供 kube-apiserver、metrics-server 等服务调用。比如 kubectl exec 需要通过 Kubelet API /exec/{token} 与容器进行交互。
- Container Manager 管理容器的各种资源,比如 cgroups、QoS、cpuset、device 等。
Volume Manager 管理容器的存储卷,比如格式化磁盘、挂载到 Node 本地、最后再将挂载路径传给容器。 - Eviction 负责容器的驱逐,比如在资源不足时驱逐优先级低的容器,保证高优先级容器的运行。
- cAdvisor 负责为容器提供 metrics 数据源。
- Metrics 和 stats 提供容器和节点的度量数据,比如 metrics-server 通过 /stats/summary 提取的度量数据是 HPA 自动扩展的依据。
- 再向下就是 Generic Runtime Manager,这是容器运行时的管理者,负责跟 CRI 交互,完成容器和镜像的管理。
- 在 CRI 之下,包括两种容器运行时的实现
一个是内置的 dockershim,实现了 docker 容器引擎的支持以及 CNI 网络插件(包括 kubenet)的支持
另一个就是外部的容器运行时,用来支持 runc、containerd、gvisor 等外部容器运行时。
Kubernetes 中的容器运行时按照不同的功能就可以分为三个部分:
- Kubelet 中容器运行时的管理模块 Generic Runtime Manager,它通过 CRI 来管理容器和镜像。
- 容器运行时接口,是 Kubelet 与外部容器运行时的通信接口。
- 容器运行时实现,包括 Kubelet 内置的 dockershim 以及外部的容器运行时(如 cri-o、cri-containerd 等)
容器运行时接口(CRI)
容器运行时接口(CRI),顾名思义,用来在 Kubernetes 扩展容器运行时,从而用户可以选择自己喜欢的容器引擎。
CRI 接口
CRI 是基于 gPRC 的,用户不需要关心内部通信逻辑,而只需要实现定义的接口就可以,包括 RuntimeService 和 ImageService: RuntimeService负责管理Pod和容器的生命周期,而ImageService负责镜像的生命周期管理
管理镜像的 ImageService 提供了 5 个接口,分别是查询镜像列表、拉取镜像到本地、查询镜像状态、删除本地镜像以及查询镜像占用空间等。这些都很容易映射到 docker API 或者 CLI 上面。
而 RuntimeService 则提供了更多的接口,按照功能可以划分为四组:
- PodSandbox 的管理接口:PodSandbox 是对 Kubernete Pod 的抽象,用来给容器提供一个隔离的环境(比如挂载到相同的 cgroup 下面),并提供网络等共享的命名空间。PodSandbox 通常对应到一个 Pause 容器或者一台虚拟机。
- Container 的管理接口:在指定的 PodSandbox 中创建、启动、停止和删除容器。
- Streaming API 接口:包括 Exec、Attach 和 PortForward 等三个和容器进行数据交互的接口,这三个接口返回的是运行时 Streaming Server 的 URL,而不是直接跟容器交互。
- 状态接口,包括查询 API 版本和查询运行时状态。
Streaming API
Streaming API 用于客户端与容器需要交互的场景,所以采用的是流式接口,包括 Exec、PortForward 和 Attach 等。Kubelet 内置的 docker 通过 nsenter、socat 等方法来支持这些特性,但它们不一定适用于其他的运行时。因而,CRI 也显式定义了这些 API,并且要求容器运行时返回一个 streaming server 的 URL 以便 Kubelet 重定向 API Server 发送过来的流式请求。
这样一个完整的 Exec 流程就是
- 客户端 kubectl exec -i -t …
- kube-apiserver 向 Kubelet 发送流式请求 /exec/
- Kubelet 通过 CRI 接口向 CRI Shim 请求 Exec 的 URL
- CRI Shim 向 Kubelet 返回 Exec URL
- Kubelet 向 kube-apiserver 返回重定向的响应
- kube-apiserver 重定向流式请求到 Exec URL,接着就是 CRI Shim 内部的 Streaming Server 跟 kube-apiserver 进行数据交互,完成 Exec 的请求和响应
参考
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 mutoulazy's space!