返回归档
🛑k8s

Kubelet → CRI → containerd/CRI-O → runc/kata:Kubernetes 容器运行时完整调用链

文章目录

Kubernetes 容器运行时的完整调用链路,从自顶向下(top-down)视角来看,大致是这样的一个分层结构:

kubelet
  ↓ (gRPC 调用)
CRI (Container Runtime Interface)  ← 标准化协议 (v1 API,从 K8s 1.26+ 强制要求)
  ↓ (CRI 实现者,两种主流选择)
[ containerd ]          或          [ CRI-O ]
  ↓ (高层次运行时 → 低层次运行时委托,基于 RuntimeClass 或默认配置)
[ runc ]   或   [ kata-runtime ]   或   [ runsc (gVisor) ]   等 OCI 兼容 runtime
  ↓ (最终执行容器进程)
Linux 内核 (namespaces + cgroups + seccomp + AppArmor 等)

kubelet(节点代理)

  • 位置:Kubernetes 集群每个 Node 上运行的核心组件。
  • 作用:负责管理本节点上的所有 Pod(创建、启动、监控、销毁、状态上报等)。
  • 原理:kubelet 通过 PodManager 组件接收来自 API Server 的 Pod 调度指令,然后把容器相关的操作(创建 Pod Sandbox、拉镜像、启动容器、停止等)转化为 CRI 请求。
  • 关键点:kubelet 不直接操作任何具体容器技术,它只认识 CRI 接口。

CRI(Container Runtime Interface)

  • 本质:一个 gRPC 接口协议(v1 版本),Kubernetes 定义的标准“插件接口”。
  • 作用:让 kubelet 与各种容器运行时解耦,kubelet 只需调用 CRI 方法(如 RunPodSandbox、CreateContainer、StartContainer、PullImage 等),具体怎么实现由下游运行时决定。
  • 原理:kubelet 作为 gRPC 客户端,连接到下游运行时的 CRI socket(Unix socket 或 Windows named pipe)。
  • 现状:从 Kubernetes 1.24 移除 dockershim 后,所有运行时必须原生支持 CRI v1 API。

CRI 的主流实现(高层次容器运行时,High-level Runtime)

目前生产环境 99% 的集群只用下面两种,它们都是轻量、专注 Kubernetes 的实现:

CRI 实现 开发者/维护者 特点与原理简述 默认 socket 路径 2026 年推荐度
containerd CNCF(原 Docker 捐出) 最主流、最轻量。内部有完整的镜像管理、网络、存储、快照等模块,直接实现 CRI 的所有方法,然后委托给低层 runtime 执行容器。 /run/containerd/containerd.sock ★★★★★(默认首选)
CRI-O Red Hat / OpenShift 社区 专为 K8s 设计的最小化实现。只做 CRI 必须的事(Pod Sandbox + 容器生命周期),镜像/存储依赖外部 OCI 项目(如 containers/image/storage),每个容器额外启动一个 conmon 进程来监控日志和退出码。 /var/run/crio/crio.sock ★★★★(非常优秀,轻量备选)

containerd vs CRI-O:containerd 功能更全、更通用;CRI-O 更纯粹、更小、更专注 K8s。

底层 OCI Runtime(Low-level Runtime,真正创建容器进程)

CRI 实现(containerd 或 CRI-O)收到请求后,会根据配置(默认或 RuntimeClass 指定)调用某个 OCI 兼容的低层运行时 来实际 spawn 容器进程。

底层 Runtime 类型 隔离原理与简单说明 典型使用方式 适用场景
runc 进程级隔离(默认) OCI 标准参考实现。直接用 Linux 原生机制(namespaces + cgroups + seccomp)创建隔离的容器进程,共享宿主机内核 containerd/CRI-O 的默认 runtime 性能优先、普通生产环境
kata-runtime VM 级隔离 每个 Pod/容器启动一个轻量级 microVM(默认用 Firecracker,也支持 QEMU 等 hypervisor),容器进程运行在独立的客体内核中,内核级强隔离 通过 RuntimeClass 指定 kata 高安全、多租户、金融/医疗
runsc (gVisor) 用户态沙箱隔离 Google 开源,用户态内核(Go 实现)。容器进程 syscall 被拦截到用户态 gVisor 内核处理,不直接访问宿主机内核 通过 RuntimeClass 指定 gvisor 强安全、需要防逃逸但不想用 VM

RuntimeClass 是 Kubernetes 提供的机制,允许同一个节点支持多种底层 runtime(例如默认 runc + 特殊 Pod 用 kata/gvisor)。

完整调用链路举例(以 containerd + runc 为例,最常见情况)

  1. API Server → kubelet:调度一个 Pod 到此节点
  2. kubelet → CRI (gRPC):调用 RunPodSandbox → CreateContainer → StartContainer 等
  3. containerd(CRI 实现):
    • 拉镜像(如果需要)
    • 准备存储、网络、cgroup 等
    • 生成 OCI 规范 bundle
    • 调用 runc create + runc start 创建并启动容器进程
  4. runc → Linux 内核:真正执行容器进程(应用代码运行在隔离的 namespace 内)
  5. containerd 监控容器状态 → 通过 CRI 上报给 kubelet → kubelet 上报 API Server

如果换成 kata:

  • containerd → kata-runtime(代替 runc)
  • kata-runtime → Firecracker/QEMU → 启动 microVM → VM 内再跑 runc + 容器进程

一句话总结当前(2026 年)主流链路

最常见:kubelet → CRI → containerd → runc

最安全:kubelet → CRI → containerd/CRI-O → kata-runtime → Firecracker microVM

这个分层设计让 Kubernetes 非常灵活:上层(kubelet + CRI)不变,下层可以随意替换(runc → kata → gvisor → 未来其他),这就是 CRI 的最大价值。

image