Ubuntu 22.04 安装 crun 指南

在 Ubuntu 22.04 上通过 apt 在线安装与官方 GitHub 源码离线编译两种方式部署 crun 1.x OCI 运行时,并完成 crun spec/run/exec 最小 rootfs 实测验证与 Podman runtime 配置。

cruncrun运行时安装部署Ubuntu 22.042026/10/09

Ubuntu 22.04 安装 crun 指南

目标:在 Ubuntu 22.04 上安装并验证 crun(OCI 标准、C 语言实现、比 runc 更轻量、依托 cgroups v2 的低层运行时,也是 Podman 的默认运行时之一)。本文覆盖 apt 在线安装与官方 GitHub release 源码离线编译两种方案,并用最小 rootfs 对 crun run/exec 做了真实回显验证。已在 Ubuntu 22.04.5 LTS(x86_64)实测通过。

💡 定位说明:crun 是「低层」运行时(low-level runtime),本身不管理镜像、不提供长驻守护进程,日常主要由 Podman、Buildah(以及 CRI 场景)按 OCI 接口调用。本文只负责在系统里安装好 crun 二进制并验证它能把 OCI bundle 跑起来。

一、环境信息

  • 操作系统:Ubuntu 22.04.5 LTS(jammy)
  • 架构:x86_64(amd64)
  • 内核 / cgroup:Linux cgroups v2(unified hierarchy)
  • 在线渠道版本:crun 0.17+dfsg-1.1ubuntu0.1(Ubuntu universe 仓库)
  • 离线渠道版本:crun 1.20(官方 GitHub release 源码编译)
  • 同机对比对象:runc 1.3.4-0ubuntu1~22.04.1(apt 安装)
  • crun 可执行文件:/usr/bin/crun
  • crun 状态目录(bundle/rootfs):/opt/crun-bundle/
  • 所需权限:root(crun 运行时需要创建命名空间与操作 cgroup v2)

⚠️ 前置:crun run/create 需要 root 权限来创建 mount/pid/user 等命名空间并挂载/写入 cgroup v2。请使用 root 账号(或具有完整 sudo 的账号,密码示例 q1w2e3r4)执行本文命令。

二、版本选型

crun 是基于 C 语言、遵循 OCI Runtime Spec 的运行时,与 runc(同源自 runc 的 Go 实现)竞争同一生态位,但更强调轻量和低内存占用。

2.1 版本线

  • 主线/稳定版:crun 1.x(如 1.20),由 containers/crun 维护,cgroups v2、systemd-cgroup、SELinux/AppArmor、seccomp、EBPF 等能力默认编译启用。
  • Ubuntu 仓库版本:universe 仓库长期停留在 0.17+dfsg(dfsg 为 Debian 的去重打包后缀)。它功能完整、开箱即用,但比上游 1.x 旧。

两者都能正常完成 OCI 启动,选择建议:能联网、不追求最新 → 用 apt 的 0.17 最省事;需要上游最新特性 / 断网交付 → 用源码编译 1.20。

2.2 cgroups v2 与低层运行时的关系

  • 现代 Ubuntu(含 22.04)默认全套启用 cgroups v2,crun 直接基于 cgroups v2 统一层级做资源限制,不依赖 systemd 也能工作(配合 systemd 时可用 --systemd-cgroup)。
  • crun 没有常驻守护进程:每次调用只是 create/start/run/delete 等进程级动作,非常适合被上层工具(Podman、kubelet/CRIO)拉起来后退出。

2.3 与 Podman / 其他运行时关系

  • Podman 默认以 crun 为其低层运行时(可从 Podman 的 --runtime 或配置文件切换,也可切回 runc)。
  • 本机同装 runc 用于对照版本与差异,不影响 crun 正常工作。

版本对照表:

项crun(apt 0.17)crun(源码 1.20)runc(apt 1.3.4)
实现语言CCGo
OCI Runtime Spec1.0.01.0.0(上限 1.1.0+dev)1.2.1
cgroups v2支持支持支持
安装方式apt install crun源码编译apt install runc
适用快速开箱上游新特性 / 断网对照 / 部分上层默认

三、在线安装(方案 A:apt)

Ubuntu 22.04 的 universe 仓库自带 crun,联网状态下一行即可装好。

3.1 更新源并安装

# Ubuntu server 服务器,root 执行
apt-get update
apt-get install -y crun

实测回显(安装摘要):

Selecting previously unselected package crun.
Preparing to unpack .../crun_0.17+dfsg-1.1ubuntu0.1_amd64.deb ...
Unpacking crun (0.17+dfsg-1.1ubuntu0.1) ...
Setting up crun (0.17+dfsg-1.1ubuntu0.1) ...

💡 apt 会自动带入运行依赖:libc6、libcap2、libseccomp2、libsystemd0、libyajl2。装完的 crun 位于 /usr/bin/crun。

3.2 验证在线版本

crun --version

实测回显:

crun version 0.17
commit: 0e9229ae34caaebcb86f1fde18de3acaf18c6d9a
spec: 1.0.0
+SYSTEMD +SELINUX +APPARMOR +CAP +SECCOMP +EBPF +YAJL

四、离线 / 源码安装(方案 B:官方 GitHub release 源码编译)

断网环境,或需要上游 1.x 新特性时,用官方 GitHub release 提供的源码 tar.gz 编译安装。

4.1 准备工作:编译依赖

apt-get update
apt-get install -y build-essential automake autoconf libtool pkg-config \
  libseccomp-dev libcap-dev libyajl-dev libjson-c-dev libsystemd-dev
  • autoconf/automake/libtool:运行 autogen.sh 生成 configure。
  • libseccomp-dev:seccomp 过滤。
  • libyajl-dev:JSON 解析(crun/libocispec 依赖 yajl)。
  • libjson-c-dev:libocispec 生成的头部依赖 json-c。
  • libsystemd-dev:systemd-cgroup 支持。

4.2 获取源码(含 libocispec 子模块)

crun 源码依赖其 libocispec(OCI schema 的 C 绑定,内含 runtime-spec/image-spec/yajl 子模块),而 GitHub 的 release tar.gz 不打包子模块源码。有两种取法:

方式一(推荐,直接拿到子模块)——用 git 拉取 release 分支的完整源码树:

cd /opt
git clone --recursive --branch 1.20 \
  https://github.com/containers/crun.git crun-src

方式二(下载官方 release tar.gz,再单独补子模块)——先下载 crun-1.20.tar.gz 解压,再按需把匹配的 libocispec(及其 runtime-spec、image-spec、yajl)源码放进 crun-1.20/libocispec/ 对应子目录下即可。本文实测采用方式二,标准目录:

/opt/crun-1.20/
├── autogen.sh
├── configure.ac
└── libocispec/          # crun 依赖的子模块
    ├── runtime-spec/    # OCI Runtime Spec schema
    ├── image-spec/      # OCI Image Spec schema
    ├── yajl/            # 打包的 yajl
    └── src/ocispec/     # 生成的 C 绑定源码

4.3 准备版本号文件

从无 .git 的 tar.gz 编译时,autotools 无法用 git describe 确定版本号,crun --version 会显示 version UNKNOWN。解决办法:在源码根目录放置 .tarball-version 后重新 autogen:

cd /opt/crun-1.20        # 或 /opt/crun-src
echo "1.20" > .tarball-version

4.4 生成配置并编译安装

cd /opt/crun-1.20
./autogen.sh                 # 生成 ./configure
./configure --prefix=/usr    # 安装到 /usr/bin/crun
make -j$(nproc)              # 编译
make install                 # 安装到 /usr
  • --prefix=/usr 下,二进制装到 /usr/bin/crun、man 页装到 /usr/share/man/man1/crun.1。
  • 若此前已通过 apt 装过 crun,make install 会覆盖 /usr/bin/crun(体现在版本号从 0.17 变为 1.20)。

实测编译尾部回显:

  CCLD     libcrun.la
  CCLD     crun
make[2]: Leaving directory '/opt/crun-1.20'
make[1]: Leaving directory '/opt/crun-1.20'

make install 关键回显:

libtool: install: /usr/bin/install -c crun /usr/bin/crun
 /usr/bin/install -c -m 644 crun.1 '/usr/share/man/man1'

4.5 验证源码版本

crun --version

实测回显:

crun version 1.20
commit: 1.20
rundir: /run/crun
spec: 1.0.0
+SYSTEMD +SELINUX +APPARMOR +CAP +SECCOMP +EBPF +YAJL

💡 与 apt 版相比,源码版多出 rundir: /run/crun 一行(1.x 新增),并支持 crun features(输出 ociVersionMax: 1.1.0+dev)等新命令。

4.6 与已装 runc 对比

若同时装了 runc,可在同一台机器直接对照:

runc --version

实测回显:

runc version 1.3.4-0ubuntu1~22.04.1
spec: 1.2.1
go: go1.24.4
libseccomp: 2.5.3

两者都遵循 OCI 接口作低层运行时;runc 自带更高 OCI spec(1.2.1),crun 由 C 实现、内存占用更小。

五、crun 配置

5.1 无守护进程、无独立配置文件

crun 采用"单次执行即退"模型:没有长驻 daemon,也没有自己是"面向全局"的独立配置文件。它的全部运行参数来自 OCI bundle 目录里的 config.json(OCI Runtime Spec),由调用方(Podman/CRI)或 crun spec 生成。

  • 默认 bunde 目录:当前目录(可用 -b DIR 指定)。
  • 状态/运行目录:/run/crun(crun --version 中的 rundir),存放运行中的容器状态。

5.2 生成默认配置:crun spec

在一个 bundle 目录里生成默认 config.json:

mkdir -p /opt/crun-bundle/rootfs
cd /opt/crun-bundle
crun spec

crun spec 帮助(实测):

Usage: spec [OPTION...] spec
OCI runtime

  -b, --bundle=DIR       path to the root of the bundle dir (default ".")
  -f, --file=PATH        destination file
      --rootless         spec for the rootless case

默认生成的关键字段(实测):

config.json 字段实测默认值说明
root.pathrootfs相对 bundle 的 rootfs 目录(只读 readonly: true)
process.args["sh"]首进程命令
process.terminaltrue默认申请 TTY
mounts7 条/proc、/sys、/dev 等基础挂载

5.3 关键字段说明(cgroups v2)

  • root:容器根文件系统,指向 rootfs。
  • process:首进程 args、env、cwd、terminal。
  • mounts:挂载点(/proc、/sys、/dev/pts 等)。
  • linux.cgroupsPath:cgroup v2 归属路径。不设时 crun 会放到默认层级;配 --systemd-cgroup 时交给 systemd 管理 scope。
  • linux.resources:CPU/内存/IO 限制,作用于 cgroups v2。

⚠️ 非 rootless 场景 crun run 需要 root:它要创建命名空间并把 cgroup v2 控制器写入 /sys/fs/cgroup。rootless(crun spec --rootless + user namespaces)需内核与子用户配置,不在本文展开。

5.4 用作 Podman 的默认运行时

在 /etc/containers/containers.conf 的 [engine.runtimes] 下把 crun 与可执行路径绑定,并作为默认 runtime(engine 段的 runtime = "crun" 即显式置为默认):

[engine.runtimes]
crun = [
  "/usr/bin/crun",
]

[engine]
runtime = "crun"

⚠️ 需装好 podman 本体后该配置才生效;crun 本身不依赖该文件。装好 Podman 后可用 podman info --format '{{.Host.OCIRuntime.Name}}' 核对当前生效的低层运行时名称。

六、验证(crun run / exec 实测)

用最小 rootfs 真实跑一次 crun,验证它能完成 OCI 启动。

6.1 准备最小 rootfs(debootstrap)

apt-get install -y debootstrap
mkdir -p /opt/crun-bundle
debootstrap --variant=minbase --arch=amd64 \
  jammy /opt/crun-bundle/rootfs http://archive.ubuntu.com/ubuntu

⚠️ 前置:debootstrap 需要能访问 archive.ubuntu.com。rootfs 就绪后 /opt/crun-bundle/rootfs/bin/sh -> dash 即说明核心用户态已就位。

6.2 生成并微调 config.json

cd /opt/crun-bundle
crun spec

把首进程改成能打印身份的一次性命令(TTY 关掉、rootfs 可写),便于非交互回显:

cd /opt/crun-bundle
python3 - <<'PY'
import json
d=json.load(open("config.json"))
d["process"]["terminal"]=False
d["process"]["args"]=["/bin/sh","-c","echo HELLO-FROM-CRUN; cat /etc/os-release | head -2; hostname"]
d["root"]["readonly"]=False
json.dump(d,open("config.json","w"),indent=2)
PY

6.3 crun run(一次性运行)

cd /opt/crun-bundle
crun run real-test

实测回显(容器内真实执行了 Ubuntu 22.04 用户态):

HELLO-FROM-CRUN
PRETTY_NAME="Ubuntu 22.04 LTS"
NAME="Ubuntu"
crun

💡 hostname 输出 crun,bundle 内 rootfs 确实是 Ubuntu 22.04 的 /bin/sh 在 crun 管理的命名空间里运行。

6.4 crun create / start / list / state / exec / kill / delete(生命周期)

把首进程改为常驻,测试完整生命周期。先把 config.json 首进程改成 /bin/sleep 300,然后:

cd /opt/crun-bundle
crun create long-test
crun list
crun state long-test
crun start long-test
crun ps long-test

实测回显(crun list):

NAME      PID    STATUS   BUNDLE PATH        CREATED                        OWNER
long-test 51185  created  /opt/crun-bundle 2026-10-09T09:52:36.330672Z    root

crun state long-test(节选):

{
  "ociVersion": "1.0.0",
  "id": "long-test",
  "pid": 51185,
  "status": "created",
  "bundle": "/opt/crun-bundle",
  "rootfs": "rootfs",
  "systemd-scope": "",
  "owner": "root"
}

crun start 后,crun list 中 STATUS 变为 running,crun ps 显示进程 PID。

再进进程内执行命令:

crun exec long-test /bin/sh -c "echo EXEC-OK; id; cat /etc/os-release | head -1"

实测回显:

EXEC-OK
uid=0(root) gid=0(root) groups=0(root)
PRETTY_NAME="Ubuntu 22.04 LTS"

最后关停并清理:

crun kill long-test 9
crun delete -f long-test
crun list          # 此时列表为空

6.5 工具速查:crun 主命令与常用参数

crun --help(实测)列出全部子命令:

COMMANDS:
        create      - create a container
        delete      - remove definition for a container
        exec        - exec a command in a running container
        features    - show the enabled features
        list        - list known containers
        kill        - send a signal to the container init process
        ps          - show the processes in the container
        run         - run a container
        spec        - generate a configuration file
        start       - start a container
        state       - output the state of a container
        pause       - pause all the processes in the container
        resume      - unpause the processes in the container
        update      - update container resource constraints

      --cgroup-manager=MANAGER   cgroup manager
      --debug
      --log=FILE
      --log-level=LEVEL
      --root=DIR
      --systemd-cgroup           use systemd cgroups
  -v, -V, --version

crun run 常用参数(实测):

  -b, --bundle=DIR        container bundle (default ".")
  -d, --detach            detach from the parent
      --keep              do not delete the container after it exits
      --no-pivot          do not use pivot_root
      --pid-file=FILE     where to write the PID of the container

七、升级 / 卸载

7.1 升级

  • apt 渠道:apt-get update && apt-get upgrade crun(跟随 Ubuntu 仓库版本)。
  • 源码渠道:拉新 release(如 1.21)重复四、4.2~4.4 的 make && make install,会覆盖旧版 /usr/bin/crun。

7.2 卸载

  • apt 安装版:
apt-get remove -y crun
# 卸载并清除配置文件
apt-get purge -y crun
apt-get autoremove -y
  • 源码编译版(make install 进 /usr/bin 的二进制):
# 在源码目录反安装
cd /opt/crun-1.20
make uninstall
# 或直接删除二进制与 man 页
rm -f /usr/bin/crun /usr/share/man/man1/crun.1

💡 运行中残留状态在 /run/crun(临时目录,重启自动清空);bundle/rootfs 在 /opt/crun-bundle,需要时自行 rm -rf /opt/crun-bundle。

八、常见问题

8.1 编译报错 Package requirements (json-c >= 0.14) were not met

现象:./autogen.sh(libocispec 内)报找不到 json-c。

定位:config.libocispec 需要 pkg-config 能查到 json-c。

解决:

apt-get install -y libjson-c-dev

8.2 编译报错 fatal error: git-version.h 或 crun version UNKNOWN

现象:make 报 git-version.h: No such file or directory;或装完 crun --version 显示 version UNKNOWN。

定位:源码来自无 .git 的 tar.gz,autotools 无法 git describe 得到版本号。

解决:四、4.3 中写入 .tarball-version 后重新 ./autogen.sh && ./configure 再编译,版本即正常显示 1.20。

8.3 crun run 报权限 / cgroup 相关错误

现象:crun run 报命名空间或 /sys/fs/cgroup 写入失败。

定位:缺少 root 权限或 cgroup 控制器不可写。

解决:用 root 执行;确认系统为 cgroups v2(/sys/fs/cgroup/cgroup.controllers 存在)。rootless 需另行准备 user namespaces 与子用户映射。

8.4 crun 0.17 与 1.20 的区别要不要管

现象:apt 装的是 0.17,官方是 1.x。

说明:0.17 功能完整,crun run/exec 行为一致;1.x 增加 rundir 行与 features 命令、spec 上限提到 1.1.0+dev。多数日常使用两者等价,无需强求统一。

8.5 与 runc 能否共存

现象:想同时保留 runc 与 crun。

说明:完全可以。两者独立二进制、各自按 OCI 接口工作;上层工具在配置里指定用哪个(如 Podman 的 runtime = "crun" 或 --runtime)。删 crun 不影响 runc。

九、参考链接

  • crun 官方仓库(源码、release):https://github.com/containers/crun
  • crun 文档 / man:https://github.com/containers/crun/blob/main/README.md
  • OCI Runtime Spec:https://github.com/opencontainers/runtime-spec
  • Podman containers.conf 说明(配置 crun 为默认运行时):https://github.com/containers/common/blob/main/docs/containers.conf.5.md
  • Ubuntu 软件源 crun 包信息:https://packages.ubuntu.com/jammy/crun
Ubuntu 22.04 安装 crun 指南 - Quzuo