2. 容器运行时基础

2.1 容器运行时定义

容器运行时(Container Runtime)是负责管理容器生命周期(创建、启动、停止、删除)以及容器镜像拉取、挂载、网络配置的核心软件组件。它是容器化工作负载在宿主机上实际执行的底层引擎,直接与操作系统内核交互,通过 Linux Namespace 和 Cgroups 实现资源隔离与限制。

核心职责:
  • 镜像管理: 拉取、存储、解包容器镜像,构建容器的根文件系统。
  • 容器生命周期: 创建、启动、停止、删除容器进程。
  • 资源隔离: 通过 Namespace(PID、Network、Mount、UTS、IPC、User)实现进程、网络、文件系统等维度的隔离。
  • 资源限制: 通过 Cgroups(CPU、内存、磁盘 I/O、网络带宽)控制容器资源使用上限。
  • 存储与网络: 挂载数据卷、配置容器网络接口(veth pair、bridge)。

在 Kubernetes 生态中,容器运行时通过 CRI(Container Runtime Interface) 与 kubelet 交互。kubelet 通过 gRPC 调用 CRI 接口,运行时负责执行具体的容器操作。

容器运行时在 Kubernetes 中的位置 kubelet CRI (gRPC) 容器运行时 (Container Runtime) Linux Namespace Linux Cgroups 宿主机操作系统内核

2.2 OCI 规范

OCI(Open Container Initiative) 是 Linux 基金会下的开放标准组织,旨在制定容器格式和运行时的行业规范。OCI 规范由三个核心部分组成:

规范名称 版本 核心内容
OCI Image Spec v1.1 定义容器镜像的格式、元数据(manifest、config、layer)、分发流程。确保镜像在不同运行时之间可移植。
OCI Runtime Spec v1.1 定义容器运行时的行为标准,包括 config.json(Namespace、Cgroups、挂载点、环境变量、进程参数)以及生命周期钩子(prestart、poststart、poststop)。
OCI Distribution Spec v1.1 定义容器镜像的推送、拉取、存储 API 标准,基于 HTTP/HTTPS 协议,支持 registry 间同步。
OCI 规范的意义: 任何符合 OCI Runtime Spec 的运行时(runc、crun、gVisor、Kata Containers)都可以被 containerd、CRI-O 等 CRI 实现调用,实现“一次构建,到处运行”。OCI 规范是容器生态互操作性的基石。

2.3 主流运行时对比

根据安全隔离级别和性能特征,主流容器运行时可分为三类:

  • 标准运行时: 直接共享宿主机内核,通过 Namespace/Cgroups 隔离。代表:runc、crun。
  • 安全运行时(沙箱运行时): 为每个容器或 Pod 启动一个轻量级虚拟机,提供硬件级隔离。代表:Kata Containers、Firecracker。
  • 半虚拟化运行时: 在用户态实现系统调用拦截和内核模拟,提供类似虚拟机的隔离但性能优于全虚拟化。代表:gVisor。
主流容器运行时架构对比 runc / crun 共享宿主机内核 Namespace + Cgroups 性能损耗极低 隔离性弱(共享内核) gVisor 用户态内核 (Sentry) 系统调用拦截/代理 性能损耗中等 隔离性较强 Kata Containers 轻量级虚拟机 硬件虚拟化 (KVM) 性能损耗较高 隔离性最强 隔离性与性能的权衡 runc/crun 性能最佳但隔离最弱 → gVisor 折中 → Kata 隔离最强但性能损耗最大

2.4 运行时详细对比

特性 runc crun gVisor Kata Containers
实现语言 Go C Go Go + Rust (agent)
隔离机制 Namespace + Cgroups Namespace + Cgroups 用户态内核 (Sentry) + 系统调用拦截 KVM 虚拟机 + 轻量内核
安全边界 共享宿主机内核 共享宿主机内核 用户态内核隔离 硬件虚拟化隔离
启动延迟 极低(毫秒级) 极低(毫秒级,比 runc 快 30-50%) 中等(百毫秒级) 较高(秒级,需启动 VM)
内存开销 极低(每个容器约 1-2 MB) 极低(每个容器约 0.5-1 MB) 中等(每个容器约 10-30 MB) 较高(每个 Pod 约 100-200 MB)
系统调用兼容性 完全兼容(直接调用宿主机内核) 完全兼容(直接调用宿主机内核) 部分兼容(约 70% 系统调用被拦截,部分需代理到宿主机) 完全兼容(运行完整 Linux 内核)
典型场景 通用容器、CI/CD、开发环境 高密度部署、边缘计算、延迟敏感场景 多租户环境、不可信工作负载、安全敏感场景 强隔离需求、金融/合规场景、运行不可信代码
OCI 合规 是(参考实现) 是 是(通过 runsc 实现) 是(通过 containerd-shim-kata-v2)
关键选择依据: 在 SLO 违约后的沙箱隔离处置场景中,如果原工作负载运行在 runc 上且 SLO 违约是由于安全事件(如容器逃逸、内核漏洞利用)导致,则必须将工作负载迁移到 Kata Containers 或 gVisor 沙箱运行时。如果 SLO 违约是由于资源争抢导致,则优先考虑 crun(降低延迟)或调整资源配额,而非切换运行时。

2.5 运行时与 CRI 的集成关系

Kubernetes 通过 CRI 与容器运行时解耦。常见的 CRI 实现(containerd、CRI-O)内部通过 shim 进程管理每个容器的运行时实例。shim 负责将 CRI 调用转换为 OCI Runtime Spec 调用,并保持容器标准输入/输出/错误流的连接。

CRI 与容器运行时的集成架构 kubelet CRI containerd / CRI-O containerd-shim-runc containerd-shim-kata containerd-shim-runsc runc / crun Kata Containers gVisor (runsc)
运行时切换方式: 在 Kubernetes 中,可以通过 RuntimeClass 资源对象为不同 Pod 指定不同的运行时。例如,为高安全需求的 Pod 指定 runtimeClassName: kata,为普通 Pod 使用默认的 runc。RuntimeClass 是 SLO 违约后沙箱隔离处置的关键控制面 API。
# RuntimeClass 示例:为 Pod 指定 Kata Containers 运行时
apiVersion: node.k8s.io/v1
kind: RuntimeClass
metadata:
  name: kata
handler: kata
---
apiVersion: v1
kind: Pod
metadata:
  name: secure-pod
spec:
  runtimeClassName: kata
  containers:
  - name: app
    image: nginx:latest

2.6 本章小结

  • 容器运行时 是容器生命周期的直接管理者,通过 OCI 规范与上层 CRI 解耦。
  • OCI 规范 包含 Image Spec、Runtime Spec、Distribution Spec,确保容器生态的互操作性。
  • runc/crun 提供极致性能但隔离性弱;gVisor 提供用户态内核隔离,性能折中;Kata Containers 提供硬件虚拟化隔离,安全性最高。
  • 在 SLO 违约后的沙箱隔离处置中,根据违约原因(安全事件 vs 资源争抢)选择合适的运行时切换策略。
  • RuntimeClass 是 Kubernetes 控制面实现运行时切换的标准 API,无需修改 Pod 定义即可动态调整隔离级别。