暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

轻量级的 OCI 运行时 — Crun

ProdanLabs 2021-10-18
6869

Open Container Initiative (OCI)  是 Docker 在 2015 年不情愿发起的一个组织,旨在制定开放的标准化容器技术。在 OCI 中,包含了 OCI 运行时规范、容器镜像格式规范和容器注册规范,符合 OCI 标准的运行时也可以称为 OCI 运行时。 OCI 运行时接收 json 文件的容器配置,在命令行启动容器的创建、启动和停止。


实际上,OCI 运行时就是一个命令行小工具,不需要通过 docker 引擎或者符合 kubernetes CRIContainer Runtime Interface标准的容器运行时软件,直接运行容器。

01

kubernetes 底层生态系统现状

事实上 Kubernete 本身不具备创建容器的能力,是通过 kubelet 组件调用容器运行时 API 接口和命令来创建容器,Kubernete 与 容器运行时的关系是历史性的,也很复杂。但是随着 Kubernete 弃用 Docker ,目前主流的运行时主要是 containerd 和 CRI-O。


containerd 从 Docker 项目中分离出来,使 Docker 更加模块化。当你安装 Docker 时,它也会安装 containerd,因为 Docker 本身也是使用 containerd 的。containerd 通过内部的 cri 插件实现了 Kubernetes 容器运行时接口 (CRI) 。

CRI-O 是在 CRI 标准提出后,RedHat 构建的一个更简单、仅为 Kubernetes 所用的运行时,它实现了一个最小的 CRI 接口。


目前广泛使用的 OCI 运行时是 runC它是 Docker 公司基于 libcontainer 的基础上封装捐献出来的,作为 OCI 的参考实现。有了 OCI 标准,Docker 无法再垄断容器技术,也涌出了一些 runC 替代方案,比如:

来自 Katacontainers 项目的 kata-runtime ,轻量级 VM(硬件虚拟化)
来自 Google 的 runsc (gVisor),可以运行独立内核的容器。

还有用 C 编写的轻量级 OCI 运行时 crun。(runC 是用 Go 编写的



在上图中 OCI 运行时看起来像是容器的父进程,但实际上 OCI 运行时在容器启动后就退出了,容器的父进程由一个独立的 containerd-shim 或 conmon 进程接管。


02

runC VS Crun

Go 对计算的 fork/exec 模型没有很好的支持,Go 的线程模型期望程序分叉第二个进程,然后立即执行。但是,OCI 容器运行时预计会分叉容器中的第一个进程。所以,Go 可能不是完成这项任务的最佳编程语言。C 默认情况下不是多线程的,而是围绕 fork/exec 模型构建和设计的。它可以以更简洁的方式处理 OCI 运行时的这一部分。C 也是一种低得多的语言,可以很好地与 Linux 内核交互。最后,C 是轻量级的,因此与 Go 相比,它可以编译成更小的尺寸并使用更少的内存。


根据社区的测试结果,不管是用时还是内存,Crun 都比 runC 好,感兴趣的读者可以去看看。 https://github.com/containers/crun


bucketbench 是一个符合 CRI 标准的容器运行时基准测试工具。 这里作者使用 bucketbench 来测试实际的差距


测试环境

服务器配置
4核8G
操作系统Ubuntu 20.04.3 LTS
容器运行时
crio  1.22.0
OCI 运行时
runc 1.0.2 、runc 0.20.1


安装 bucketbench

# 需要安装 golang
git clone https://github.com/estesp/bucketbench
make binary


这里测试参数很简单,5 个线程 ,循环 2 次,执行 run/stop/delete 操作

cat crio.yaml 
---
name: CRICrio
image: docker.io/polinux/stress:latest
command: stress --cpu 1 --io 1 --vm 1 --vm-bytes 128M --timeout 10s
detached: true
drivers:
-  type: CRI
   threads: 5
   iterations: 2
   clientpath: /var/run/crio/crio.sock
commands:
- run
- stop
- delete


测试

# 确认 OCI 运行时
crio-status config | egrep "default_runtime|runtime_path" 

time ./bucketbench --log-level=debug    run  -b crio.yaml 


runc 的结果


切换 crun,重启 cri-o

cat /etc/crio/crio.conf.d/10-crun.conf 
[crio.runtime]
default_runtime = "crun"

[crio.runtime.runtimes.crun]
allowed_annotations = [
    "io.containers.trace-syscall",
]


执行

time ./bucketbench --log-level=debug    run  -b crio.yaml 


crun 结果


对比结果看,crun 操作时 ,crun 平均值明显好于 runC,stop/delete 其实总体也相差不大。



测试的方式方法仅供参考,有环境的读者的可以去测试验证下。crun 的详细介绍文档见 

https://www.redhat.com/sysadmin/introduction-crun

文章转载自ProdanLabs,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论