“容器運行時”是一個被過度使用的名詞。 在 Red Hat,我們樂意這么說,“容器即 Linux,Linux 即容器”。下面解釋一下這種說法。傳統(tǒng)的容器是操作系統(tǒng)中的進程,通常具有如下 3 個特性: 資源限制 當你在系統(tǒng)中運行多個容器時,你肯定不希望某個容器獨占系統(tǒng)資源,所以我們需要使用資源約束來控制 CPU、內(nèi)存和網(wǎng)絡帶寬等資源。Linux 內(nèi)核提供了 cgroup 特性,可以通過配置控制容器進程的資源使用。 安全性配置 一般而言,你不希望你的容器可以攻擊其它容器或甚至攻擊宿主機系統(tǒng)。我們使用了 Linux 內(nèi)核的若干特性建立安全隔離,相關(guān)特性包括 SELinux、seccomp 和 capabilities。 (LCTT 譯注:從 2.2 版本內(nèi)核開始,Linux 將特權(quán)從超級用戶中分離,產(chǎn)生了一系列可以單獨啟用或關(guān)閉的 capabilities) 虛擬隔離 容器外的任何進程對于容器而言都應該不可見。容器應該使用獨立的網(wǎng)絡。不同的容器對應的進程應該都可以綁定 80 端口。每個容器的內(nèi)核映像image、根文件系統(tǒng)rootfs(rootfs)都應該相互獨立。在 Linux 中,我們使用內(nèi)核的名字空間namespace特性提供虛擬隔離virtual separation。 那么,具有安全性配置并且在 cgroup 和名字空間下運行的進程都可以稱為容器。查看一下 Red Hat Enterprise Linux 7 操作系統(tǒng)中的 PID 1 的進程 systemd,你會發(fā)現(xiàn) systemd 運行在一個 cgroup 下。 ps 命令讓我們看到 systemd 進程具有 SELinux 標簽: 以及 capabilities: 最后,查看 /proc/1/ns 子目錄,你會發(fā)現(xiàn) systemd 運行所在的名字空間。 如果 PID 1 進程(實際上每個系統(tǒng)進程)具有資源約束、安全性配置和名字空間,那么我可以說系統(tǒng)上的每一個進程都運行在容器中。 容器運行時工具也不過是修改了資源約束、安全性配置和名字空間,然后 Linux 內(nèi)核運行起進程。容器啟動后,容器運行時可以在容器內(nèi)監(jiān)控 PID 1 進程,也可以監(jiān)控容器的標準輸入/輸出,從而進行容器進程的生命周期管理。 容器運行時 你可能自言自語道,“哦,systemd 看起來很像一個容器運行時”。經(jīng)過若干次關(guān)于“為何容器運行時不使用 systemd-nspawn 工具來啟動容器”的郵件討論后,我認為值得討論一下容器運行時及其發(fā)展史。 Docker 通常被稱為容器運行時,但“容器運行時container runtime”是一個被過度使用的詞語。當用戶提到“容器運行時”,他們其實提到的是為開發(fā)人員提供便利的上層high-level工具,包括 Docker,CRI-O 和 RKT。這些工具都是基于 API 的,涉及操作包括從容器倉庫拉取容器鏡像、配置存儲和啟動容器等。啟動容器通常涉及一個特殊工具,用于配置內(nèi)核如何運行容器,這類工具也被稱為“容器運行時”,下文中我將稱其為“底層容器運行時”以作區(qū)分。像 Docker、CRI-O 這樣的守護進程及形如 Podman、Buildah 的命令行工具,似乎更應該被稱為“容器管理器”。 早期版本的 Docker 使用 lxc 工具集啟動容器,該工具出現(xiàn)在 systemd-nspawn 之前。Red Hat 最初試圖將 libvirt (libvirt-lxc)集成到 Docker 中替代 lxc 工具,因為 RHEL 并不支持 lxc。libvirt-lxc 也沒有使用 systemd-nspawn,在那時 systemd 團隊僅將 systemd-nspawn 視為測試工具,不適用于生產(chǎn)環(huán)境。 與此同時,包括我的 Red Hat 團隊部分成員在內(nèi)的上游upstream Docker 開發(fā)者,認為應該采用 golang 原生的方式啟動容器,而不是調(diào)用外部應用。他們的工作促成了 libcontainer 這個 golang 原生庫,用于啟動容器。Red Hat 工程師更看好該庫的發(fā)展前景,放棄了 libvirt-lxc。 后來成立 開放容器組織Open Container Initiative(OCI)的部分原因就是人們希望用其它方式啟動容器。傳統(tǒng)的基于名字空間隔離的容器已經(jīng)家喻戶曉,但人們也有虛擬機級別隔離virtual machine-level isolation的需求。Intel 和 Hyper.sh 正致力于開發(fā)基于 KVM 隔離的容器,Microsoft 致力于開發(fā)基于 Windows 的容器。OCI 希望有一份定義容器的標準規(guī)范,因而產(chǎn)生了 OCI 運行時規(guī)范Runtime Specification。 OCI 運行時規(guī)范定義了一個 JSON 文件格式,用于描述要運行的二進制,如何容器化以及容器根文件系統(tǒng)的位置。一些工具用于生成符合標準規(guī)范的 JSON 文件,另外的工具用于解析 JSON 文件并在該根文件系統(tǒng)(rootfs)上運行容器。Docker 的部分代碼被抽取出來構(gòu)成了 libcontainer 項目,該項目被貢獻給 OCI。上游 Docker 工程師及我們自己的工程師創(chuàng)建了一個新的前端工具,用于解析符合 OCI 運行時規(guī)范的 JSON 文件,然后與 libcontainer 交互以便啟動容器。這個前端工具就是 runc,也被貢獻給 OCI。雖然 runc 可以解析 OCI JSON 文件,但用戶需要自行生成這些文件。此后,runc 也成為了最流行的底層容器運行時,基本所有的容器管理工具都支持 runc,包括 CRI-O、Docker、Buildah、Podman 和 Cloud Foundry Garden 等。此后,其它工具的實現(xiàn)也參照 OCI 運行時規(guī)范,以便可以運行 OCI 兼容的容器。 Clear Containers 和 Hyper.sh 的 runV 工具都是參照 OCI 運行時規(guī)范運行基于 KVM 的容器,二者將其各自工作合并到一個名為 Kata 的新項目中。在去年,Oracle 創(chuàng)建了一個示例版本的 OCI 運行時工具,名為 RailCar,使用 Rust 語言編寫。但該 GitHub 項目已經(jīng)兩個月沒有更新了,故無法判斷是否仍在開發(fā)。幾年前,Vincent Batts 試圖創(chuàng)建一個名為 nspawn-oci 的工具,用于解析 OCI 運行時規(guī)范文件并啟動 systemd-nspawn;但似乎沒有引起大家的注意,而且也不是原生的實現(xiàn)。 如果有開發(fā)者希望實現(xiàn)一個原生的 systemd-nspawn --oci OCI-SPEC.json 并讓 systemd 團隊認可和提供支持,那么CRI-O、Docker 和 Podman 等容器管理工具將可以像使用 runc 和 Clear Container/runV (Kata) 那樣使用這個新的底層運行時。(目前我的團隊沒有人參與這方面的工作。) 總結(jié)如下,在 3-4 年前,上游開發(fā)者打算編寫一個底層的 golang 工具用于啟動容器,最終這個工具就是 runc。那時開發(fā)者有一個使用 C 編寫的 lxc 工具,在 runc 開發(fā)后,他們很快轉(zhuǎn)向 runc。我很確信,當決定構(gòu)建 libcontainer 時,他們對 systemd-nspawn 或其它非原生(即不使用 golang)的運行 namespaces 隔離的容器的方式都不感興趣。 |
|
來自: 昵稱63557093 > 《待分類》