3. CRI(Container Runtime Interface)接口规范:设计目标、gRPC 接口定义与生命周期
CRI(Container Runtime Interface)是 Kubernetes 与容器运行时之间的核心抽象层。它定义了 kubelet 如何与容器运行时通信,以管理 Pod 和容器的完整生命周期。本章深入剖析 CRI 的设计目标、gRPC 接口定义以及 PodSandbox 与 Container 的生命周期管理。
3.1 CRI 设计目标
CRI 的设计初衷是为了解耦 Kubernetes 控制面与具体的容器运行时实现,使 kubelet 无需关心底层是 Docker、containerd、CRI-O 还是其他运行时。其核心设计目标包括:
| 设计目标 | 说明 | 关键收益 |
|---|---|---|
| 运行时无关性 | kubelet 通过统一的 gRPC 协议调用运行时,不依赖特定运行时的内部 API | 支持 containerd、CRI-O、Kata Containers 等多种运行时 |
| Pod 语义原生支持 | 引入 PodSandbox 概念,将 Pod 作为资源调度的最小单元 | 支持 Pod 级别的网络命名空间、PID 命名空间共享 |
| 生命周期标准化 | 定义清晰的创建、启动、停止、删除等操作接口 | 运行时实现可预测,kubelet 状态机简化 |
| 可扩展性 | 通过 gRPC 的流式接口和可选的扩展点支持未来功能 | 支持容器日志流、执行命令、端口转发等 |
| 安全与隔离 | 接口设计支持安全上下文、Seccomp、AppArmor 等安全策略 | 运行时可以实施细粒度的安全隔离 |
3.2 gRPC 接口定义
CRI 使用 Protocol Buffers(protobuf)定义接口,并通过 gRPC 进行通信。整个接口分为两大服务:RuntimeService 和 ImageService。以下是最核心的接口定义:
3.2.1 RuntimeService(运行时服务)
负责 PodSandbox 和容器的生命周期管理:
service RuntimeService {
// PodSandbox 生命周期
rpc RunPodSandbox(RunPodSandboxRequest) returns (RunPodSandboxResponse) {}
rpc StopPodSandbox(StopPodSandboxRequest) returns (StopPodSandboxResponse) {}
rpc RemovePodSandbox(RemovePodSandboxRequest) returns (RemovePodSandboxResponse) {}
rpc PodSandboxStatus(PodSandboxStatusRequest) returns (PodSandboxStatusResponse) {}
rpc ListPodSandbox(ListPodSandboxRequest) returns (ListPodSandboxResponse) {}
// 容器生命周期
rpc CreateContainer(CreateContainerRequest) returns (CreateContainerResponse) {}
rpc StartContainer(StartContainerRequest) returns (StartContainerResponse) {}
rpc StopContainer(StopContainerRequest) returns (StopContainerResponse) {}
rpc RemoveContainer(RemoveContainerRequest) returns (RemoveContainerResponse) {}
rpc ListContainers(ListContainersRequest) returns (ListContainersResponse) {}
rpc ContainerStatus(ContainerStatusRequest) returns (ContainerStatusResponse) {}
// 容器执行与日志
rpc ExecSync(ExecSyncRequest) returns (ExecSyncResponse) {}
rpc Exec(ExecRequest) returns (ExecResponse) {}
rpc Attach(AttachRequest) returns (AttachResponse) {}
rpc PortForward(PortForwardRequest) returns (PortForwardResponse) {}
rpc ContainerStats(ContainerStatsRequest) returns (ContainerStatsResponse) {}
}
3.2.2 ImageService(镜像服务)
负责容器镜像的拉取、列表和删除:
service ImageService {
rpc ListImages(ListImagesRequest) returns (ListImagesResponse) {}
rpc ImageStatus(ImageStatusRequest) returns (ImageStatusResponse) {}
rpc PullImage(PullImageRequest) returns (PullImageResponse) {}
rpc RemoveImage(RemoveImageRequest) returns (RemoveImageResponse) {}
rpc ImageFsInfo(ImageFsInfoRequest) returns (ImageFsInfoResponse) {}
}
CreateContainerRequest 包含 PodSandbox ID、容器配置(ContainerConfig)、PodSandbox 配置等字段。这些结构定义了 kubelet 与运行时之间的数据契约。
3.3 PodSandbox 与 Container 生命周期
CRI 将 Pod 抽象为 PodSandbox,这是一个隔离的环境(通常对应一个网络命名空间),容器在其中运行。PodSandbox 和 Container 的生命周期是 CRI 的核心流程。
3.3.1 PodSandbox 生命周期
PodSandbox 的生命周期包含以下阶段:
- 创建(RunPodSandbox):kubelet 调用
RunPodSandbox,运行时创建 Pod 级别的隔离环境(如网络命名空间、cgroup 父目录)。 - 运行中:PodSandbox 处于活跃状态,可以创建和运行容器。
- 停止(StopPodSandbox):停止 PodSandbox 内的所有容器,并清理网络资源。
- 删除(RemovePodSandbox):彻底删除 PodSandbox 及其所有资源。
3.3.2 Container 生命周期
容器在 PodSandbox 内创建,其生命周期如下:
- 创建(CreateContainer):在指定的 PodSandbox 内创建容器,但容器进程尚未启动。
- 启动(StartContainer):启动容器的主进程。
- 运行中:容器进程正常运行,kubelet 通过
ContainerStatus监控健康状态。 - 停止(StopContainer):发送信号停止容器进程,支持优雅关闭。
- 删除(RemoveContainer):清理容器的所有资源。
3.3.3 生命周期状态机
下图展示了 PodSandbox 与 Container 的完整生命周期状态转换:
3.4 关键接口调用流程
以下是一个典型的 Pod 创建流程,展示了 kubelet 如何通过 CRI 接口与运行时交互:
- kubelet 调用
RunPodSandbox:创建 Pod 的网络隔离环境,返回 PodSandbox ID。 - kubelet 调用
PullImage(如果镜像不存在):拉取容器镜像。 - kubelet 调用
CreateContainer:传入 PodSandbox ID 和容器配置,创建容器但不启动。 - kubelet 调用
StartContainer:启动容器主进程。 - kubelet 定期调用
ContainerStatus:监控容器健康状态。
RunPodSandbox 和 CreateContainer 通常合并为一次操作,以减少 gRPC 调用次数。这种优化在 CRI 规范中是允许的,只要接口语义保持一致。
3.5 接口调用示例
以下是一个简化的 CreateContainerRequest 的 protobuf 定义示例:
message CreateContainerRequest {
// PodSandbox ID,标识容器所属的 Pod
string pod_sandbox_id = 1;
// 容器配置
ContainerConfig config = 2;
// PodSandbox 配置(用于继承 Pod 级别的设置)
PodSandboxConfig sandbox_config = 3;
}
message ContainerConfig {
// 容器名称
string name = 1;
// 容器镜像
ImageSpec image = 2;
// 容器命令和参数
repeated string command = 3;
repeated string args = 4;
// 工作目录
string working_dir = 5;
// 环境变量
repeated KeyValue envs = 6;
// 挂载卷
repeated Mount mounts = 7;
// 资源限制(CPU、内存)
LinuxContainerResources linux = 8;
// 安全上下文
LinuxContainerSecurityContext security_context = 9;
}
pod_sandbox_id 是必填字段,而 sandbox_config 在某些实现中可以为空。生产环境中建议始终传递完整的配置以避免兼容性问题。
3.6 总结
CRI 接口规范通过 gRPC 定义了 kubelet 与容器运行时之间的标准化通信协议。其核心设计目标包括运行时无关性、Pod 语义原生支持和生命周期标准化。PodSandbox 作为 Pod 的抽象,与 Container 共同构成了 CRI 的生命周期管理模型。理解这些接口和生命周期是构建容器运行时治理控制面的基础。