3. CRI(Container Runtime Interface)概述:CRI的诞生背景、接口定义与主流实现

3.1 CRI 的诞生背景:从“紧耦合”到“标准化”

在 Kubernetes 早期版本(v1.5 之前),kubelet 与容器运行时的交互是硬编码的。kubelet 内部直接通过 Docker API 调用 Docker Engine 来创建、启动、删除容器。这种架构存在三个核心痛点:

  • 供应商锁定:Kubernetes 与 Docker 深度绑定,无法接入其他容器运行时(如 rkt、Hyper.sh、Kata Containers)。
  • 版本耦合:kubelet 必须跟随 Docker API 的版本升级而修改代码,维护成本极高。
  • 社区分裂风险:每个运行时都想成为 Kubernetes 的“一等公民”,但缺乏统一的接入标准。

为了解决上述问题,Kubernetes 社区在 2016 年提出了 CRI(Container Runtime Interface),作为 kubelet 与容器运行时之间的中间层抽象。CRI 使用 Protocol Buffers(protobuf) 定义 gRPC 服务,将容器生命周期管理、镜像管理、Pod 沙箱管理等操作标准化。从此,任何实现了 CRI 接口的运行时都可以无缝接入 Kubernetes。

关键里程碑:Kubernetes v1.5 引入 CRI(Alpha),v1.6 进入 Beta,v1.10 正式 GA。Dockershim 作为 Docker 的 CRI 适配器被内置在 kubelet 中,直到 v1.24 被彻底移除。
CRI 诞生前后架构对比 CRI 之前(紧耦合) kubelet Docker API Docker Engine CRI 之后(标准化) kubelet CRI gRPC containerd CRI-O

3.2 CRI 接口定义:RuntimeService 与 ImageService

CRI 将容器运行时管理拆分为两个独立的 gRPC 服务:

服务名称 核心职责 关键 RPC 方法
RuntimeService 管理 Pod 沙箱(Sandbox)和容器的完整生命周期 RunPodSandbox、StopPodSandbox、CreateContainer、StartContainer、StopContainer、RemoveContainer、ContainerStatus
ImageService 管理容器镜像的拉取、列表、检查和删除 PullImage、ListImages、ImageStatus、RemoveImage、ImageFsInfo
设计要点:Pod 在 CRI 中被抽象为“沙箱”(Sandbox)。对于基于 VM 的运行时(如 Kata Containers),一个沙箱就是一个轻量级虚拟机;对于传统容器运行时,沙箱通常对应一个隔离的 Linux 命名空间(Network、PID、IPC 等)。

以下是一个典型的 RunPodSandboxRequest 消息结构示例:

message RunPodSandboxRequest {
  // Pod 沙箱的唯一标识
  string pod_sandbox_id = 1;
  // 沙箱配置,包含 Pod 名称、UID、命名空间、DNS 等
  PodSandboxConfig config = 2;
  // 运行时特定的扩展配置
  RuntimeConfig runtime_config = 3;
}

message PodSandboxConfig {
  string name = 1;
  string uid = 2;
  string namespace = 3;
  // 主机名、DNS 配置、端口映射、标签、注解等
  DNSConfig dns_config = 4;
  repeated PortMapping port_mappings = 5;
  map<string, string> labels = 6;
  map<string, string> annotations = 7;
  LinuxPodSandboxConfig linux = 8;
}

3.3 主流 CRI 实现对比

目前社区主流的 CRI 实现有三个:containerd、CRI-O 和 Docker(通过 Dockershim)。Dockershim 已在 Kubernetes v1.24 中被移除,但仍有大量存量集群在使用。

特性 containerd CRI-O Docker + Dockershim(已弃用)
所属组织 CNCF(毕业项目) CNCF(孵化项目) Docker Inc.
核心定位 工业级容器运行时,强调稳定性和性能 专为 Kubernetes 优化的轻量级运行时 通用容器平台,通过适配器接入 K8s
镜像格式 OCI 镜像规范 OCI 镜像规范 Docker 镜像 + OCI 兼容
CRI 实现方式 内置 CRI 插件(cri) 原生 CRI 实现 kubelet 内置 Dockershim 适配器
资源开销 低(无 Docker daemon 开销) 极低(最小化依赖) 高(需运行完整 Docker daemon)
Kubernetes 默认 v1.24+ 默认运行时 OpenShift 默认运行时 v1.23 及之前默认(已弃用)
主流 CRI 实现架构对比 containerd kubelet (CRI gRPC) containerd CRI Plugin containerd 核心 CRI-O kubelet (CRI gRPC) CRI-O 守护进程 OCI 运行时 (runc)

3.4 如何选择 CRI 实现?

在选择 CRI 实现时,建议从以下维度评估:

  • Kubernetes 版本兼容性:v1.24+ 推荐 containerd,OpenShift 推荐 CRI-O。
  • 运维复杂度:containerd 和 CRI-O 都比 Docker 轻量,无需管理 Docker daemon。
  • 生态集成:如果需要与 Docker Compose、Docker Swarm 等工具共存,Docker 仍有优势(但需注意 K8s 已弃用)。
  • 性能与资源:containerd 和 CRI-O 在启动延迟、内存占用上优于 Docker。
注意:从 Kubernetes v1.24 开始,Dockershim 已被彻底移除。如果集群仍在使用 Docker 作为运行时,必须迁移到 containerd 或 CRI-O,否则无法升级到 v1.24+。