OCI Runtime Specification 介绍


在上次的 文章 OCI Image Specification 介绍 中我们介绍了 OCI Image Specification 定义的关于镜像如何实现的标准。这篇文章我们接着介绍一下 OCI Runtime Specification。

OCI Runtime Specification 的出发点和 Image Spec 基本一致,它通过制定容器执行的标准规范,使容器的行为和状态与具体的上层软件无关,实现容器的便携性和更好地自动化支持。

满足 OCI Runtime 的标准容器有五个基本的原则(runtime-spec/principles.md at main · opencontainers/runtime-spec):

  • Standard Operations
  • Content-agnostic
  • Infra-agnostic
  • Designed for automation
  • Industrial-grade delivery

术语

为了尽可能准确地明确文章中使用术语的上下文,我们着重介绍一下 Runtime Spec 中涉及到的两个和其上下文较紧密相关的术语, 详细的列表大家可以参考 runtime-spec/glossary.md at main · opencontainers/runtime-spec

Filesystem Bundle

image-20240217204703368

如图所示,Runtime Bundle 包含两部分文件内容。


config.json 文件

Config 文件 是和容器运行相关的配置文件,必须放在 Bundle 根目录下。它包含的典型内容如环境变量信息、挂载(Mounts) 信息、容器进程(process) 信息、和容器生命周期相关的 hooks 等。

Config 文件的生成来源主要有两种:

  • 通过 Runtime 指令生成默认的 config.json 文件: 如 runc spec , 通常用于开发、测试或是定制化配置的场景,生成默认配置后可以在其上进行修改来适配容器场景。
  • 通过 OCI Image config 转化: 转化逻辑可以参考 image-spec/conversion.md at main · opencontainers/image-spec, 我们日常接触的其实主要是这种来源,它具有一致性和可复现,通常与容器生态系统进行了集成(如 Docker 实际上帮我们做了这层转化)。

rootfs 文件夹

rootfs 即容器的 filesystem, 工业使用场景中通过 Image Layers unpack 得到, rootfs 的路径和名称可以在 config.json 文件的 root.path 中进行指定。

Demo

Runtime Bundle 的文件结构相较于 Image Spec 要简单许多,我们不妨尝试按一下步骤动手尝试构建一个 Bundle 。

  1. 准备 Linux 环境(runc 只支持 Linux 环境执行)并进行 runc 准备, 见 runc

  2. 通过 docker export 指令获得容器的 rootfs 并放置在指定文件夹, 这里以 busybox 镜像为例

    $ mkdir rootfs
    $ docker export $(docker create busybox:latest) | tar -C rootfs -xvf -
    
  3. 创建默认的 config.json 文件

    $ runc spec
    

Over, 最终文件结构如下

$ tree -L 2
.
├── config.json
└── rootfs
    ├── bin
    ├── dev
    ├── etc
    ├── home
    ├── lib
    ├── lib64 -> lib
    ├── proc
    ├── root
    ├── sys
    ├── tmp
    ├── usr
    └── var

13 directories, 1 file

Lifecycle

除了文件结构 Bundle, OCI Runtime Spec 还定义了容器状态机及相关的 (Runtime 需要支持的) Operation 操作。

image-20240217211241523

上图展示了容器的生命周期、对应触发指令及容器的响应行为,上图涉及的相关行为说明可以在 runtime-spec/runtime.md at main · opencontainers/runtime-spec 这里找到, 图上涉及的 Env 信息、Hooks 信息、用户制定的容器进程 process 都是在 config.json 文件中指定的。

我们可以在上文初始化好的 bundle 文件夹中创建容器并观察 Lifecycle:

  1. 执行 runc create <container-id>, container-id 可以任意指定, 这里我们指定为 testid

  2. 执行 runc list 观察状态, 这时我们容器的状态为 created

    $ runc list
    ID          PID         STATUS      BUNDLE                                              CREATED                          OWNER
    testid      7094        created     .../busybox_fs   2024-02-17T13:20:13.231362865Z   root
    
  3. 执行 runc start testid 后再执行 runc list, 会发现状态变为了 stopped (我们没有指定 process)

  4. 可以通过 runc state testid 获得 runtime-spec/runtime.md at main · opencontainers/runtime-spec 描述的状态元数据信息, 如

    {
      "ociVersion": "1.1.0+dev",
      "id": "testid",
      "pid": 0,
      "status": "stopped",
      "bundle": "...",
      "rootfs": "...",
      "created": "2024-02-17T14:19:51.642906094Z",
      "owner": ""
    }
    
comments powered by Disqus