CRI

定义

CRI(Container Runtime Interface)是 Kubernetes 为节点代理 kubelet 定义的运行时接口。kubelet 通过 gRPC 调用该接口上的方法,例如 RunPodSandboxCreateContainerStartContainerStopContainerPullImage。任何实现了 CRI 的进程,都可以成为 kubelet 的容器运行时,而不必是 Docker。

CRI 分成两类服务:

  • RuntimeService:Pod 沙箱与容器的生命周期、exec、日志、状态;
  • ImageService:镜像列表、拉取、删除与状态。

问题背景

Kubernetes 早期直接依赖 Docker 引擎。当节点上需要换用其他运行时(containerd、CRI-O,或带硬件隔离的运行时)时,把 Docker 的 API 写进 kubelet 会使控制面与单一实现耦合。CRI 把「集群认为应当存在的 Pod」翻译成一组稳定的本地调用,运行时可以用自己的方式落实这些调用。

机制说明

一次 Pod 启动的调用顺序

简化后的顺序如下:

  1. kubelet 调用 RunPodSandbox,运行时创建网络命名空间等外壳;
  2. 如有需要,PullImage 拉取容器镜像;
  3. CreateContainer 在该 sandbox 中登记容器配置;
  4. StartContainer 启动容器进程;
  5. 就绪后,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.rssandbox.rscontainer.rs
  • 配置映射:config_mapper.rs 把 CRI 请求翻译为 Box 的 CreateExecutionRequest 一类产品类型。
  • 持久状态:persistent_store.rsstate.rs
  • 文档:docs/cri-conformance.md

验证命令

在已启动 Box CRI 服务器的节点上,可使用 crictl 对同一 Unix 套接字执行 inforunpcreatestart。未部署集群时,阅读 src/cri/src/runtime_service/ 的方法列表即可建立与官方 CRI protobuf 的对应关系。

相关与易混

  • 相关:Kubernetescontainerd 与 shimOCI 标准与 bundle
  • 易混:CRI 不是 OCI Runtime Spec。OCI Runtime Spec 描述如何启动一个 bundle;CRI 描述 kubelet 如何管理 Pod 与镜像。containerd 常常同时实现 CRI,并在内部再调用 OCI runtime。