爲什麼說2019,是屬於容器技術的時代?

此文系 QCon 十週年特別策劃《技術十年》系列文章,旨在通過回顧技術發展總結最佳實踐、爲開發者啓發技術新思路。訪問QCon北京2019官網日程,瞭解最新技術趨勢與實踐。

2019 年,是屬於容器的年代。

在這一年,全世界的開發人員都開始習慣用容器測試自己的軟件,用容器做線上發佈,開始對容器化的軟件構建和交付流程習以爲常。全世界的架構師們都在對“雲原生”侃侃而談,描繪多雲時代的應用治理方式,不經意間就把 “sidecar” 這種容器組織方式當做了默認選項。在“雲”已經成爲了大衆基礎設施的今天,我們已經習慣了把“容器“當做現代軟件基礎設施的基本依賴。這就像我們每天打開 Eclipse 編寫 Java 代碼一樣自然。

不過,不要忘了,只需要往回倒數兩年, 整個容器生態都還在圍着 Docker 公司爭得不可開交,看起來完全沒有定數。當時的國內很多公有云廠商,甚至都沒有正式的 Kubernetes 服務。在那個時候,要依託容器技術在雲上託管完整的軟件生命週期,可以說是相當前沿的探索。誰能想到短短兩年之後,容器這個站在巨人肩膀上的設計,就真的成爲技術人員日常工作的一部分呢?

事實上,伴隨着容器技術普及到“千家萬戶”,我們在這兩年期間所經歷的,是現代軟件交付形式的一次重要變革。

源起:屬於 Jails 們的時代

虛擬化容器技術(virtualized container)的歷史,其實可以一直追溯上世紀 70 年代末。感謝 Wikipedia 等活歷史,我們現在至少還能從文字上瞭解到在很多讀者出生前,一羣來自貝爾實驗室( Bell Laboratories )的“黑客”研究員們正試圖用“容器”的概念來解決什麼樣問題。

時間回到 1979 年,貝爾實驗室正在爲 Unix V7 (Version 7 Unix)操作系統的發佈進行最後的開發和測試工作。在那個時候,Unix 操作系統還是貝爾實驗室的內部項目,而運行 Unix 的機器則是長得像音響一樣的、名叫 PDP 系列的巨型盒子。在那個“軟件危機(The Software Crisis)”橫行的末期,開發和維護 Unix 這樣一套操作系統項目,即使對貝爾實驗室來說也絕非易事。更何況,那裏的程序員們還得一邊開發 Unix ,一邊開發 C 語言本身呢。

而在 Unix V7 的開發過程中,系統級別軟件構建(Build)和測試(Test)的效率其實是其中一個最爲棘手的難題。這裏的原因也容易理解:當一個系統軟件編譯和安裝完成後,整個測試環境其實就被“污染”了。如果要進行下一次構建、安裝和測試,就必須重新搭建和配置整改測試環境。在有云計算能力的今天,我們或許可以通過虛擬機等方法來完整的復現一個集羣。但在那個一塊 64K 的內存條要賣 419 美元的年代,“快速銷燬和重建基礎設施”的想法還是有點“科幻”了。

所以,貝爾實驗室的聰明腦袋們開始構思一種在現有操作系統環境下“隔離”出一個可供軟件進行構建和測試的環境。更確切的說,就是我能否簡單的執行一些指令,就改變一個程序的“視圖”,讓它把當前目錄當做自己的根目錄呢?這樣,我每次只要在當前目錄裏放置一個完整操作系統文件系統部分,該軟件運行所需的所有依賴就完備了。

更爲重要的是,有了這個能力,開發者實際上就間接擁有了應用基礎設施“快速銷燬和重現”的能力,而不需要在環境搭好之後進入到環境裏去進行應用所需的依賴安裝和配置。這當然是因爲,現在我的整個軟件運行的依賴,是以一個操作系統文件目錄的形式事先準備好的,而開發者只需要構建和測試應用的時候,切換應用“眼中”的根目錄到這個文件目錄即可。

於是,一個叫做 chroot(Change Root)的系統調用就此誕生了。

顧名思義,chroot 的作用是“重定向進程及其子進程的根目錄到一個文件系統上的新位置”,使得該進程再也看不到也沒法接觸到這個位置上層的“世界”。所以這個被隔離出來的新環境就有一個非常形象的名字,叫做 Chroot Jail。

值得一提的是,這款孕育了 chroot 的 Unix V7 操作系統,成爲了貝爾實驗室 Unix 內部發行版的絕唱。在這一年末尾, Unix 操作系統正式被 AT&T 公司商業化,並被允許授權給外部使用,自此開啓了一代經典操作系統的傳奇之旅。

而 Chroot 的誕生,也第一次爲世人打開了“進程隔離”的大門。

伴隨着這種機被更廣泛的用戶接觸到, chroot 也逐漸成爲了開發測試環境配置和應用依賴管理的一個重要工具。而 “Jail” 這個用來描述進程被隔離環境的概念,也開始激發出這個技術領域更多的靈感。在 2000 年,同屬 Unix 家族的 FreeBSD 操作系統發佈了”jail“命令,宣佈了 FreeBSD Jails 隔離環境的正式發佈。相比於 Chroot Jail,FreeBSD Jails 把”隔離“這個概念擴展到了進程的完整視圖,隔離出了獨立進程環境和用戶體系,併爲 Jails 環境分配了獨立的 IP 地址。所以確切的說,儘管 chroot 開創了進程環境隔離的思想,但 FreeBSD Jails,其實才真正實現了進程的沙箱化。而這裏的關鍵在於,這種沙箱的實現,依靠的是操作系統級別的隔離與限制能力而非硬件虛擬化技術。

不過,無論是 FreeBSD Jails(Unix 平臺),還是緊接着出現的 Oracle Solaris Containers(Solaris 平臺),都沒有能在更廣泛的軟件開發和交付場景中扮演到更重要的角色。在這段屬於 Jails 們的時代,進程沙箱技術因爲“雲”的概念尚未普及,始終被侷限在了小衆而有限的世界裏。

發展:雲,與應用容器

事實上,在 Jails 大行其道的這幾年間,同樣在迅速發展的 Linux 陣營上也陸續出現多個類似的沙箱技術比如 Linux VServer 和 Open VZ(未進入內核主幹)。但跟 Jails 的發展路徑比較類似,這些沙箱技術最後也都淪爲了小衆功能。我們再次看到了,進程沙箱技術的發展過程中“雲”的角色缺失所帶來的影響,其實還是非常巨大的。而既然說到“雲”,我們就不得不提到基礎設施領域的翹楚:Google。

Google 在雲計算背後最核心的基礎設施領域的強大影響力,是被業界公認的一個事實,無論是當初震驚世界的三大論文,還是像 Borg/Omega 等領先業界多年的內部基礎設施項目,都在這個領域扮演者重要的啓迪者角色。然而,放眼當今的雲計算市場, 僅僅比 Google 雲計算髮布早一年多的 AWS 卻是“雲”這個產業毫無爭議的領導者。而每每談到這裏的原因,大家都會提到一個充滿了爭議的項目:GAE。

GAE 對於中國的某幾代技術人員來說,可以說是一個揮之不去的記憶。然而,即使是這批 GAE 的忠實用戶,恐怕也很難理解這個服務竟然就是 Google 當年決定用來對抗 AWS 的核心雲產品了。事實上,GAE 本身與其說是 PaaS,倒不如說是簡化版的 Serverless。在 2008 年,在絕大多數人還完全不知道雲計算爲何物的情況下,這樣的產品要想取得成功拿下企業用戶,確實有些困難。

不過,在這裏我們想要討論的並不是 Google 的雲戰略,而是爲什麼從技術的角度上,Google 也認爲 GAE 這樣的應用託管服務就是雲計算呢?

這裏的一個重要原因可能很多人都瞭解過,那就是 Google 的基礎設施技術棧其實是一個標準容器技術棧,而不是一個虛擬機技術棧。更爲重要的是,在 Google 的這套體系下,得益於 Borg 項目提供的獨有的應用編排與管理能力,容器不再是一個簡單的隔離進程的沙箱,而成爲了對應用本身的一種封裝方式。依託於這種輕量級的應用封裝,Google 的基礎設施可以說是一個天然以應用爲中心的託管架構和編程框架,這也是很多前 Googler 調侃“離開了 Borg 都不知道怎麼寫代碼”的真實含義。這樣一種架構和形態,映射到外部的雲服務成爲 GAE 這樣的一個 PaaS/Serverless 產品,也就容易理解了。而 Google 這套容器化基礎設施的規模化應用與成熟,可以追溯到 2004~2007 年之間,而這其中一個最爲關鍵的節點,正是一種名叫 Process Container 技術的發佈。

Process Container 的目的非常直白,它希望能夠像虛擬化技術那樣給進程提供操作系統級別的資源限制、優先級控制、資源審計能力和進程控制能力,這與前面提到的沙箱技術的目標其實是一致的。這種能力,是前面提到的 Google 內部基礎設施得以實現的基本訴求和基礎依賴,同時也成爲了 Google 眼中“容器”技術的雛形。帶着這樣的設思路,Process Container 在 2006 年由 Google 的工程師正式推出後,第二年就進入了 Linux 內核主幹。不過,由於 Container 這個術語在 Linux 內核中另有它用,Process Container 在 Linux 中被正式改名叫作:Cgroups。

Cgroups 技術的出現和成熟,標誌在 Linux 陣營中“容器”的概念開始被重新審視和實現。更重要的是,這一次“容器”這個概念的倡導者變成了 Google:一個正在大規模使用容器技術定義世界級基礎設施的開拓者。

在 2008 年,通過將 Cgroups 的資源管理能力和 Linux Namespace 的視圖隔離能力組合在一起,LXC(Linux Container)這樣的完整的容器技術出現在了 Linux 內核當中。儘管 LXC 提供給用戶的能力跟前面提到的各種 Jails 以及 OpenVZ 等早期 Linux 沙箱技術是非常相似的,但伴隨着 Linux 操作系統開始迅速佔領商用服務器市場的契機,LXC 的境遇比前面的這些前輩要好上不少。而更爲重要的是,2008 年之後 AWS ,Microsoft 等巨頭們持續不斷的開始在公有云市場上進行發力,很快就催生出了一個全新的、名叫 PaaS 的新興產業。

老牌雲計算廠商在 IaaS 層的先發優勢以及這一部分的技術壁壘,使得越來越多受到公有云影響的技術廠商以及雲計算的後來者,開始思考如何在 IaaS 之上構建新的技術與商業價值,同時避免走入 GAE 當年的歧途。在這樣的背景之下,一批以開源和開放爲主要特點的平臺級項目應運而生,將 “PaaS” 這個原本虛無縹緲的概念第一次實現和落地。這些 PaaS 項目的定位是應用託管服務,而不同於 GAE 等公有云託管服務 ,這些開放 PaaS 項目希望構建的則是完全獨立於 IaaS 層的一套應用管理生態,目標是藉助 PaaS 離開發者足夠近的優勢鎖定雲乃至所有數據中心的更上層入口。這樣的定位,實際上就意味着 PaaS 項目必須能夠不依賴 IaaS 層虛擬機技術,就能夠將用戶提交的應用進行封裝,然後快速的部署到下層基礎設施上。而這其中,開源、中立,同時又輕量、敏捷的 Linux 容器技術,自然就成爲了 PaaS 進行託管和部署應用的最佳選擇。

在 2009 年,VMware 公司在收購了 SpringSource 公司(Spring 框架的創始公司)之後,將 SpringSource 內部的一個 Java PaaS 項目的名字,套在了自己的一個內部 PaaS 頭上,然後於 2011 年宣佈了這個項目的開源。這個項目的名字,就叫做:Cloud Foundry。

Cloud Foundry 項目的誕生,第一次對 PaaS 的概念完成了清晰而完整的定義。這其中,“PaaS 項目通過對應用的直接管理、編排和調度讓開發者專注於業務邏輯而非基礎設施”,以及“PaaS 項目通過容器技術來封裝和啓動應用”等理念,也第一次出現在雲計算產業當中並得到認可。值得一提的是,Cloud Foundry 用來操作和啓動容器的項目叫做:Warden,它最開始是一個 LXC 的封裝,後來重構成了直接對 Cgroups 以及 Linux Namespace 操作的架構。

實際上,Cloud Foundry 等 PaaS 項目的逐漸流行,與當初 Google 發佈 GAE 的初衷是完全一樣的。說到底,這些服務都認爲應用的開發者不應該關注於虛擬機等底層基礎設施,而應該專注在編寫業務邏輯這件最有價值的事情上。這個理念,在越來越多的人得以通過雲的普及開始感受到管理基礎設施的複雜性和高成本之後,才變得越來越有說服力。在這幅藍圖中,Linux 容器已經跳出了進程沙箱的侷限性,開始扮演的“應用容器”的角色。在這個新的舞臺上, 容器和應用終於畫上了等號,這才最終使得平臺層系統能夠實現應用的全生命週期託管。

按照這個劇本,容器技術以及雲計算的發展,理應向着 PaaS 的和以應用爲中心的方向繼續演進下去。

如果不是有一家叫做 Docker 的公司出現的話。

容器:改寫的軟件交付的歷程

如果不是親歷者的話,你很難想象 PaaS 乃至雲計算產業的發展,會如何因爲 2013 年一個創業公司開源項目的發佈而被徹底改變。但這件事情本身,確實是過去 5 年間整個雲計算產業變革的真實縮影。

Docker 項目的發佈,以及它與 PaaS 的關係,想必我們已經無需在做贅述。一個“降維打擊”,就足以給當初業界的爭論不休畫上一個乾淨利落的句號。

我們都知道, Docker 項目發佈時,無非也是 LXC 的一個使用者,它創建和使用應用容器的邏輯跟 Warden 等沒有本質不同。不過,我們現在也知道,真正讓 PaaS 項目無所適從的,是 Docker 項目最厲害的殺手鐗:容器鏡像。

關於如何封裝應用,這本身不是開發者所關心的事情,所以 PaaS 項目有着無數的發揮空間。但到這如何定義應用這個問題,就是跟每一位技術人員息息相關了。在那個時候,Cloud Foundry 給出的方法是 Buildpack,它是一個應用可運行文件(比如 WAR 包)的封裝,然後在裏面內置了 Cloud Foundry 可以識別的啓動和停止腳本,以及配置信息。

然而,Docker 項目通過容器鏡像,直接將一個應用運行所需的完整環境,即:整個操作系統的文件系統也打包了進去。這種思路,可算是解決了困擾 PaaS 用戶已久的一致性問題,製作一個“一次發佈、隨處運行”的 Docker 鏡像的意義,一下子就比製作一個連開發和測試環境都無法統一的 Buildpack 高明瞭太多。

更爲重要的是,Docker 項目還在容器鏡像的製作上引入了“層”的概念,這種基於“層”(也就是“commit” ) 進行 build,push,update 的思路,顯然是借鑑了 Git 的思想。所以這個做法的好處也跟 Github 如出一轍:製作 Docker 鏡像不再是一個枯燥而乏味的事情,因爲通過 DockerHub 這樣的鏡像託管倉庫,你和你的軟件立刻就可以參與到全世界軟件分發的流程當中。

至此,你就應該明白,Docker 項目實際上解決的確實是一個更高維度的問題:軟件究竟應該通過什麼樣的方式進行交付?

更重要的是,一旦當軟件的交付方式定義的如此清晰並且完備的時候,利用這個定義在去做一個託管軟件的平臺比如 PaaS,就變得非常簡單而明瞭了。這也是爲什麼 Docker 項目會多次表示自己只是“站在巨人肩膀上”的根本原因:沒有最近十年 Linux 容器等技術的提出與完善,要通過一個開源項目來定義並且統一軟件的交付歷程,恐怕如癡人說夢。

雲,應用,與雲原生

時至今日,容器鏡像已經成爲了現代軟件交付與分發的事實標準。然而, Docker 公司卻並沒有在這個領域取得同樣的領導地位。這裏的原因相比大家已經瞭然於心:在容器技術取得巨大的成功之後,Docker 公司在接下來的“編排之爭”中犯下了錯誤。事實上,Docker 公司憑藉“容器鏡像”這個巧妙的創新已經成功解決了“應用交付”所面臨的最關鍵的技術問題。但在如何定義和管理應用這個更爲上層的問題上,容器技術並不是“銀彈”。在“應用”這個與開發者息息相關的領域裏,從來就少不了複雜性和靈活性的訴求,而容器技術又天然要求應用的“微服務化”和“單一職責化”,這對於絕大多數真實企業用戶來說都是非常困難的。而這部分用戶,又偏偏是雲計算產業的關鍵所在。

而相比於 Docker 體系以“單一容器”爲核心的應用定義方式,Kubernetes 項目則提出了一整套容器化設計模式和對應的控制模型,從而明確瞭如何真正以容器爲核心構建能夠真正跟開發者對接起來的應用交付和開發範式。而 Docker 公司、Mesosphere 公司 以及 Kubernetes 項目在“應用”這一層上的不同理解和頂層設計,其實就是所謂“編排之爭”的核心所在。

2017 年末,Google 在過去十年編織全世界最先進的容器化基礎設施的經驗,最終幫助 Kubernetes 項目取得到了關鍵的領導地位,並將 CNCF 這個以“雲原生”爲關鍵詞的組織和生態推向了巔峯。

而最爲有意思的是, Google 公司在 Kubernetes 項目傾其全力注入的“靈魂”,既不是 Borg/Omega 多年來積累下來的大規模調度與資源管理能力,也不是“三大論文”這樣讓當年業界望塵莫及的領先科技。Kubernetes 項目裏最能體現 Google 容器理念的設計,是“源自 Borg/Omega 體系的應用編排與管理能力”。

我們知道,Kubernetes 是一個“重 API 層” 的項目,但我們還應該理解的是,Kubernetes 是一個“以 API 爲中心”的項目。圍繞着這套聲明式 API,Kubernetes 的容器設計模式,控制器模型,以及異常複雜的 apiserver 實現與擴展機制纔有了意義。而這些看似繁雜的設計與實現背後,實際上只服務於一個目的,那就是:如何讓用戶在管理應用的時候能最大程度的發揮容器和雲的價值。

本着這個目的,Kubernetes 纔會把容器進行組合,用 Pod 的概念來模擬進程組的行爲。纔會堅持用聲明式 API 加控制器模型來進行應用編排,用 API 資源對象的創建與更新(PATCH)來驅動整個系統的持續運轉。更確切的說,有了 Pod 和容器設計模式,我們的應用基礎設施才能夠與應用(而不是容器)進行交互和響應的能力,實現了“雲”與“應用”的直接對接。而有了聲明式 API,我們的應用基礎而設施才能真正同下層資源、調度、編排、網絡、存儲等雲的細節與邏輯解耦。我們現在,可以把這些設計稱爲“雲原生的應用管理思想”,這是我們“讓開發者專注於業務邏輯”、“最大程度發揮雲的價值”的關鍵路徑。

所以說,Kubernetes 項目一直在做的,其實是在進一步清晰和明確“應用交付”這個亙古不變的話題。只不過,相比於交付一個容器和容器鏡像, Kubernetes 項目正在嘗試明確的定義雲時代“應用”的概念。在這裏,應用是一組容器的有機組合,同時也包括了應用運行所需的網絡、存儲的需求的描述。而像這樣一個“描述”應用的 YAML 文件,放在 etcd 裏存起來,然後通過控制器模型驅動整個基礎設施的狀態不斷地向用戶聲明的狀態逼近,就是 Kubernetes 的核心工作原理了。

未來:應用交付的革命不會停止

說到這裏,我們已經回到了 2019 年這個軟件交付已經被 Kubernetes 和容器重新定義的時間點。

在這個時間點上,Kubernetes 項目正在繼續嘗試將應用的定義、管理和交付推向一個全新的高度。我們其實已經看到了現有模型的一些問題與不足之處,尤其是聲明式 API 如何更好的與用戶的體驗達成一致。在這個事情上,Kubernetes 項目還有不少路要走,但也在快速前行。

我們也能夠看到,整個雲計算生態正在嘗試重新思考 PaaS 的故事。Google Cloud Next 2019 上發佈的 Cloud Run,其實已經間接宣告了 GAE 正憑藉 Kubernetes 和 Knative 的標準 API “浴火重生”。而另一個典型的例子,則是越來越多很多應用被更“極端”的抽象成了 Function,以便完全託管於與基礎設施無關的環境(FaaS)中。如果說容器是完整的應用環境封裝從而將應用交付的自由交還給開發者,那麼 Function 則是剝離了應用與環境的關係,將應用交付的權利交給了 FaaS 平臺。我們不難看到,雲計算在向 PaaS 的發展過程中被 Docker “攪局”之後,又開始帶着“容器”這個全新的思路向 “PaaS” 不斷收斂。只不過這一次,PaaS 可能會換一個新的名字叫做:Serverless。

我們還能夠看到,雲的邊界正在被技術和開源迅速的抹平。越來越多的軟件和框架從設計上就不再會跟某雲產生直接綁定。畢竟,你沒辦法撫平用戶對商業競爭擔憂和焦慮,也不可能阻止越來越多的用戶把 Kubernetes 部署在全世界的所有云上和數據中心裏。我們常常把雲比作“水、電、煤”,並勸誡開發者不應該關心“發電”和“燒煤”的事情。但實際上,開發者不僅不關心這些事情,他們恐怕連“水、電、煤”是哪來的都不想知道。在未來的雲的世界裏,開發者完全無差別的交付自己的應用到世界任何一個地方,很有可能會像現在我們會把電腦插頭插在房間裏任何一個插孔裏那樣自然。

這也是爲什麼,我們看到越來越多的開發者在討論“雲原生”。

我們無法預見未來,但代碼與技術演進的正在告訴我們這樣一個事實:未來的軟件一定是生長於雲上的。這將會是“軟件交付”這個本質問題的不斷自我革命的終極走向,也是“雲原生”理念的最核心假設。而所謂“雲原生”,實際上就是在定義一條能夠讓應用最大程度利用雲的能力、發揮雲的價值的最佳路徑。在這條路徑上,脫離了“應用”這個載體,“雲原生”就無從談起;容器技術,則是將這個理念落地、將軟件交付的革命持續進行下去的重要手段之一。

而至於 Kubernetes 項目,它的確是整個“雲原生”理念落地的核心與關鍵所在。但更爲重要的是,在這次關於“軟件”的技術革命中,Kubernetes 並不需要嘗試在 PaaS 領域裏分到一杯羹:它會成爲連通“雲”與“應用”的高速公路,以標準、高效的方式將“應用”快速交付到世界上任何一個位置。而這裏的交付目的地,既可以是最終用戶,也可以是 PaaS/Serverless 從而催生出更加多樣化的應用託管生態

“雲”的價值,一定會迴歸到應用本身。


最新一屆的QCon即將於5月6-10日在北京國際會議召開。除了涵蓋架構、移動、運維、安全、大數據等經典方向以外,QCon還策劃了智慧零售、用戶增長、Chaos Engineering 等新興方向的話題,超150位技術大咖將分享最值得參考的技術實踐案例。訪問QCon北京2019查看大會日程,收穫技術成長。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章