CRI
定义
CRI(Container Runtime Interface)是 Kubernetes 为节点代理 kubelet
定义的运行时接口。kubelet 通过 gRPC 调用该接口上的方法,例如
RunPodSandbox、CreateContainer、StartContainer、StopContainer、PullImage。任何实现了
CRI 的进程,都可以成为 kubelet 的容器运行时,而不必是 Docker。
CRI 分成两类服务:
- RuntimeService:Pod 沙箱与容器的生命周期、exec、日志、状态;
- ImageService:镜像列表、拉取、删除与状态。
问题背景
Kubernetes 早期直接依赖 Docker 引擎。当节点上需要换用其他运行时(containerd、CRI-O,或带硬件隔离的运行时)时,把 Docker 的 API 写进 kubelet 会使控制面与单一实现耦合。CRI 把「集群认为应当存在的 Pod」翻译成一组稳定的本地调用,运行时可以用自己的方式落实这些调用。
机制说明
一次 Pod 启动的调用顺序
简化后的顺序如下:
- kubelet 调用
RunPodSandbox,运行时创建网络命名空间等外壳; - 如有需要,
PullImage拉取容器镜像; CreateContainer在该 sandbox 中登记容器配置;StartContainer启动容器进程;- 就绪后,kubelet 通过状态接口与 exec / 日志接口观察和调试。
Box 的当前实现将 agent 工作负载推迟到
StartContainer,而不是在创建 sandbox
时立即拉起,以避免取消路径上留下半创建的 VM。取消与销毁在 VM
拆除失败时仍须尽力回收孤儿资源。
传输与 Unix 套接字
节点上 kubelet 与运行时通常通过 Unix domain socket 通信,而不是公开的
TCP 端口。gRPC 建立在 HTTP/2 之上。标准 h2
库会拒绝把套接字路径当作 :authority 的写法,导致
kubelet、crictl 一类客户端被复位。Box 因此在 workspace 中 vendor 并修补
h2,见 src/Cargo.toml 的
[patch.crates-io] 与
src/third_party/h2/。这是适配细节,不影响 CRI
的语义,但解释了为何 CRI crate 需要额外依赖。
符合性与预览
「实现了若干方法」不等于「通过官方 CRI 符合性套件」。Box 将 CRI 与
containerd shim 标为预览,并在 docs/cri-conformance.md
中单独记录范围。阅读代码时,不应把 src/cri/
的存在理解成生产集群声明。
在 Box 中的位置
- crate:
src/cri/,入口src/cri/src/main.rs,服务拆在runtime_service/、image_service.rs、sandbox.rs、container.rs。 - 配置映射:
config_mapper.rs把 CRI 请求翻译为 Box 的CreateExecutionRequest一类产品类型。 - 持久状态:
persistent_store.rs、state.rs。 - 文档:
docs/cri-conformance.md。
验证命令
在已启动 Box CRI 服务器的节点上,可使用 crictl 对同一
Unix 套接字执行
info、runp、create、start。未部署集群时,阅读
src/cri/src/runtime_service/ 的方法列表即可建立与官方 CRI
protobuf 的对应关系。
相关与易混
- 相关:Kubernetes、containerd 与 shim、OCI 标准与 bundle
- 易混:CRI 不是 OCI Runtime Spec。OCI Runtime Spec 描述如何启动一个 bundle;CRI 描述 kubelet 如何管理 Pod 与镜像。containerd 常常同时实现 CRI,并在内部再调用 OCI runtime。