這是今年開源之夏活動中,陳軼陽同學(xué)參加 runk 項目的總結(jié)文檔,主要介紹了 runk 的由來,以及如何基于現(xiàn)有 kata agent 組件來實現(xiàn)一個標(biāo)準(zhǔn)的 OCI runtime。
1. runk背景
kata-agent是在虛擬機(jī) (VM) 中運行的進(jìn)程,作為管理容器和在這些容器中運行的進(jìn)程的主管。換句話說,kata-agent是 VM 內(nèi)部的一種“低級”容器運行時,因為agent根據(jù) OCI 運行時規(guī)范生成和運行容器。但是,kata-agent沒有運行時規(guī)范中定義的 OCI 命令行界面 (CLI)。kata-runtime提供了Kata Containers運行時組件的 CLI 部分,但kata-runtime是一個容器運行時,用于創(chuàng)建在主機(jī)上運行的硬件虛擬化容器。
ManaSugi[1]發(fā)起了實驗性質(zhì)的runk項目。runk是一個基于 Rust 的標(biāo)準(zhǔn) OCI 容器運行時,它管理傳統(tǒng)的容器。runk旨在成為現(xiàn)有 OCI 兼容容器運行時的替代方案之一。kata-agent具有容器運行時所需的大部分功能,并且由于使用 Rust 語言實現(xiàn),因此具有高性能和低內(nèi)存占用的特點。runk利用kata-agent的機(jī)制來避免重新發(fā)明輪子。
目前,runk仍然是實驗性質(zhì)的工具,有一部分功能還有待實現(xiàn)。根據(jù) 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開源夏令營中新增實現(xiàn)的功能有l(wèi)ist/ps/exec/pause/resume子命令。
2. 新增子命令的作用和實現(xiàn)
2.1 list
list子命令用于列出當(dāng)前運行的容器,列出的基本信息包括容器ID、進(jìn)程PID、狀態(tài)、Bundle、創(chuàng)建時間、所有者。運行效果如下:
$ 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
實現(xiàn)方式是遍歷root目錄下的所有子目錄,然后讀取state.json文件,解析出容器的基本信息并打印輸出。
2.2 ps
ps子命令用于列出容器內(nèi)的進(jìn)程信息。運行效果如下:
$ 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
實現(xiàn)方式是首先通過cgroup來獲取容器內(nèi)所有的pid;然后利用ps -ef命令搜集操作系統(tǒng)上所有進(jìn)程的信息。最后通過pid的比對,將容器進(jìn)程相關(guān)的信息打印出來。
2.3 exec
exec子命令用于在容器內(nèi)執(zhí)行一個新的進(jìn)程,它允許指定啟動進(jìn)程的命令行參數(shù)、環(huán)境變量、cwd等信息。新進(jìn)程會通過setns系統(tǒng)調(diào)用來加入到容器的namesapce中,同時也會加入容器所在的cgroup進(jìn)程集合。
它與已實現(xiàn)的create和run命令類似,依賴rustjail包里的LinuxContainer類。LinuxContainer類是agent啟動容器的核心類,針對每個容器會生成一個LinuxContainer實例,并通過這個對象來管理整個容器的生命周期,包括創(chuàng)建、啟動、停止、刪除等一系列操作。runk也依賴LinuxContainer類來啟動容器進(jìn)程。目前只在兩個場景下使用:創(chuàng)建初始容器進(jìn)程(對應(yīng)create/run命令)和在已創(chuàng)建的容器中再啟動額外進(jìn)程(對應(yīng)exec命令)。針對這兩種啟動進(jìn)程的方式,我抽象出了兩個類,InitContainer和ActivatedContainer,它們能夠生成ContainerLauncher類的對象來啟動進(jìn)程。
運行方式如下:
# --pid-file 用于輸出啟動進(jìn)程的進(jìn)程號,--env用于指定環(huán)境變量,--cwd用于指定工作目錄 $ sudo runk exec --pid-file container1.pid --env ENV1=test --cwd / container1 ls -l
2.4 pause/resume
pause/resume利用了cgroup的freezer子系統(tǒng),可以掛起或者恢復(fù)cgroup集合中的進(jìn)程。
在cgroup_rs包中,已經(jīng)封裝好了對于freezer子系統(tǒng)的操作,目前支持cgroup v1和cgroup v2。核心代碼如下,可以很簡單地改變?nèi)萜鞯膄reezer狀態(tài)。
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狀態(tài)的進(jìn)程無法處理信號,所以對于kill命令,需要先將容器解除frozen狀態(tài),然后再發(fā)送信號。詳情可以參考runc倉庫的討論[5]。
4. 測試
目前,runk除了rust自帶的單元測試外,還添加了集成測試。集成測試的目的是驗證runk的功能是否正常,以及runk與containerd的交互是否正常。集成測試的代碼在kata-containers/tests倉庫的integration/containerd/runk/runk-tests.sh文件。測試會利用containerd自帶的調(diào)試工具ctr來調(diào)用runk,比如典型的容器啟動命令如下:
# --runc-binary 用于指定runk的路徑,從而使用runk而非默認(rèn)的runc作為 OCI runtime sudo ctr run --pid-file ${PID_FILE} --rm -d --runc-binary ${RUNK_BIN_PATH} ${CONTAINER_ID}
5. 總結(jié)展望
在runk開發(fā)的過程中,我學(xué)習(xí)到了安全容器的基本架構(gòu),閱讀了一些容器相關(guān)的源碼(kata agent/runc/youki),并輔以動手編碼,加深了對 OCI runtime 細(xì)節(jié)的了解。在參與 ·kata· 社區(qū)的定期周會以及 GitHub issue 討論中,我學(xué)習(xí)到了開源社區(qū)的工作模式,也體驗到了開源社區(qū)的友好氛圍。在未來,我希望能夠繼續(xù)參與kata社區(qū)的開發(fā),為kata社區(qū)的發(fā)展做出貢獻(xiàn)。短期目標(biāo)來看,我會繼續(xù)專注runk,補全其他特性的開發(fā),并持續(xù)跟進(jìn)runk的測試,最終讓runk成為一個完善的 OCI runtime。
最后,感謝一直以來給予指導(dǎo)和review代碼的劉斌導(dǎo)師(@liubin)和Manabu Sugimoto(@ManaSugi)。
6. 個人介紹
我是來自中國科學(xué)院計算機(jī)網(wǎng)絡(luò)信息中心的研究生陳軼陽,研究方向是超算環(huán)境的容器應(yīng)用。機(jī)緣巧合下從隔壁軟件所舉辦的開源之夏活動中知道了kata社區(qū),并最終參加了GLCC開源夏令營,并做了一點微小的工作。
審核編輯:湯梓紅
-
容器
+關(guān)注
關(guān)注
0文章
507瀏覽量
22353 -
OCI
+關(guān)注
關(guān)注
0文章
15瀏覽量
9067 -
runtime
+關(guān)注
關(guān)注
0文章
17瀏覽量
2260 -
Rust
+關(guān)注
關(guān)注
1文章
233瀏覽量
6933
原文標(biāo)題:開源之夏總結(jié) runk:基于 Rust 的 OCI runtime 實現(xiàn)
文章出處:【微信號:Rust語言中文社區(qū),微信公眾號:Rust語言中文社區(qū)】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
Rust GUI實踐之Rust-Qt模塊
Rust 語言中的 RwLock內(nèi)部實現(xiàn)原理
如何在STM32 (Cortex M3)和GD32(RISC-V)上用Rust開發(fā)
關(guān)于Runtime的應(yīng)用

如何構(gòu)建可以支持Runtime模塊的自定義Substrate鏈
如何在同步的Rust方法中調(diào)用異步代碼呢?
rust語言基礎(chǔ)學(xué)習(xí): 智能指針之Cow
基于Rust語言的高可靠、開源嵌入式Hypervisor

runtime 的一些對比選型和應(yīng)用

評論