這是今年開源之夏活動中,陳軼陽同學參加 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) | |
runcommand | |
speccommand | |
execcommand | |
listcommand | |
pscommand | |
pause/resumecommands | |
updatecommand | |
eventscommand | |
initcommand | |
checkpoint/restorecommands (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開源夏令營,并做了一點微小的工作。
審核編輯:湯梓紅
-
容器
+關注
關注
0文章
503瀏覽量
22312 -
OCI
+關注
關注
0文章
14瀏覽量
9055 -
runtime
+關注
關注
0文章
17瀏覽量
2249 -
Rust
+關注
關注
1文章
233瀏覽量
6868
原文標題:開源之夏總結 runk:基于 Rust 的 OCI runtime 實現
文章出處:【微信號:Rust語言中文社區,微信公眾號:Rust語言中文社區】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
Rust GUI實踐之Rust-Qt模塊
Rust 語言中的 RwLock內部實現原理
如何在STM32 (Cortex M3)和GD32(RISC-V)上用Rust開發
關于Runtime的應用

如何構建可以支持Runtime模塊的自定義Substrate鏈
如何在同步的Rust方法中調用異步代碼呢?
rust語言基礎學習: 智能指針之Cow
基于Rust語言的高可靠、開源嵌入式Hypervisor

runtime 的一些對比選型和應用

評論