开源之夏总结runk:基于Rust的OCI runtime实现

电子说

1.2w人已加入

描述

这是今年开源之夏活动中,陈轶阳同学参加 runk 项目的总结文档,主要介绍了 runk 的由来,以及如何基于现有 kata agent 组件来实现一个标准的 OCI runtime。

1. runk背景

kata-agent是在虚拟机 (VM) 中运行的进程,作为管理容器和在这些容器中运行的进程的主管。换句话说,kata-agent 是 VM 内部的一种“低级”容器运行时,因为agent根据 OCI 运行时规范生成和运行容器。但是,kata-agent 没有运行时规范中定义的 OCI 命令行界面 (CLI)。 kata-runtime 提供了 Kata Containers 运行时组件的 CLI 部分,但 kata-runtime是一个容器运行时,用于创建在主机上运行的硬件虚拟化容器。

ManaSugi[1]发起了实验性质的 runk 项目。runk 是一个基于 Rust 的标准 OCI 容器运行时,它管理传统的容器。 runk 旨在成为现有 OCI 兼容容器运行时的替代方案之一。 kata-agent具有容器运行时所需的大部分功能,并且由于使用 Rust 语言实现,因此具有高性能和低内存占用的特点。runk 利用 kata-agent 的机制来避免重新发明轮子。

目前,runk仍然是实验性质的工具,有一部分功能还有待实现。根据 ManaSugi 提交的 Proposal[2],截止到目前,runk支持的功能如下:

Feature Status
crictl  
Docker  
Podman  
OCI commands (state/create/start/kill/delete)  
run command  
spec command  
exec command  
list command  
ps command  
pause/resume commands  
update command  
events command  
init command  
checkpoint/restore commands (CRIU)  
Foreground terminal mode See therunc modes[3].
Cgroups v1  
Cgroups v2  
Systemd Cgroups  
Namespaces  
no pivot_root  kata-agent 支持该功能,但是runk还不支持。
Capabilities  
Seccomp  
AppArmor WIP on#2227[4]
SELinux  
Rlimit  
Readonly path  
Masked path  
Hooks  
Rootless  

我在这次CCF开源夏令营中新增实现的功能有list/ps/exec/pause/resume子命令。

2. 新增子命令的作用和实现

2.1 list

list子命令用于列出当前运行的容器,列出的基本信息包括容器ID、进程PID、状态、Bundle、创建时间、所有者。运行效果如下:

 

$ sudo runk list container1
ID  PID  STATUS   BUNDLE                                    CREATED                            OWNER
k1  0    stopped  /home/cyyzero/workspace/test/runk/bundle  2022-11-04 07:41:47.489394784 UTC  root

 

实现方式是遍历root目录下的所有子目录,然后读取state.json文件,解析出容器的基本信息并打印输出。

2.2 ps

ps子命令用于列出容器内的进程信息。运行效果如下:

 

$ sudo runk ps container1
  PID TTY          TIME CMD
    1 ?        00:00:00 sh
    2 ?        00:00:00 sleep
    3 pts/0    00:00:00 ps

 

实现方式是首先通过cgroup来获取容器内所有的pid;然后利用ps -ef命令搜集操作系统上所有进程的信息。最后通过pid的比对,将容器进程相关的信息打印出来。

2.3 exec

exec子命令用于在容器内执行一个新的进程,它允许指定启动进程的命令行参数、环境变量、cwd等信息。新进程会通过setns系统调用来加入到容器的namesapce中,同时也会加入容器所在的cgroup进程集合。

它与已实现的create和run命令类似,依赖rustjail包里的LinuxContainer类。LinuxContainer类是agent启动容器的核心类,针对每个容器会生成一个LinuxContainer实例,并通过这个对象来管理整个容器的生命周期,包括创建、启动、停止、删除等一系列操作。runk也依赖LinuxContainer类来启动容器进程。目前只在两个场景下使用:创建初始容器进程(对应create/run命令)和在已创建的容器中再启动额外进程(对应exec命令)。针对这两种启动进程的方式,我抽象出了两个类,InitContainer和ActivatedContainer,它们能够生成ContainerLauncher类的对象来启动进程。

运行方式如下:

 

# --pid-file 用于输出启动进程的进程号,--env用于指定环境变量,--cwd用于指定工作目录
$ sudo runk exec --pid-file container1.pid --env ENV1=test --cwd / container1 ls -l

 

2.4 pause/resume

pause/resume利用了cgroup的freezer子系统,可以挂起或者恢复cgroup集合中的进程。

在cgroup_rs包中,已经封装好了对于freezer子系统的操作,目前支持cgroup v1和cgroup v2。核心代码如下,可以很简单地改变容器的freezer状态。

 

pub fn freeze(cgroup: &cgroups::Cgroup, state: FreezerState) -> Result<()> {
    let freezer_controller: &FreezerController = cgroup
        .controller_of()
        .ok_or_else(|| anyhow!("failed to get freezer controller"))?;
    match state {
        FreezerState::Frozen => {
            freezer_controller.freeze()?;
        }
        FreezerState::Thawed => {
            freezer_controller.thaw()?;
        }
        _ => return Err(anyhow!("invalid freezer state")),
    }
    Ok(())
}

 

3. 遇到的特殊问题

在cgroup v1,处于frozen状态的进程无法处理信号,所以对于kill命令,需要先将容器解除frozen状态,然后再发送信号。详情可以参考 runc 仓库的讨论[5]。

4. 测试

目前,runk除了rust自带的单元测试外,还添加了集成测试。集成测试的目的是验证runk的功能是否正常,以及runk与containerd的交互是否正常。集成测试的代码在kata-containers/tests仓库的integration/containerd/runk/runk-tests.sh文件。测试会利用containerd自带的调试工具ctr来调用runk,比如典型的容器启动命令如下:

 

# --runc-binary 用于指定runk的路径,从而使用runk而非默认的runc作为 OCI runtime
sudo ctr run --pid-file ${PID_FILE} --rm -d --runc-binary ${RUNK_BIN_PATH}  ${CONTAINER_ID}

 

5. 总结展望

在runk开发的过程中,我学习到了安全容器的基本架构,阅读了一些容器相关的源码(kata agent/runc/youki),并辅以动手编码,加深了对 OCI runtime 细节的了解。在参与 ·kata· 社区的定期周会以及 GitHub issue 讨论中,我学习到了开源社区的工作模式,也体验到了开源社区的友好氛围。在未来,我希望能够继续参与 kata 社区的开发,为 kata 社区的发展做出贡献。短期目标来看,我会继续专注 runk ,补全其他特性的开发,并持续跟进 runk 的测试,最终让 runk 成为一个完善的 OCI runtime。

最后,感谢一直以来给予指导和review代码的刘斌导师(@liubin)和Manabu Sugimoto(@ManaSugi)。

6. 个人介绍

我是来自中国科学院计算机网络信息中心的研究生陈轶阳,研究方向是超算环境的容器应用。机缘巧合下从隔壁软件所举办的开源之夏活动中知道了kata社区,并最终参加了GLCC开源夏令营,并做了一点微小的工作。

  审核编辑:汤梓红

 

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分