写这篇文章是来填 很久之前挖下的坑[1] 。
本文涉及组件的源码版本如下:
- Kube.NETes 1.24
- CRI 0.25.0
- ContAInerd 1.6
文章插图
图片
常见容器运行时有下面这几种,这些容器运行时都提供了不同程度的功能和性能 。但他们都遵循容器运行时接口(CRI),以便能够与 Kubernetes 或其他容器编排系统集成,实现容器的调度和管理 。
- containerd[2]
- CRI-O[3]
- Docker Engine[4]
- Mirantis Container Runtime[5]
CRI 的前生今世
文章插图
图片
CRI 的首次引入是在 Kubernets 1.5[6],初始版本是 v1alpha1 。在这之前,Kubernetes 需要在 kubelet 源码中维护对各个容器运行时的支持 。
有了 CRI 之后,在 kubelet 中仅需支持 CRI 即可,然后通过一个中间层 CRI shim(grpc 服务器)与容器运行时进行交互 。因为此时各家容器运行时实现还未支持 CRI 。
在去年发布的 Kubernetes 1.24 中,正式移除了 Dockershim[7],与容易运行时的交互得到了简化 。
Kubernetes 目前支持 CRI 的 v1alpha2 和 v1 。其中 v1 版本是在 Kubernetes 1.23 版本中引入的 。
每次 kubelet 启动时,首先会尝试使用 v1 的 API 与容器运行时进行连接 。如果失败,才会尝试使用 v1alpha2 。
kubelet 与 CRI在之前做过的 kubelet 源码分析[8] 会持续监控来自 文件、apiserver、http 的变更,来更新 pod 的状态 。写那篇文章的时候,分析到这里就结束了 。因为这之后的工作就交给 容器运行时[9] 来完成 sandbox 和各种容器的创建和运行,见 `kubeGenericRuntimeManager#SyncPod()`[10] 。
kubelet 启动时便会 初始化 CRI 客户端[11],与容器运行时建立连接并确认 CRI 的版本 。
创建 pod 的过程中,都会通过 CRI 与容器运行时进行交互:
- 创建 sandbox
- 创建容器
- 拉取镜像
- pkg/kubelet/kuberuntime/kuberuntime_sandbox.go#L39[12]
- pkg/kubelet/kuberuntime/kuberuntime_container.go#L176[13]
- pkg/kubelet/images/image_manager.go#L89[14]
Containerd 与 CRIContainerd 的 `criService`[15] 实现了 CRI 接口 `RuntimeService`[16] 和 `ImageService `[17] 的 RuntimeServiceServer 和 ImageServiceServer 。
cirService 会进一步包装成 `instrumentedService`[18],保证所有的操作都是在 k8s.io命名空间下执行的
RuntimeServiceServer
ImageServiceServerImageServiceServer[20]
type ImageServiceServer interface {// ListImages lists existing images.ListImages(context.Context, *ListImagesRequest) (*ListImagesResponse, error)// ImageStatus returns the status of the image. If the image is not// present, returns a response with ImageStatusResponse.Image set to// nil.ImageStatus(context.Context, *ImageStatusRequest) (*ImageStatusResponse, error)// PullImage pulls an image with authentication config.PullImage(context.Context, *PullImageRequest) (*PullImageResponse, error)// RemoveImage removes the image.// This call is idempotent, and must not return an error if the image has// already been removed.RemoveImage(context.Context, *RemoveImageRequest) (*RemoveImageResponse, error)// ImageFSInfo returns information of the filesystem that is used to store images.ImageFsInfo(context.Context, *ImageFsInfoRequest) (*ImageFsInfoResponse, error)}
下面以创建 sandbox 为例看一下 Containerd 的源码 。Containerd 源码分析创建 sandbox 容器的请求通过 CRI 的 UDS(Unix domain socket)[21] 接口 /runtime.v1.RuntimeService/RunPodSandbox,进入到 criService 的处理流程中 。在 criService#RunPodSandbox(),负责创建和运行 sandbox 容器,并保证容器状态正常 。
推荐阅读
- 海蛤怎么存放
- 怎么存放蜜蜂 怎么存储蜂蜜
- Docker容器中的Postgresql备份脚本异常解决办法
- 容器技术架构、网络和生态详解
- 基于容器的微服务架构选型与设计
- 如何基于 Kubernetes 实现优质开发者平台体验?
- Kubernetes 是我的正确选择吗?
- Kubernetes 1.28发布,包含45项增强功能!
- DevOps团队如何提高Kubernetes性能
- Kubernetes 微内核的分布式操作系统