從 Solaris Zones 的早期探索到 Docker 的普及,容器技術的發展歷程可謂精彩紛呈。如今,Podman 作為新一代容器引擎,以其無 Daemon 架構和 Rootless 容器等特性,正逐漸受到開發者的青睞。容器技術的興起,不僅改變了應用程式的佈署方式,也推動了微服務架構的發展。本文將帶您回顧容器技術的演進,並探討其在現代軟體開發中的應用。早期 Solaris Zones 的品牌區域概念,已具備容器化的雛形,透過 ZFS 檔案系統的快照和複製功能,實作了應用程式環境的隔離。隨後 Linux Containers (LXC) 的出現,奠定了 Linux 容器技術的根本。LXC 利用名稱空間、強制存取控制和控制群組等核心功能,提供了接近虛擬機器的隔離環境,同時避免了硬體模擬和核心執行的開銷。Docker 的創新之處在於引入了容器映象和容器 registry 的概念,簡化了容器的構建和分享流程,推動了容器技術的普及。rkt 作為無 Daemon 化的容器引擎,也曾一度受到關注。而 OCI 標準的制定,則為容器技術的發展提供了重要的規範,確保了容器引擎之間的互操作性。
為何你需要容器?玄貓解密容器技術演進與應用場景
容器技術已成為現代軟體開發和佈署的根本。但容器並非憑空出現,它們是從早期虛擬化技術演變而來。本文中,玄貓(BlackCat)將帶領大家回顧容器技術的發展歷程,從 Solaris Zones 到 Docker,再到 OCI 標準,探討容器技術的核心概念和應用場景。
Solaris Zones:容器技術的早期先驅
在容器概念還未普及的時代,Solaris Zones(最初稱為 Solaris Containers)已展現出容器化的雛形。Solaris Zones 是 Solaris 作業系統內建的虛擬化技術,結合 ZFS 檔案系統的快照和複製功能,實作了應用程式環境的隔離。
Solaris Zones 的一個亮點是「品牌區域」(branded zone)的概念。品牌區域可以模擬與底層作業系統完全不同的環境,甚至可以包含不同的二進位檔案、工具組或作業系統。這種靈活性使得 Solaris Zones 成為早期容器技術的先驅。
為了確保隔離性,Solaris Zones 擁有獨立的網路、使用者,甚至是時區。這使得應用程式在各自的 Zone 中執行,互不幹擾。
Linux Containers (LXC):Linux 容器化的根本
2008 年,Linux Containers (LXC) 的出現標誌著 Linux 容器技術邁出了重要一步。LXC 不僅是一個容器管理工具,更重要的是,它的開發者貢獻了許多核心功能,這些功能至今仍被 Linux 上的其他容器執行時所使用。
LXC 的目標是提供一個盡可能接近虛擬機器的隔離環境,但又避免了模擬硬體和執行全新核心的開銷。為此,LXC 依賴於以下 Linux 核心功能:
- 名稱空間(Namespaces): 名稱空間隔離了行程,使其只能看到抽象的系統資源。在名稱空間中對系統資源的修改,只對同一名稱空間中的其他行程可見。
- 強制存取控制(Mandatory Access Control): Linux 生態系統中有多種 MAC 實作,其中最著名的是由美國國家安全域性(NSA)開發的 Security Enhanced Linux (SELinux)。
- 控制群組(Control Groups,cgroups): cgroups 是 Linux 核心內建的功能,可以將行程組織成層級群組,並限制和監控這些群組的資源使用。
玄貓(BlackCat)認為,LXC 最重要的特性之一是無特權容器(unprivileged containers)。透過名稱空間、MAC 和 cgroups,LXC 可以隔離一定數量的 UID 和 GID,並將它們對映到底層作業系統。這確保了容器中的 UID 0 實際上對映到主機系統上較高的 UID。
LXC 提供了多種預先建立的名稱空間型別,可以根據需求分配給容器,例如:
- 網路(Network): 提供對網路裝置、堆積疊、埠等的存取。
- 掛載(Mount): 提供對掛載點的存取。
- PID: 提供對行程 ID 的存取。
Docker:容器技術的普及者
2013 年,Docker 的出現引爆了容器技術的普及。有趣的是,最初的 Docker 容器引擎實際上是 LXC!
在經過一年的開發後,Docker 團隊推出了 libcontainer,並最終用自己的實作取代了 LXC 容器引擎。與 LXC 類別似,Docker 也需要在主機系統上執行一個守護行程(daemon)來管理容器。
Docker 的一個重要特性是 OverlayFS,這是一種聯合檔案系統,可以將多個檔案系統合併成一個單一的檔案系統。
玄貓(BlackCat)認為,Docker 真正的創新之處在於引入了容器映象(container images)和容器 registry 的概念。映象和 registry 使得開發者、系統管理員和技術愛好者可以協作並貢獻自己的容器映象,從而建立了一個龐大的生態系統。Docker 還建立了一種特殊的檔案格式(Dockerfile),用於自動化容器映象的建立過程。
rkt:無 Daemon 化的容器引擎
在 Docker 興起後不久,CoreOS 公司(後被 Red Hat 收購)於 2014 年至 2015 年間推出了自己的容器引擎 rkt(發音為 “rocket”)。rkt 的一個獨特之處是它沒有守護行程(daemon-less)。
這意味著每個容器都是獨立的,就像在主機系統上啟動的任何其他標準行程一樣。2017 年,rkt 被雲原生計算基金會(CNCF)接納,與 Docker 捐贈的 containerd 專案一起,成為 CNCF 的一部分。
OCI 與 CRI-O:容器標準化的推動者
Docker 將 containerd 捐贈給 CNCF,促使開源社群開始認真開發可以注入到 Kubernetes 等協調層下的容器引擎。
2015 年,Docker 與 Red Hat、AWS、Google、Microsoft 和 IBM 等公司共同成立了開放容器倡議(OCI),旨在制定容器引擎的 API 和架構標準。
OCI 團隊開發了執行時規範(runtime spec)和映象規範(image spec),用於描述如何建立新的容器引擎。同年,OCI 團隊還發布了第一個符合 OCI 規範的容器執行時 runc。
為何我擁抱容器技術:從VM到雲原生架構的演進
在現代軟體開發中,容器技術已成為不可或缺的一環。但你是否曾想過,為何我們需要容器?這背後其實經歷了一段技術演進的過程。讓玄貓(BlackCat)帶你一起回顧容器技術的發展歷程,以及它如何改變了我們的應用程式佈署方式。
OCI與CRI:容器標準化的根本
容器技術的標準化對於其普及至關重要。開放容器倡議(OCI)不僅定義了執行獨立容器的規範,也為Kubernetes與底層容器引擎的整合奠定了基礎。同時,Kubernetes社群發布了容器執行時介面(CRI),這是一個外掛介面,旨在支援各種容器執行時的採用。
CRI-O:Kubernetes的輕量級執行時選擇
CRI-O於2017年由Red Hat以開源專案的形式發布,是最早實作Kubernetes容器執行時介面(CRI)的專案之一,它使得使用OCI相容的執行時成為可能。相較於Docker、rkt或其他引擎,CRI-O提供了一個更輕量級的替代方案,作為Kubernetes的執行時。
Podman:無Daemon的容器管理新星
讓我們快轉到2017年,這一年Podman專案在GitHub上首次提交。Podman這個名字就揭示了它的目的:POD MANager(Pod管理器)。在容器的世界裡,一個Pod是可以被Kubernetes處理的最小可佈署計算單元,它可以由一個或多個容器組成。在同一個Pod中的多個容器會並排排程和執行,分享相同的上下文。
Podman管理容器和容器映像、它們的儲存卷以及由一個或多個容器組成的Pod,並且從頭開始構建以符合OCI標準。與其前身rkt一樣,Podman沒有管理容器的中央Daemon,而是將它們作為標準系統行程啟動。它還定義了一個與Docker相容的CLI介面,以簡化從Docker的過渡。
Rootless容器:安全與便捷的完美結合
Podman引入的一個重要特性是Rootless容器。通常,當我們想到Linux容器時,我們立即會想到系統管理員需要在作業系統層級設定一些先決條件,以準備讓我們的容器啟動並執行的環境。Rootless容器可以輕鬆地以普通使用者身分執行,而無需root許可權。使用Podman與非特權使用者將啟動受限容器,而無需任何特權,例如執行它的使用者。
容器的應用場景:從單體到微服務
毫無疑問,Podman引入了更大的靈活性,並且是一個高度活躍的專案,其採用率不斷增長。例如,3.0版本引入了對Docker Compose的支援,這是一個備受要求的功能。這也是社群支援的一個很好的健康指標。
容器的採用正在每個企業公司的每個業務部門中蔓延。但如果我們調查已經使用容器或Kubernetes發行版的公司的成功案例,我們會發現容器化和容器協調正在加速專案的開發和交付,從汽車到醫療保健,加速了各種行業中新使用案例的建立。
公司正在從舊的VM佈署模型轉向容器模型,以用於新應用程式。正如我們在前面的段落中簡要介紹的那樣,容器可以很容易地表示為一種新的應用程式封裝方式。回顧VM,它們的主要目的是什麼?它是建立一個隔離的環境,其中包含為目標應用程式執行的保留資源數量。隨著容器的引入,企業公司意識到它們可以更好地最佳化其基礎設施,加速新服務的開發和佈署,從而引入某種創新。
回顧容器採用和使用的歷史,我們可以發現,一開始它們被用作舊式單體應用程式執行時的封裝方法,但隨著雲原生浪潮的興起,以及微服務等概念的普及,容器成為封裝下一代雲原生應用程式的事實標準。
從玄貓(BlackCat)與採用容器的客戶的日常工作中,我們可以確認,客戶開始僅在容器中封裝標準應用程式,並使用容器協調器(例如Kubernetes)對它們進行協調,但是一旦新的開發模型到達開發人員團隊,容器及其協調器也開始越來越多地管理這種新型服務。
容器技術概論:玄貓解構微服務與容器化架構
在探討微服務架構之前,讓玄貓先帶領大家回顧一下相關的背景知識。考慮一個使用微服務建構的簡單網頁商店應用程式。根據我們使用的客戶端型別(手機或網頁瀏覽器),我們可以與三個底層服務互動,這些服務都是解耦的,並透過 REST API 進行通訊。其中一個很棒的新特性是在資料層級進行解耦;每個微服務都有自己的資料函式庫和資料結構,這使得它們在開發和佈署的每個階段都具有獨立性。
現在,如果我們為架構中顯示的每個微服務比對一個容器,並新增一個協調器(例如 Kubernetes),我們會發現解決方案幾乎完成了!由於容器技術的發展,每個服務都可以擁有自己的容器基礎映像,其中僅包含所需的執行階段,從而確保了一個輕量級的預先構建的套件,其中包含服務啟動後所需的所有資源。
另一方面,看看圍繞應用程式開發及其維護的各種自動化流程,根據容器的架構也可以輕鬆地適用於 CI/CD 工具,以自動化開發、測試和執行應用程式所需的所有步驟。
CI/CD 代表持續整合和持續交付/佈署。這些實踐試圖填補開發和營運活動之間的差距,增加構建、測試和佈署應用程式過程中的自動化程度。
玄貓認為,容器技術的誕生是為了滿足系統管理員的需求,但最終卻成為了開發人員喜愛的工具!這項技術在許多公司中代表了開發團隊和營運團隊之間的連線環,從而實作並加速了 DevOps 實踐的採用,這些實踐以前是孤立的,目的是加強這兩個團隊之間的協作。
DevOps 是一組有助於連結軟體開發 (Dev) 和 IT 營運 (Ops) 的實踐。DevOps 的目標是縮短應用程式的開發生命週期,並增加應用程式的交付發布。
容器化與單體應用:玄貓的實戰經驗分享
雖然微服務和容器喜歡一起生活,但企業公司有很多應用程式、軟體和解決方案並非根據微服務架構,而是根據以前的單體方法,例如,使用叢集應用程式伺服器!但我們不必太擔心,因為容器及其協調器同時發展以支援這種工作負載。
容器技術可以被認為是一種進化的應用程式封裝格式,可以針對包含所有必要的函式庫和工具(甚至是複雜的單體應用程式)進行最佳化。多年來,基礎容器映像不斷發展,以最佳化大小和內容,從而建立更小的執行階段,從而提高整體管理能力,即使對於複雜的單體應用程式也是如此。
如果我們檢視 Red Hat Enterprise Linux 容器基礎映像的大小(以其最小的形式),我們可以看到該映像在下載期間約為 30 MB,並且在目標基礎系統中提取後(當然透過 Podman)僅為 84 MB。
即使是協調器也採用了內部特性和資源來處理單體應用程式,這些應用程式與雲原生概念相去甚遠。例如,Kubernetes 在平台核心中引入了一些特性,以確保容器的狀態性,以及用於儲存本地快取資料或應用程式重要內容的持久儲存概念。
玄貓觀點:容器技術的演進與企業應用
在本章中,玄貓帶領大家探索了容器技術的底層功能,從行程隔離到容器執行階段。然後,我們研究了容器相對於虛擬機器的主要目的和優勢。之後,我們啟動了時光機,從 1979 年到今天,瞭解了容器的歷史。最後,我們瞭解了當今的市場趨勢以及當前企業公司中容器的採用情況。
本章提供了容器技術及其歷史的簡介。Podman 在可用性和 CLI 方面與 Docker 非常接近,下一章將介紹這兩個專案之間的差異,從架構角度和使用者經驗角度來看。
在介紹 Docker 高階架構之後,將詳細描述 Podman 無守護行程架構,以瞭解此容器引擎如何在不需要執行守護行程的情況下管理容器。
延伸閱讀
有關本章涵蓋主題的更多資訊,請參閱以下內容:
- The Linux Programming Interface, Michael Kerrisk (ISBN 978-1-59327-220-3)
- Demystifying namespaces and containers in Linux: https://opensource.com/ article/19/10/namespaces-and-containers-linux
- OCI Runtime Specs: https://github.com/opencontainers/runtime-spec
- OCI Image Specs: https://github.com/opencontainers/image-spec
- Container Runtime Interface announcement: https://kubernetes. io/blog/2016/12/container-runtime-interface-cri-in-kubernetes/
Podman 與 Docker:玄貓的深度比較
正如我們從前一章瞭解到的,容器技術並不像我們想像的那麼新,因此它的實施和架構多年來一直受到影響,以達到目前的狀態。
在本章中,我們將介紹 Docker 和 Podman 容器引擎的一些歷史和主要架構,並進行並排比較,以便讓具有 Docker 經驗的讀者輕鬆上手,並在深入探索 Podman 之前瞭解主要差異。
如果您沒有太多 Docker 經驗,您可以輕鬆跳到下一章,並在您覺得是時候瞭解 Podman 和 Docker 容器引擎之間的差異時傳回本章。
在本章中,我們將介紹以下主要主題:
- Docker 容器守護行程架構
- Podman 無守護行程架構
- Docker 和 Podman 之間的主要差異
技術要求
本章不需要任何技術先決條件;請隨意閱讀它,而不必過於擔心在您的工作站上安裝或設定任何型別的軟體!
如果您想複製本章中將描述的一些範例,您需要在您的工作站上安裝和設定 Podman 和 Docker。正如我們之前描述的,您可以輕鬆跳到下一章,並在您覺得是時候瞭解 Podman 和 Docker 容器引擎之間的差異時傳回本章。
請考慮到在下一章中,您將被介紹到 Podman 的安裝和設定,因此您將很快能夠複製您在本章和以下章節中看到的任何範例。
Docker 容器守護行程架構
容器是執行隔離行程例項需求的一個簡單而聰明的答案。我們可以安全地確認容器是一種在多個層級(例如檔案系統、網路、資源使用、行程等)工作的應用程式隔離形式。
正如我們在第 1 章「容器技術概論」的「容器與虛擬機器」部分中看到的,容器也與虛擬機器不同,因為容器與主機共用相同的核心,而虛擬機器有自己的客體作業系統核心。從安全形度來看,虛擬機器提供比潛在攻擊更好的隔離,但虛擬機器通常會消耗比容器更多的資源。要啟動客體作業系統,我們通常需要分配比啟動容器所需的資源更多的 RAM、CPU 和儲存空間。
早在 2013 年,Docker 容器引擎就出現在容器領域,並迅速變得非常受歡迎。
正如我們之前解釋的,容器引擎是一種軟體工具,它接受和處理來自使用者的建立容器的請求;它可以被看作是一種協調器。另一方面,容器執行階段是一種較低層級的軟體,容器引擎使用它來在主機中執行容器,管理隔離、儲存、網路等。
在早期階段,Docker 容器引擎使用 LXC 作為容器執行階段,但隨後用他們自己的實作 libcontainer 替換了它。
玄貓解說:Docker 的興起與架構演進
玄貓認為 Docker 的出現,大幅簡化了容器的使用,讓開發者能更方便地封裝和佈署應用程式。Docker 透過 Client-Server 架構運作,其中 Docker Client 負責接收使用者的指令,並將其傳送給 Docker Daemon 處理。Docker Daemon 則負責建立、執行和管理容器。
Docker 架構元件:
- Docker Client: 使用者與 Docker 互動的介面,負責傳送指令給 Docker Daemon。
- Docker Daemon: 負責接收 Client 的指令,並執行容器的建立、執行、管理等操作。
- Docker Image: 唯讀的範本,用於建立 Docker 容器。
- Docker Container: 從 Docker Image 建立的可執行例項。
- Docker Hub: 公有的 Docker Image 倉函式庫,提供大量的現成 Image 供使用者下載使用。
Docker 的 Client-Server 架構雖然簡潔易用,但也存在一些潛在問題。例如,Docker Daemon 需要以 root 許可權執行,這可能存在安全風險。此外,單一的 Docker Daemon 負責管理所有的容器,如果 Daemon 發生故障,可能會影響到所有的容器。
在接下來的章節中,玄貓將會探討 Podman 的架構,並比較 Podman 與 Docker 之間的差異,讓大家更瞭解這兩種容器工具的優缺點。
總結來說,Docker 的出現確實推動了容器技術的普及,但其架構也存在一些限制。Podman 的出現,則提供了一個更安全、更靈活的容器解決方案。