如今,Kube.NETes 已經成為分布式集群管理系統和公有云/私有云的事實標準。實際上,Kubernetes 是一個分布式操作系統,它是 google 在分布式操作系統領域十余年工程經驗和智慧的結晶,而 Google 一直以來都管理著世界上最大的分布式集群,在分布式操作系統領域的研究和認識領先于全世界。因此,2014年發布的 Kubernetes 能在短短幾年時間內就超越了諸多前輩,大獲成功。
作為分布式操作系統,Kubernetes(包括其前代產品 Google Borg)的出現遠遠晚于 UNIX、linux、windows 等著名的單機操作系統,Kubernetes 架構設計自然地繼承了很多單機操作系統的珍貴遺產,微內核架構就是這些遺產中最重要的一份。在本文接下來的部分,我們將專注于微內核(microkernel)這個概念及其對 Kubernetes 架構的影響。
一、什么是微內核?
在介紹微內核的時候,我們有必要同時回顧一下單機操作系統的歷史,以理解其價值所在。本章中以「操作系統」指代「單機操作系統」。
1.1 UNIX 的興起
電子計算機誕生之后,在上個世紀70年代以前,出現過許許多多的操作系統,DOS、OS/360、Multics 是其中的知名代表,這是操作系統領域的拓荒時代。20年來的拓荒孕育出了偉大的成果:隨著 CPU 技術的發展,UNIX 于1969年誕生了,這是一個真正意義上的分時操作系統。
借助新的 CPU 技術的支持,UNIX 將軟件系統劃分為內核(kernel)和用戶態程序(userland programs)兩部分。
內核是一組中斷處理程序的集合,把硬件的能力封裝為操作系統功能調用(system calls),用戶態程序通過系統調用使用硬件功能,用戶態程序運行于各自的進程中,所有用戶態進程都共享同一個內核,每當系統調用或中斷發生,UNIX 便陷入(trap)內核,內核執行系統調用,與此同時,內核中的分時調度算法將決定把 CPU 交給哪個進程,并管理進程的上下文切換。另外,UNIX 把(幾乎)所有硬件都封裝為文件。
UNIX 還提供了一個特殊的用戶態程序 shell,供用戶直接使用系統,通過內核提供的進程間通信能力,shell讓 用戶可以把一系列應用程序組合起來,處理復雜的需求,作者稱這個設計思想為「KISS」(Keep It Simple and Stupld)。UNIX 的所有設計思想在當時是都是非常了不起的創舉。
UNIX 不但自身對業界產生了巨大的直接貢獻,還成為所有現代操作系統的藍本,兩位作者 Ken Tompson 和 Dennis Ritchie 因此榮獲1983年度的圖靈獎。
UNIX 誕生于貝爾實驗室,該實驗室屬于美國國家電信電報公司(AT&T),見識到 UNIX 的強大威力之后,AT&T 做出了一個看似無私的決定:將 UNIX 開源(初期只對大學開源),這使得所有現代操作系統得以誕生。雖然 AT&T 最終被分拆,輝煌不再,但這個決定對人們的貢獻綿延至今。在21世紀20年代的今天,無論是 macOS、Windows、Linux,都直接受到 UNIX 的影響,而 IOS 來自 MacOS,Android 來自 Linux,因此 UNIX 的靈魂仍然活在每個人的手機中、活在每個手機 App 后臺的服務中。
此外,UNIX 誕生之時,還附送了一項比操作系統本身價值更大的副產品:Dennis Ritchie 為開發 UNIX 設計了C語言,C語言成為了所有流行的現代編程語言的主要設計來源,不僅如此,C語言在其誕生近40年后的今天,仍然是最重要的編程語言之一。
值得一提的是,當時 UNIX 的主要開放對象是伯克利、卡內基梅隆等研究型大學,文理學院規模較小,沒有研究生項目,不屬于 AT&T 的主要開放目標,因此 Olivet College 畢業的一位小哥未受到 UNIX 思潮的影響。這位名叫 David Cutler 的軟件天才于1975年在 DEC 設計了 VMS 操作系統,VMS 和最初的 UNIX 一樣,運行在 PDP-11 上,但并不是基于 UNIX,而是獨立設計的。VMS 在業界沒有掀起大浪,以兼容 UNIX 告終。后來 David Cutler 離開 DEC,加入微軟,在那里譜寫了屬于他自己的傳奇。有趣的是,喬布斯也曾在文理學院就讀,看來美國文理學院的學生是不走尋常路的。
1.2 微內核的興起
UNIX「一切皆文件」的設計帶來了用戶程序設計的很多便利,但它要求所有對硬件的封裝都要在內核態,因此內核中模塊的 bug 會讓整個系統受到影響,比如說,如果某個設備驅動有內存泄漏,所有使用該設備的用戶態進程都會有內存泄漏,如果某個內核模塊有安全漏洞,整個系統的安全性將不再可控。
為了解決這類問題,上個世紀70年代,操作系統研究者們開始發展「微內核」的概念,微內核的本質是讓操作系統的內核態只保留內存地址管理、線程管理和進程間通訊(IPC)這些基本功能,而把其它功能如文件系統、設備驅動、網絡協議棧、GUI 系統等都作為單獨的服務,這類服務一般是單獨的用戶態 daemon 進程。
用戶態應用程序通過 IPC 訪問這些服務,從而訪問操作系統的全部功能,如此一來,需要陷入內核的系統調用數量將大大減少,系統的模塊化更加清晰。同時系統更加健壯,只有內核中的少量系統調用才有權限訪問硬件的全部能力,如設備驅動的問題只會影響對應服務,而不是影響整個系統。和 micro kernel 相對,UNIX 的設計被稱為 monolithic kernel。
UNIX 開放后,AT&T 繼續著版本迭代,而各大學基于 AT&T 的 UNIX 開發了很多新的操作系統內核,其中較為知名的有:
- BSD,monolithic,由伯克利的傳奇人物 Bill Joy 于1974年發布(據說 Bill Joy 花三天便完成了 BSD 內核的第一個版本開發,Bill Joy 的作品還包含第一個 TCP/IP 協議棧、vi、Solaris、SPARK 芯片等等)。該內核對業界影響非常之大,后來發展為 FreeBSD、OpenBSD、NetBSD 等分支。現代操作系統如 Solaris、MacOS X、Windows NT 對其多有借鑒。
- Mach,微內核,由卡內基梅隆大學于1984年發布,主要作者是 CMU 的兩位研究生 Avie Tevanian 和 Rick Rashid。該內核對業界影響也很大,GNU Hurd、MacOS X 對其多有借鑒,但該項目本身以失敗告終。
- MINIX,微內核,由阿姆斯特丹自由大學(Vrije Universiteit Amsterdam)的 Andrew Tanenbaum 教授于1987年發布。無數計算機系學生通過 MINIX 及其配套教材掌握了操作系統的設計原理,Linux 的初始版本就是基于 MINIX 復刻的。MINIX 雖然著名,但主要用于教學,從未在工業界獲得一席之地。
1.3 微內核的沉寂
從上世紀90年代至本世紀10年代,UNIX 和 VMS 的后裔們展開了一場混戰,從結果來看,微內核的概念雖然美好,但現實非常殘酷:
- MINIX 僅限于教學,而基于 MINIX 設計的 Linux 是 monolithic 系統,反而大獲成功。Mach 對業界影響深遠,但本身并未得到大規模應用,其繼承者 GNU Hurd 一直在開發中,從未能應用。
- Windows 的 NTOS 內核是 David Cutler 基于他原來在 DEC 獨立設計的系統 VMS 設計的(VMS 和 UNIX 無關)。NTOS 借鑒了微內核的思想和 BSD 的一些代碼,但最終 David Cutler 決定將所有服務(如 GUI)都放到內核態而非用戶態,因此 Windows NT 在軟件架構上和微內核一致,而實際運行和 monolithic 內核一致,被稱為 hybrid kernel。
- MacOS X 基于 NextStep OS 設計,NextStep 是 Avie Tevanian 設計的,Avie Tevanian 是 Mach 的主要設計者,博士畢業后,蓋茨和喬布斯都邀請過他,他去了 Next,他在 CMU 的好友 Rick Rashid 則去微軟作為 David Cutler 的首席助手,據說 Avie Tevanian 在 Next 每天用計算器算自己沒去微軟而損失的股票增值。跟喬布斯回到蘋果后,Avie 基于 NextStep 和 BSD 的代碼設計了 OS X,巧的是,OS X 也采用了 hybrid kernel 的架構,最終大獲成功,還能在 PowerPC 和 x86 兩種指令架構間無縫切換。
在幾位操作系統技術巨擎中,除 Linus Torvalds 外,無論是 David Cutler 和 Andrew Tanenbaum,還是 Avie Tevanian 和 Rick Rashid,都是微內核架構的領袖級人物,但最終他們都沒有將微內核徹底落地,這是有原因的。
微內核操作系統訪問系統服務的效率比 monolithic 操作系統要低得多,舉例而言,在 Linux 中,系統調用(比如 open)只要陷入內核一次,也就是先切換 CPU 到高權限模式,再切回低權限模式。如果在一個微內核操作系統中,用戶調用 open 就需要先拼裝一條 IPC 請求消息,發送給對應的文件系統服務進程,隨后從文件系統服務進程獲取IPC響應消息并解包,拿到調用結果,這樣一來,消息帶來的數據拷貝和進程上下文切換都會帶來很多開銷。消息需要拷貝是因為用戶態進程間不能相互訪問內存地址,而內核的代碼可以訪問任何用戶態進程的任何內存地址。正是因為性能原因,OS X 和 Windows 都選擇了 hybrid kernel 的架構,NTOS 甚至在內核中集成了 GUI 子系統,以帶來更好的用戶體驗。
簡單來說,在電腦性能不佳的情況下,我們會發現 Windows 的鼠標箭頭更加“跟手”,即使系統接近死機,Windows 系統的鼠標箭頭仍然可以活動。Windows XP 能在 Windows 98 這樣「珠玉在前」的上代產品后獲得更大的成功,和 NTOS 對性能的密切關注是分不開的,相比之下,蘋果固然在1980年代中期就有初代 Machintosh 這樣的壯舉,但因為喬布斯無法說服銷售團隊換一根更強的內存條,因此初代 Mac 的性能較差,運行程序非常之慢,未能獲得應得的藍海成功。
二、Kubernetes 和微內核
性能問題對單機操作系統來說可能是至關重要的,但對分布式操作系統并非如此,分布式操作系統作為「幕后功臣」,不需要直接面對用戶,而單機性能上的小小損失可以用更多機器來彌補,在這個前提下,更好的架構往往更加重要。
2.1 Borg 的誕生
在單機操作系統大戰快要分出勝負之時,Google 這家行業新寵正準備 IPO,用現在的話來說,Google 那時是一家「小巨頭」:已經初露鋒芒,不容小覷,但巨頭們彼時正陷入戰爭泥潭,無暇顧及之。
2003年,為了更好地支持新版本的搜索引擎(基于MapReduce),使其能服務好億萬用戶,Google 開始了大規模集群管理系統的開發,這個系統叫做 Borg,它的目標是管理以萬臺為單位的計算機集群。
雖然剛開始只有3、4個人的小團隊,但 Borg 還是跟上了 Google 的飛速發展,證明了它的潛力,最終 Google 的全部機器都由 Borg 管理,MapReduce、Pregel 等著名系統都建立于 Borg 之上。從操作系統的角度來看,Borg 是一個 monolithic 系統,任何對系統的功能升級都需要深入到 Borg 底層代碼來修改支持。
在 Google 這樣成熟的技術型公司中,有很多優秀的工程師,因此這個問題在內部系統中并不算嚴重。但如果是公有云,必然要接入許多第三方應用的需求,一家公司的工程師團隊再強大,也無法把業界所有其他系統都接入 Borg,這時系統的可擴展性將非常重要。
在2010年左右,隨著 Google 中國部門的撤銷,很多優秀的 Google 工程師加入了 BAT 等中國公司,其中一部分加入了騰訊搜搜。這些前 Googler 加入騰訊后,復刻了 Google 的許多系統,技術上也很出色,其中 Borg 的復制品叫做 TBorg,后來改名為 Torca。Torca 在搜搜的廣告業務中起到了非常重要的作用,后來由于騰訊業務調整,搜搜與搜狗合并,Torca 在騰訊內部失去用戶,逐漸停止了維護。
在 Borg 上線幾年后,Google 意識到 monolithic 架構的問題和瓶頸,于是又一支小團隊開始了 Omega 系統的研發。Omega 系統繼承的是微內核的思想,新的功能升級幾乎不需修改底層代碼就能完成,它比 Borg 更加靈活,有更好的伸縮性。但因為當時 Google 的全部系統已經搭建在 Borg 之上了,由于 Borg 的 monolithic 特性,MapReduce 等系統都緊密綁定到 Borg 核心代碼,不但無縫遷移到 Omega 系統是不可能的,遷移還要花巨大的人力、時間和試錯成本,因此即使核心成員堅持不懈地推動,Omega 系統在 Google 仍未能取得成功。
有趣的是,Omega 項目的核心成員之一 Brendan Burns 的職業軌跡和操作系統領域的大前輩 David Cutler 有不少相似之處。
- 他們同樣畢業于文理學院:David Cutler 畢業于 Olivet College,Brendan Burns 畢業于 Williams College。
- 他們同樣在畢業后加入了一家傳統行業的巨頭:David Cutler 畢業后加入杜邦,Brendan Burns 畢業后加入湯姆森金融。
- 正如教父所說,一個男人只能有一種命運,Cutler 和 Burns 在這兩家傳統巨頭學會了寫代碼,也許就是在那時,他們發現了自己在軟件上的天分,發現了自己的命運是構建新一代操作系統。因此他們同樣在第二份工作中選擇了當時最炙手可熱的科技巨頭:David Cutler 加入 DEC,Brendan Burns 加入 Google。
- 他們同樣在微軟到達了職業生涯的頂峰:Brendan Burns 現如今已是微軟的 Corporate VP,而 David Cutler 老爺子早已是微軟唯一的 Senior Technical Fellow,據傳微軟甚至有條規定,Cutler 的技術職級必須是全公司最高的,任何人升到 Cutler 的 level,Cutler 就自動升一級。
2.2 Kubernetes 的誕生
在單機操作系統時代,hybrid kernel 盛行一時,這證明了微內核在軟件架構上的成功,但因為性能問題,又沒有任何一個成功的內核采用「純粹的」微內核架構,因此微內核從實用角度上來說是失敗的。
和單機操作系統時代中微內核架構的失敗原因不同,Omega 在 Google 公司內部的失敗和性能問題無關,只是歷史遺留問題的影響。對開源社區和大部分公司來說,尚無能和 Borg 相媲美的系統,也沒有歷史負擔,因此幾年后,Google 決定開源 Omega 這一超越 Borg 的新一代分布式操作系統,將其命名為 Kubernetes。
為了介紹清楚 Kubernetes 和微內核的關系,以及微內核架構為 Kubernetes 帶來的優勢,這里有必要引入一些技術細節。
上文中提到,單機操作系統的系統調用需要「陷入」內核,所謂的陷入(trap)也叫做中斷(interrupt),無論內核是什么類型,單機操作系統都需要在啟動時將系統調用注冊到內存中的一個區域里,這個區域叫做中斷向量(Interrupt Vector)或中斷描述符表(IDT,Interrupt Descriptor Table)。
當然,現代操作系統的中斷處理非常復雜,系統調用也很多,因此除了IDT之外,還需要一張系統調用表(SCV,System Call Vector),系統調用通過一個統一的中斷入口(如 INT 80)調用某個中斷處理程序,由這個中斷處理程序通過 SCV 把系統調用分發給內核中不同的函數代碼。因此 SCV 在操作系統中的位置和在星際爭霸中的位置同樣重要。對微內核架構來說,除了 SCV 中的系統調用之外,用戶態服務提供什么樣的系統能力,同樣需要注冊到某個區域。
與此類似,Kubernetes 這樣的分布式操作系統對外提供服務是通過 API 的形式,分布式操作系統本身提供的 API 相當于單機操作系統的系統調用,每個 API 也需要能夠注冊到某個位置。對 Kubernetes 來說,API 會注冊到 ectd 里。Kubernetes 本身提供的相當于系統調用的那些 API,通過名為 Controller 的組件來支持,由開發者為 Kubernetes 提供的新的 API,則通過 Operator 來支持,Operator 本身和 Controller 基于同一套機制開發。
這和微內核架構的思想一脈相承:Controller 相當于內核態中運行的服務,提供線程、進程管理和調度算法等核心能力,Operator 則相當于微內核架構中 GUI、文件系統、打印機等服務,在用戶態運行。
因此,Kubernetes 的工作機制和單機操作系統也較為相似,etcd 提供一個 watch 機制,Controller 和 Operator 需要指定自己 watch 哪些內容,并告訴 etcd,這相當于是微內核架構在 IDT 或 SCV 中注冊系統調用的過程。
以 Argo 為例,Argo 是個 Operator,提供在 Kubernetes 中執行一個 DAG 工作流的能力。用戶在使用 kubectl 命令提交 Argo 任務時,實際是讓 kubectl 將 Argo 的 yaml 提交給 Kubernetes 的 API Server,API Server 將 yaml 中的 Key-Value 數據寫入 etcd,etcd 將會提醒那些正在 watch 指定 Key 的服務。在我們的例子中,這個服務也就是 Argo。這正像是微內核架構里用戶進程請求用戶態服務的過程。
Argo 得到 etcd watch 的 http 請求,去 etcd 讀出 yaml 中的數據并解析, 然后知道要去啟動什么容器,并通過 API 要求 Kubernetes 啟動相應的容器。Kubernetes scheduler 是一個 Controller,在收到啟動容器請求后,分配資源,啟動容器。這是微內核架構中用戶進程通過系統調用啟動另一個進程的過程。
當然,Kubernetes 和單機操作系統也有不同之處:Kubernetes 沒有明確的「陷入」過程,而微內核架構的單機操作系統在訪問系統調用時需要陷入,在訪問用戶態服務時則不需要陷入。但是,Kubernetes 可以為不同的服務設置不同的權限,這一點在一定程度上類似于單機操作系統中內核態和用戶態的 CPU 權限的區別。
微內核在架構上的優勢在 Kubernetes 中顯露無遺:在 Borg 中,開發者想要添加新的子系統是非常復雜的,往往需要修改 Borg 底層代碼,而新系統也因此會綁定到 Borg 上。而對 Kubernetes 來說,開發者只需要基于 Kubernetes 提供的 SDK 實現一個 Operator,就能夠添加一組新的 API,而不需要關注 Kubernetes 的底層代碼。Argo、Kubeflow 都是 Operator 的應用。任何已有軟件都可以方便地通過 Operator 機制集成到 Kubernetes 中,因而 Kubernetes 非常適合作為公有云的底層分布式操作系統,正因如此,Kubernetes 在2014年年中發布,經過2015年一年的成長,在2016年便成為業界主流,對于沒有歷史負擔的公司,也將 Kubernetes 作為內部云的底層系統使用。
三、尾聲
在這篇文章中,我們介紹了單機操作系統的發展簡史,介紹了微內核架構在這個歷史進程中從興起到衰落的過程,也介紹了微內核架構在 Kubernetes 中重新煥發生機的過程。總的來說,顯著超前于時代的技術雖然未必能在被提出的時代取得成功,但一定會在多年后,在時代跟上來之后,拿回屬于自己的榮耀。微內核架構在單機操作系統的時代和云計算的時代的不同遭遇證明了這一點,深度學習在低算力時代和高算力時代的不同遭遇也證明了這一點。
值得一提的是,在 Kubernetes 之后,Google 推出了 Fuchsia 作為 Android 可能的替代品。而 Fuchsia 基于 Zircon 內核開發,Zircon 基于 C++ 開發,正是微內核架構。在算力井噴的現代,除了在分布式操作系統領域,微內核能否也在手機/物聯網操作系統領域復興,讓我們拭目以待。
文章來源:
https://mp.weixin.qq.com/s?__biz=MzUzMzU5Mjc1Nw==&mid=2247486583&idx=1&sn=de15ec3224bc4f00b7e77c9f7481eee0&chksm=faa0e3adcdd76abb1b771514c09a486483f008dd911c27295b52da7979cf7509858134ffaf01&scene=21