4. OCI Runtime Spec 深度解析:容器生命周期、状态机、配置规范

OCI Runtime Spec(runtime-spec)定义了容器运行时的标准化行为,是容器引擎(如 containerd、CRI-O)与底层运行时(如 runc、youki)之间的契约。本章从生命周期、状态机与配置规范三个维度进行深度解析。

4.1 容器生命周期:从创建到删除的标准化流程

OCI Runtime Spec 将容器生命周期划分为五个核心阶段,每个阶段对应一个明确的运行时操作。下表总结了各阶段的触发动作与关键状态变化:

阶段 运行时操作 状态变化 关键说明
创建 create 空 → created 根据 config.json 生成容器文件系统与 cgroup,但进程尚未启动
启动 start created → running 执行容器内指定的进程(entrypoint),容器进入运行态
停止 kill / 进程退出 running → stopped 主进程退出或收到终止信号后,容器进入停止态
删除 delete stopped → 空 清理容器资源(文件系统、cgroup、网络命名空间)
查询 state 无状态变更 返回当前容器的完整状态 JSON,用于监控与编排
实践要点: 在 Kubernetes 环境中,kubelet 通过 CRI 调用 containerd,containerd 再调用 runc 的 create、start、kill、delete 等操作。理解生命周期阶段有助于排查 Pod 启动卡在 ContainerCreating 或 Terminating 的问题。

4.2 状态机模型:容器状态的确定性转换

OCI Runtime Spec 定义了严格的状态机,容器在任何时刻只能处于以下四种状态之一:creating、created、running、stopped。状态转换必须遵循单向路径,不允许跳跃或回退。

状态机核心规则:
  • creating 是瞬态,创建成功后立即进入 created。
  • 只有 created 状态可以调用 start 进入 running。
  • running 只能通过进程退出或 kill 进入 stopped。
  • stopped 是终态,只能调用 delete 清理资源。
OCI 容器状态机转换图 creating created running stopped create 成功 start 进程退出 / kill delete 状态转换不可逆:creating → created → running → stopped → 删除
常见陷阱: 某些实现可能允许在 created 状态直接调用 delete(跳过 start),但 OCI 规范明确禁止在 running 状态直接调用 delete。必须先 kill 使容器进入 stopped,再执行 delete。

4.3 配置规范:config.json 的结构与关键字段

OCI Runtime Spec 的核心是 config.json,它定义了容器的完整配置。配置文件采用 JSON 格式,包含以下顶级对象:

  • ociVersion:必填,声明使用的 OCI 规范版本(如 1.0.2)。
  • root:指定容器的根文件系统路径(path)与只读标志(readonly)。
  • mounts:挂载点列表,包含 destination、type、source、options。
  • process:定义容器内运行的进程,包括 args、env、cwd、capabilities、rlimits 等。
  • hostname:容器的主机名。
  • linux:Linux 特有配置,包括 namespaces、cgroupsPath、seccomp、maskedPaths、readonlyPaths。
  • annotations:键值对形式的元数据,用于传递额外信息。

4.4 process 对象详解:容器进程的完整定义

process 对象是 config.json 中最复杂的部分,它决定了容器内进程的执行环境。以下是一个典型的 process 配置示例:

{
  "process": {
    "args": ["/bin/sh", "-c", "echo Hello OCI"],
    "env": [
      "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
      "TERM=xterm"
    ],
    "cwd": "/",
    "capabilities": {
      "bounding": ["CAP_NET_RAW", "CAP_CHOWN"],
      "effective": ["CAP_NET_RAW", "CAP_CHOWN"],
      "inheritable": [],
      "permitted": ["CAP_NET_RAW", "CAP_CHOWN"],
      "ambient": []
    },
    "rlimits": [
      {"type": "RLIMIT_NOFILE", "hard": 1024, "soft": 1024}
    ],
    "noNewPrivileges": true,
    "apparmorProfile": "",
    "selinuxLabel": "",
    "oomScoreAdj": 0
  }
}
关键字段说明:
  • args:进程的入口命令与参数,第一个元素必须是可执行文件路径。
  • capabilities:细粒度权限控制,推荐使用白名单策略,仅授予必要权限。
  • rlimits:资源限制,如文件描述符数量、进程数等。
  • noNewPrivileges:设置为 true 可防止进程通过 setuid 等方式提权。

4.5 Linux 特有配置:命名空间、Cgroups 与安全策略

OCI Runtime Spec 的 linux 对象提供了 Linux 容器特有的隔离与资源控制能力。下表总结了核心配置项:

配置项 类型 说明 典型值
namespaces 数组 指定容器使用的命名空间类型(pid、net、mnt、uts、ipc、user、cgroup) [{"type": "pid"}, {"type": "network"}]
cgroupsPath 字符串 容器的 cgroup 路径,用于资源限制与监控 /kubepods/besteffort/pod123
seccomp 对象 系统调用过滤规则,默认使用 SCMP_ACT_ERRNO 拒绝未允许的调用 {"defaultAction": "SCMP_ACT_ALLOW"}
maskedPaths 数组 将宿主机敏感路径挂载为 /dev/null,防止容器读取 ["/proc/kcore"]
readonlyPaths 数组 将指定路径设置为只读,增强安全性 ["/proc/sys"]
config.json 配置结构层次图 config.json ociVersion root process mounts linux args env capabilities rlimits namespaces cgroupsPath seccomp config.json 是 OCI 运行时的唯一配置入口,所有容器行为由此文件驱动

4.6 生命周期与配置的关联:从 config.json 到状态转换

config.json 的配置直接影响容器的生命周期行为。例如:

  • process.args 决定了容器启动后运行的进程;如果该进程立即退出,容器会迅速从 running 进入 stopped。
  • linux.namespaces 配置错误(如缺少 pid 命名空间)可能导致 create 阶段失败,状态停留在 creating 并返回错误。
  • linux.seccomp 如果过于严格,可能阻止容器内进程执行必要的系统调用,导致进程异常退出。
验证建议: 在测试环境中,使用 runc state <container-id> 实时观察容器状态变化,并结合 config.json 的配置项进行故障注入测试,验证状态机转换的健壮性。

4.7 本章小结