底層 Linux 容器執行時之發展史
“容器執行時”是一個被過度使用的名詞。
在 Red Hat,我們樂意這麼說,“容器即 Linux,Linux 即容器”。下面解釋一下這種說法。傳統的容器是作業系統中的程式,通常具有如下 3 個特性:
-
資源限制
當你在系統中執行多個容器時,你肯定不希望某個容器獨佔系統資源,所以我們需要使用資源約束來控制 CPU、記憶體和網路頻寬等資源。Linux 核心提供了 cgroup 特性,可以通過配置控制容器程式的資源使用。
-
安全性配置
一般而言,你不希望你的容器可以攻擊其它容器或甚至攻擊宿主機系統。我們使用了 Linux 核心的若干特性建立安全隔離,相關特性包括 SELinux、seccomp 和 capabilities。
(LCTT 譯註:從 2.2 版本核心開始,Linux 將特權從超級使用者中分離,產生了一系列可以單獨啟用或關閉的 capabilities)
-
虛擬隔離
容器外的任何程式對於容器而言都應該不可見。容器應該使用獨立的網路。不同的容器對應的程式應該都可以繫結 80 埠。每個容器的核心映像、根檔案系統(rootfs)都應該相互獨立。在 Linux 中,我們使用核心的名字空間特性提供虛擬隔離。
那麼,具有安全性配置並且在 cgroup 和名字空間下執行的程式都可以稱為容器。檢視一下 Red Hat Enterprise Linux 7 作業系統中的 PID 1 的程式 systemd,你會發現 systemd 執行在一個 cgroup 下。
# tail -1 /proc/1/cgroup
1:name=systemd:/
ps
命令讓我們看到 systemd 程式具有 SELinux 標籤:
# ps -eZ | grep systemd
system_u:system_r:init_t:s0 1 ? 00:00:48 systemd
以及 capabilities:
# grep Cap /proc/1/status
...
CapEff: 0000001fffffffff
CapBnd: 0000001fffffffff
CapBnd: 0000003fffffffff
最後,檢視 /proc/1/ns
子目錄,你會發現 systemd 執行所在的名字空間。
ls -l /proc/1/ns
lrwxrwxrwx. 1 root root 0 Jan 11 11:46 mnt -> mnt:[4026531840]
lrwxrwxrwx. 1 root root 0 Jan 11 11:46 net -> net:[4026532009]
lrwxrwxrwx. 1 root root 0 Jan 11 11:46 pid -> pid:[4026531836]
...
如果 PID 1 程式(實際上每個系統程式)具有資源約束、安全性配置和名字空間,那麼我可以說系統上的每一個程式都執行在容器中。
容器執行時工具也不過是修改了資源約束、安全性配置和名字空間,然後 Linux 核心執行起程式。容器啟動後,容器執行時可以在容器內監控 PID 1 程式,也可以監控容器的標準輸入/輸出,從而進行容器程式的生命週期管理。
容器執行時
你可能自言自語道,“哦,systemd 看起來很像一個容器執行時”。經過若干次關於“為何容器執行時不使用 systemd-nspawn
工具來啟動容器”的郵件討論後,我認為值得討論一下容器執行時及其發展史。
Docker 通常被稱為容器執行時,但“容器執行時”是一個被過度使用的詞語。當使用者提到“容器執行時”,他們其實提到的是為開發人員提供便利的上層工具,包括 Docker,CRI-O 和 RKT。這些工具都是基於 API 的,涉及操作包括從容器倉庫拉取容器映象、配置儲存和啟動容器等。啟動容器通常涉及一個特殊工具,用於配置核心如何執行容器,這類工具也被稱為“容器執行時”,下文中我將稱其為“底層容器執行時”以作區分。像 Docker、CRI-O 這樣的守護程式及形如 Podman、Buildah 的命令列工具,似乎更應該被稱為“容器管理器”。
早期版本的 Docker 使用 lxc
工具集啟動容器,該工具出現在 systemd-nspawn
之前。Red Hat 最初試圖將 libvirt (libvirt-lxc
)整合到 Docker 中替代 lxc
工具,因為 RHEL 並不支援 lxc
。libvirt-lxc
也沒有使用 systemd-nspawn
,在那時 systemd 團隊僅將 systemd-nspawn
視為測試工具,不適用於生產環境。
與此同時,包括我的 Red Hat 團隊部分成員在內的上游 Docker 開發者,認為應該採用 golang 原生的方式啟動容器,而不是呼叫外部應用。他們的工作促成了 libcontainer 這個 golang 原生庫,用於啟動容器。Red Hat 工程師更看好該庫的發展前景,放棄了 libvirt-lxc
。
後來成立 開放容器組織(OCI)的部分原因就是人們希望用其它方式啟動容器。傳統的基於名字空間隔離的容器已經家喻戶曉,但人們也有虛擬機器級別隔離的需求。Intel 和 Hyper.sh 正致力於開發基於 KVM 隔離的容器,Microsoft 致力於開發基於 Windows 的容器。OCI 希望有一份定義容器的標準規範,因而產生了 OCI 執行時規範。
OCI 執行時規範定義了一個 JSON 檔案格式,用於描述要執行的二進位制,如何容器化以及容器根檔案系統的位置。一些工具用於生成符合標準規範的 JSON 檔案,另外的工具用於解析 JSON 檔案並在該根檔案系統(rootfs)上執行容器。Docker 的部分程式碼被抽取出來構成了 libcontainer 專案,該專案被貢獻給 OCI。上游 Docker 工程師及我們自己的工程師建立了一個新的前端工具,用於解析符合 OCI 執行時規範的 JSON 檔案,然後與 libcontainer 互動以便啟動容器。這個前端工具就是 runc,也被貢獻給 OCI。雖然 runc
可以解析 OCI JSON 檔案,但使用者需要自行生成這些檔案。此後,runc
也成為了最流行的底層容器執行時,基本所有的容器管理工具都支援 runc
,包括 CRI-O、Docker、Buildah、Podman 和 Cloud Foundry Garden 等。此後,其它工具的實現也參照 OCI 執行時規範,以便可以執行 OCI 相容的容器。
Clear Containers 和 Hyper.sh 的 runV
工具都是參照 OCI 執行時規範執行基於 KVM 的容器,二者將其各自工作合併到一個名為 Kata 的新專案中。在去年,Oracle 建立了一個示例版本的 OCI 執行時工具,名為 RailCar,使用 Rust 語言編寫。但該 GitHub 專案已經兩個月沒有更新了,故無法判斷是否仍在開發。幾年前,Vincent Batts 試圖建立一個名為 nspawn-oci 的工具,用於解析 OCI 執行時規範檔案並啟動 systemd-nspawn
;但似乎沒有引起大家的注意,而且也不是原生的實現。
如果有開發者希望實現一個原生的 systemd-nspawn --oci OCI-SPEC.json
並讓 systemd 團隊認可和提供支援,那麼CRI-O、Docker 和 Podman 等容器管理工具將可以像使用 runc
和 Clear Container/runV (Kata) 那樣使用這個新的底層執行時。(目前我的團隊沒有人蔘與這方面的工作。)
總結如下,在 3-4 年前,上游開發者打算編寫一個底層的 golang 工具用於啟動容器,最終這個工具就是 runc
。那時開發者有一個使用 C 編寫的 lxc
工具,在 runc
開發後,他們很快轉向 runc
。我很確信,當決定構建 libcontainer 時,他們對 systemd-nspawn
或其它非原生(即不使用 golang)的執行 namespaces 隔離的容器的方式都不感興趣。
via: https://opensource.com/article/18/1/history-low-level-container-runtimes
作者:Daniel Walsh 譯者:pinewall 校對:wxy
相關文章
- 容器技術之發展簡史
- 探索雲端計算容器底層之Cgroup
- 【原創】探索容器底層知識之Namespacenamespace
- Linux發展歷史Linux
- Java併發容器,底層原理深入分析Java
- 聊聊我對Linux發展史之淺見Linux
- JAVA執行緒建立底層流程Java執行緒
- 【原創】探索雲端計算容器底層之Cgroup
- Linux 學習基礎入門之Linux發展史Linux
- iOS底層原理 - 常駐執行緒iOS執行緒
- 從底層理解Python的執行Python
- 容器進階:OCI與容器執行時
- 定時任務發展史(二)
- 定時任務發展史(一)
- iOS底層原理 多執行緒之GCD 看我就夠了 --(10)iOS執行緒GC
- IL程式碼底層執行機制之迴圈處理 (轉)
- Linux發展史及簡介Linux
- 死磕java底層(一)—多執行緒Java執行緒
- JavaScript 閉包的底層執行機制JavaScript
- PHP底層的執行機制與原理PHP
- JavaScript閉包的底層執行機制JavaScript
- PHP 底層的執行機制與原理PHP
- Linux設定歷史命令顯示執行時間Linux
- OpenCV認識之發展歷史OpenCV
- Hive底層執行引擎的深度剖析(免費)Hive
- 【深入 PHP】PHP7 底層執行機制PHP
- Hive底層原理:explain執行計劃詳解HiveAI
- 以 DEBUG 方式深入理解執行緒的底層執行原理執行緒
- Docker容器執行時許可權和Linux系統功能DockerLinux
- 線上旅遊行業發展歷史行業
- Linux是如何發展壯大的?一圖看盡Linux發展史!Linux
- HTTP的發展歷史 【積一時之跬步,臻千里之遙程】HTTP
- linux 清空歷史執行記錄Linux
- PHP 底層的執行機制與原理解析PHP
- 【Web發展史】Web
- 前端發展史前端
- 史上最全Docker教程,從容器發展史到實操演練(一)Docker
- iOS底層原理 多執行緒之安全鎖以及常用的讀寫鎖 --(11)iOS執行緒