1. CRI 概述:定义、设计目标与在 Kubernetes 中的位置
1.1 CRI 的定义
CRI(Container Runtime Interface) 是 Kubernetes 在 v1.5 引入的插件接口协议,用于解耦 kubelet 与底层容器运行时。CRI 定义了 kubelet 与容器运行时之间的 gRPC API 契约,使任何实现了该接口的运行时都能无缝接入 Kubernetes 集群。
核心定义:CRI 是一组 protobuf 定义的 gRPC 服务,包含 ImageService(镜像管理)和 RuntimeService(容器生命周期管理),是 Kubernetes 节点组件与容器运行时之间的唯一通信通道。
1.2 设计目标
| 设计目标 | 说明 | 关键作用 |
|---|---|---|
| 解耦 | 将 kubelet 与具体运行时实现分离 | 支持 Docker、containerd、CRI-O、Kata Containers 等任意运行时 |
| 标准化 | 统一容器生命周期管理接口 | PodSandbox、Container 创建/启动/停止/删除等操作标准化 |
| 可插拔 | 运行时可在不修改 kubelet 代码的前提下替换 | 集群运维升级、容量调优时灵活切换运行时版本 |
| 向后兼容 | 接口版本演进时保持旧版本兼容 | 版本差异校验机制保障升级过程不中断 |
| 性能透明 | 运行时实现细节对 kubelet 透明 | 容量治理场景下可独立优化运行时资源消耗 |
1.3 CRI 在 Kubernetes 架构中的位置
CRI 位于 Kubernetes 节点组件 kubelet 与 容器运行时 之间,是节点侧的核心抽象层。其位置关系如下图所示:
1.4 CRI 的核心服务与接口
CRI 定义了两个核心 gRPC 服务,每个服务包含若干 RPC 方法:
| 服务名称 | 主要 RPC 方法 | 功能描述 |
|---|---|---|
| RuntimeService | RunPodSandbox |
创建 Pod 沙箱(隔离环境) |
CreateContainer |
在 Pod 沙箱内创建容器 | |
StartContainer |
启动已创建的容器 | |
StopContainer |
停止运行中的容器 | |
RemoveContainer |
删除已停止的容器 | |
| ImageService | PullImage |
拉取容器镜像 |
ListImages |
列出节点上已有镜像 | |
RemoveImage |
删除指定镜像 |
1.5 CRI 版本差异校验的引入背景
在容量治理与运行时调优场景中,CRI 版本差异校验成为关键环节,原因如下:
- 运行时版本碎片化:大规模集群中不同节点可能运行不同版本的 containerd 或 CRI-O,各版本对 CRI 接口的实现细节存在差异。
- 容量调优依赖精确接口:资源统计(如
ContainerStats)、Pod 资源限制查询等容量治理操作依赖 CRI 返回的精确字段,版本差异可能导致数据缺失或格式变化。 - 升级过程中的兼容性保障:滚动升级节点运行时版本时,kubelet 需要校验 CRI 版本是否在支持范围内,避免因接口不匹配导致 Pod 调度失败。
容量治理视角:CRI 版本差异校验直接影响
kubelet 对容器内存、CPU、磁盘等资源使用量的采集精度。在版本差异较大的场景下,建议优先使用 crictl 工具手动验证接口响应结构,再调整 kubelet 的 --container-runtime-endpoint 参数。
1.6 CRI 版本协商机制
kubelet 与容器运行时之间通过 VersionRequest/VersionResponse 进行版本协商:
// CRI 版本协商流程(简化)
1. kubelet 启动时调用 RuntimeService.Version()
2. 运行时返回自身支持的 CRI 版本号(如 "v1alpha2" 或 "v1")
3. kubelet 校验版本是否在支持列表内
4. 若版本不匹配,kubelet 拒绝注册该运行时并报错
5. 若版本匹配,后续所有 CRI 调用均使用该版本协议
版本差异校验的核心在于:不同 CRI 版本(如 v1alpha2 与 v1)在 protobuf 消息定义、字段编号、枚举值上可能存在不兼容变更。容量调优场景下,ContainerStatsResponse 中的 CpuUsage、MemoryUsage 字段结构在不同版本间可能发生变化,直接影响资源监控数据的正确性。
注意:Kubernetes v1.24 之后移除了 dockershim,默认使用 CRI v1 版本。如果集群中仍存在使用 v1alpha2 的旧版运行时,必须通过版本差异校验逻辑进行适配,否则 kubelet 将无法正常启动。