我們知道,Kubernetes是Google根據(jù)自己的Borg系統(tǒng),采用go語言重構(gòu)誕生的,那么我們可以先看看Borg系統(tǒng)的架構(gòu)。
1、Borg系統(tǒng)架構(gòu)解讀
Borg是一個C++寫的的集群管理系統(tǒng),它負責(zé)權(quán)限控制、調(diào)度、啟動、重新啟動和監(jiān)視全部的Google中運行的應(yīng)用程序。其高可用架構(gòu)如下所示:
-
BorgMaster是整個集群的大腦,負責(zé)維護整個集群的狀態(tài),并將數(shù)據(jù)持久化到Paxos存儲中;
-
Scheduer負責(zé)任務(wù)的調(diào)度,根據(jù)應(yīng)用的特點將其調(diào)度到具體的機器上去;
-
Borglet負責(zé)真正運行任務(wù)(在容器中);
-
borgcfg是Borg的命令行工具,用于跟Borg系統(tǒng)交互,一般通過一個配置文件來提交任務(wù)。

它有三個好處:
-
隱藏資源管理和故障處理的細節(jié),因此其用戶可以專注于應(yīng)用程序開發(fā);
-
提供高可靠性和高可用性操作,支持的應(yīng)用也是如此;
-
使我們能夠有效地在數(shù)萬臺機器上運行工作負載。
由上圖可知Borg的中心控制模塊叫BorgMaster(包含主進程、調(diào)度器), 每個節(jié)點模塊叫Borglet,所有組件均使用C++編寫。
1.1、borgmaster主進程
BorgMaster主進程負責(zé)處理客戶端RPC調(diào)用(支持包括web瀏覽器、命令行工具、borgcfg方式),管理系統(tǒng)中所有對象的狀態(tài)機,與borglet進行通信。
BorgMaster在邏輯上是一個進程,但是有5個副本(單數(shù)),每個副本都維護cell狀態(tài)的一份內(nèi)存副本,cell狀態(tài)同時在高可用、分布式、基于Paxos的存儲系統(tǒng)中做本地磁盤持久化存儲。
一個單一的被選舉的master既是Paxos leader, 也是狀態(tài)管理者。當(dāng)cell啟動或者被選舉master掛掉時,系統(tǒng)會選舉Borgmaster,選舉機制按照Paxos算法流程進行。選舉master的過程通常會消耗10秒,在一些規(guī)模較大的cell會消耗1分鐘左右。
BorgMaster的狀態(tài)會定時設(shè)置checkpoint, 具體形式就是在Paxos store中存儲周期性的鏡像snapshot和增量更改日志。其作用可以存儲borgmaster的狀態(tài),修復(fù)問題,離線模擬等。
1.2、scheduling調(diào)度器
一個Borg作業(yè)Job具有name、owner、task數(shù)量等屬性,Job具有約束性來強制其任務(wù)運行在特定屬性的機器上。
當(dāng)job被提交時,borgmaster會將其記錄到paxos store中,并將task增加到等待隊列中,調(diào)度器通過異步的方式掃描隊列將機器分配給任務(wù)并持久化到paxos(persistent store)中,調(diào)度過程主要包括可行性檢查和打分。
可行性檢查主要用于解決硬約束,找到一組滿足硬約束的機器;打分則是滿足軟約束,在可行的機器中根據(jù)用戶偏好為機器打分,用戶偏好主要是系統(tǒng)內(nèi)置的標(biāo)準(zhǔn),如:被搶占的task的優(yōu)先級和數(shù)量最小化,具有任務(wù)軟件包的機器、 分散任務(wù)到不同的失敗域中,將高優(yōu)先級和低優(yōu)先級的task分配到同一個node上,使得高優(yōu)先的任務(wù)可以搶占低優(yōu)先級的任務(wù)等。
borgmaster一開始使用E-PVN進行打分,其會將任務(wù)分散到不同的機器上,稱為worst fit;而best fit會盡量使用緊湊的機器以減少資源碎片。考慮到系統(tǒng)中不同類型任務(wù)單額資源需求,采用混合的模型進行打分。
如果對于—個新task沒有充足的資源、那么系統(tǒng)會殺死低優(yōu)先級的任務(wù),殺死的低優(yōu)先級的任務(wù)會被放置在等待隊列中。任務(wù)啟動延遲平均在25秒,有80%的時間花費在包安裝上。因此在調(diào)度的時候盡量把任務(wù)調(diào)度在含有包的機器上,同時因為包是不變的,所以可以共享和緩存,同時還提供了一些并行分發(fā)包的協(xié)議。
1.3、Borglet
borglet是運行在每臺機器上的代理,負責(zé)啟動和停止task、重啟任務(wù)、管理本地資源、向master和監(jiān)控模塊匯報自己的狀態(tài)。master會周期性的向boralet拉取其當(dāng)前的狀態(tài).這樣做能夠控制通信速度避免"恢復(fù)風(fēng)暴”。
為了性能擴展,master副本會運行一個無狀態(tài)的link shard去處理與部分borglet的通信,但重新選舉時會重新分區(qū),master副本會聚合和壓縮信息,向被選舉的master報告狀態(tài)機的不同部分,減少更新負擔(dān)。如果borglet多輪都沒有進行響應(yīng)會被標(biāo)記為down。運行在上面的任務(wù)會被重新調(diào)度至其他機器,如果通信恢復(fù),master會通知boralet殺死已經(jīng)重調(diào)度的任務(wù)保證一致性。
解讀:borglet的設(shè)計與其他調(diào)度系統(tǒng)相同,提供匯報功能。不同的是borg中采用拉取的方式進行,也就是borglet主動去paxos拉取屬于自己的任務(wù)。另外borg中的副本會與一些borglet通信以此方式來減少更新負擔(dān)。
1.4、Kubernetes吸取的優(yōu)缺點
-
在Borg中,Job是用來對task進行分組的唯一方式,這種方式相當(dāng)不靈活,導(dǎo)致用戶自己發(fā)展出很多方式來實現(xiàn)更靈活對分組。Kuberntes吸取了Borg的這個教訓(xùn),引入了Labels,使Pod可以被靈活地分組。
-
在Borg中,1個node 上的所有task共享node的ip,這直接導(dǎo)致端口也成為一種資源,在調(diào)度時候需要被考慮。Kubernetes為每個Pod分配獨立的P。
-
Kubernetes借鑒了 Alloc (node上的一塊可以被多個task共享的資源),設(shè)計了Pod (多個容器的封裝)。這種設(shè)計,可以將1個pod中的任務(wù)分拆成不同 的容器,由不同的團隊開發(fā),特別是一些輔助性的任務(wù),例如日志采集等。
-
Borg中task、job的命名機制被kubernetes借鑒,提供了service等特性。
-
Borg將系統(tǒng)內(nèi)部的事件、task的日志暴露給用戶,提供了不同級別的UI和調(diào)試工具,使幾千個用戶能夠自助地使用Borg。Kubernetes吸收了Borg的這些特性,引入cAdvisor、Elasticsearch/Kibana、Fluentd等組件。
-
Borg采用中心式設(shè)計,管理功能集中于Master,這種設(shè)計方便了后續(xù)更多特性引入以及規(guī)模的擴展。Kubernetes更進一步,apiserver只負責(zé)處理請求和狀態(tài)維護,集群的管理邏輯被拆分到多個更精悍、內(nèi)聚的controller中。
2、 Kubernetes組件說明
2.1、Kubernetes整體架構(gòu)
Kubernetes 提供了一種靈活、松耦合的機制,與大多數(shù)分布式計算平臺一樣,Kubernetes 集群由至少一個主節(jié)點和多個計算節(jié)點組成。master負責(zé)公開應(yīng)用程序接口(API)、調(diào)度部署和管理整個集群。每個節(jié)點運行一個容器,例如Docker或rkt,與主服務(wù)器進行通信。如下圖所示:


節(jié)點是 Kubernetes 集群的主力。它們對應(yīng)用程序暴露自己的計算、網(wǎng)絡(luò)和存儲資源。節(jié)點可以是在云中運行的虛擬機 (VM),也可以是在數(shù)據(jù)中心內(nèi)運行的裸機服務(wù)器。同時節(jié)點還可運行用于日志記錄、監(jiān)控、服務(wù)發(fā)現(xiàn)和其余可選的附加組件。如下圖所示:

2.2、Kubernetes組件概述
Kubernetes借鑒了Borg的設(shè)計理念,比如Pod、Service、Label和單Pod單IP等。Kubernetes的整體架構(gòu)跟Borg非常像,官方的如下圖所示:
Kubernetes 遵循非常傳統(tǒng)的客戶端/服務(wù)端的架構(gòu)模式,客戶端可以通過 RESTful 接口或者直接使用 kubectl 與 Kubernetes 集群進行通信,Kubernetes主要由Master組件以及一系列節(jié)點(Node)組件構(gòu)成,其中 Master 節(jié)點主要負責(zé)存儲集群的狀態(tài)并為 Kubernetes 對象分配和調(diào)度資源。
2.2.1、Master組件
-
kube-apiserver:所有服務(wù)訪問的唯一入口,提供認證、授權(quán)、訪問控制、API 注冊和發(fā)現(xiàn)等機制,用于對外提供 RESTful 的接口暴露Kubernetes API,包括用于查看集群狀態(tài)的讀請求以及改變集群狀態(tài)的寫請求,也是唯一一個與 etcd 集群通信的組件。
-
etcd:etcd的官方將其定位成一個可信賴的分布式鍵值存儲服務(wù),能夠為整個分布式集群存儲一些關(guān)鍵數(shù)據(jù),協(xié)助分布式集群正常運轉(zhuǎn),因此作為兼具一致性和高可用性的鍵值數(shù)據(jù)庫,保存了 Kubernetes 所有集群數(shù)據(jù),使用時需要為etcd數(shù)據(jù)提供備份計劃。推薦在Kubernetes集群中使用etcs v3,v2版本已經(jīng)棄用。
-
kube-scheduler: 該組件監(jiān)視那些新創(chuàng)建的未指定運行節(jié)點的 Pod,并選擇節(jié)點讓 Pod 在上面運行。調(diào)度決策考慮的因素包括單個 Pod 和 Pod 集合的資源需求、硬件/軟件/策略約束、親和性和反親和性規(guī)范、數(shù)據(jù)位置、工作負載間的干擾和最后時限。
-
kube-controller-manager: 在主節(jié)點上運行控制器的組件,從邏輯上講,每個控制器都是一個單獨的進程,但是為了降低復(fù)雜性,它們都被編譯到同一個可執(zhí)行文件,并在一個進程中運行。這些控制器包括:節(jié)點控制器(負責(zé)在節(jié)點出現(xiàn)故障時進行通知和響應(yīng))、副本控制器(負責(zé)為系統(tǒng)中的每個副本控制器對象維護正確數(shù)量的 Pod)、端點控制器(填充端點 Endpoints 對象,即加入 Service 與 Pod))、服務(wù)帳戶和令牌控制器(為新的命名空間創(chuàng)建默認帳戶和 API 訪問令牌)。
-
cloud-controller-manager:云控制器管理器負責(zé)與底層云提供商的平臺交互,云控制器管理器是Kubernetes版本1.6中引入的,目前還是Alpha的功能。云控制器管理器僅運行云提供商特定的(controller loops)控制器循環(huán),可以通過將--cloud-provider flag設(shè)置為external啟動kube-controller-manager ,來禁用控制器循環(huán)。cloud-controller-manager 具體功能:節(jié)點(Node)控制器、路由(Route)控制器、Service控制器、卷(Volume)控制器。(圖中未體現(xiàn),同kube-controller-manager一樣與kube-apiserver交互)
除了以上基礎(chǔ)組件外還有插件(addon),插件是實現(xiàn)集群pod和Services功能的 。Pod由Deployments,ReplicationController等進行管理。Namespace 插件對象是在kube-system Namespace中創(chuàng)建。
-
CoreDNS:可以為集群中的 SVC 創(chuàng)建一個域名 IP 的對應(yīng)關(guān)系解析的 DNS 服務(wù),雖然不嚴格要求使用插件,但Kubernetes集群都應(yīng)該具有集群 DNS,集群DNS是一個DNS服務(wù)器,能夠為 Kubernetes services提供 DNS記錄。由Kubernetes啟動的容器自動將這個DNS服務(wù)器包含在他們的DNS searches中。
-
kube-ui:給K8s集群提供了一個B/S架構(gòu)的訪問入口,提供集群狀態(tài)基礎(chǔ)信息查看。
-
Cluster-level logging:負責(zé)保存容器日志,搜索/查看日志。
-
Prometheus:給K8s集群提供資源監(jiān)控的能力。
-
Ingress Controller:官方只能夠?qū)崿F(xiàn)四層的網(wǎng)絡(luò)代理,而 Ingress 可以實現(xiàn)七層的代理
-
Federation:提供一個可以跨集群中心多 K8s 的統(tǒng)一管理功能,提供跨可用區(qū)的集群
2.2.2、節(jié)點(Node)組件
Worker節(jié)點實現(xiàn)就相對比較簡單,它主要由 kubelet 和 kube-proxy 兩部分組成。
-
kubelet: 是工作節(jié)點執(zhí)行操作的agent,負責(zé)具體的容器生命周期管理,根據(jù)從數(shù)據(jù)庫中獲取的信息來管理容器,并監(jiān)視已分配給節(jié)點的pod,包含:安裝Pod所需的volume、下載Pod的Secrets、Pod中運行的docker(或experimentally,rkt)容器、定期執(zhí)行容器健康檢查、上報Pod狀態(tài),必要時新建一個pod副本、上報node節(jié)點狀態(tài)。
-
kube-proxy: 是一個簡單的網(wǎng)絡(luò)訪問代理,同時也是一個Load Balancer,通過在主機上維護網(wǎng)絡(luò)規(guī)則并執(zhí)行連接轉(zhuǎn)發(fā)來實現(xiàn)Kubernetes服務(wù)抽象。它負責(zé)將訪問到某個服務(wù)的請求具體分配給工作節(jié)點上同一類標(biāo)簽的 Pod。kube-proxy實質(zhì)就是通過操作防火墻規(guī)則(iptables或者ipvs)來實現(xiàn)Pod的映射。
-
Container Runtime: 容器運行環(huán)境是負責(zé)運行容器的軟件,Kubernetes 支持多個容器運行環(huán)境: Docker、 containerd、cri-o、 rktlet 以及任何實現(xiàn) Kubernetes CRI(容器運行環(huán)境接口)。
-
docker:用于運行容器。
-
RKT:rkt運行容器,作為docker工具的替代方案。
-
supervisord:是一個輕量級的監(jiān)控系統(tǒng),用于保障kubelet和docker運行。
-
fluentd:是一個守護進程,可提供cluster-level logging。
2.3、Kubernetes組件通信協(xié)議
下圖清晰表明了Kubernetes的架構(gòu)設(shè)計以及組件之間的通信協(xié)議。

2.4、Kubernetes分層架構(gòu)
Kubernetes設(shè)計理念和功能其實就是一個類似Linux的分層架構(gòu),如下圖所示:

-
核心層:Kubernetes最核心的功能,對外提供API構(gòu)建高層的應(yīng)用,對內(nèi)提供插件式應(yīng)用執(zhí)行環(huán)境
-
應(yīng)用層:部署(無狀態(tài)應(yīng)用、有狀態(tài)應(yīng)用、批處理任務(wù)、集群應(yīng)用等)和路由(服務(wù)發(fā)現(xiàn)、DNS解析等)
-
管理層:系統(tǒng)度量(如基礎(chǔ)設(shè)施、容器和網(wǎng)絡(luò)的度量),自動化(如自動擴展、動態(tài)Provision等)以及策略管理(RBAC、Quota、PSP、NetworkPolicy等)
-
接口層:kubectl命令行工具、客戶端SDK以及集群聯(lián)邦
-
生態(tài)系統(tǒng):在接口層之上的龐大容器集群管理調(diào)度的生態(tài)系統(tǒng),可以劃分為兩個范疇
- Kubernetes外部:日志、監(jiān)控、配置管理、CI、CD、Workflow、FaaS、OTS應(yīng)用、ChatOps等
- Kubernetes內(nèi)部:CRI、CNI、CVI、鏡像倉庫、Cloud Provider、集群自身的配置和管理等
2.5、Kubernetes API設(shè)計原則
對于云計算系統(tǒng),系統(tǒng)API實際上處于系統(tǒng)設(shè)計的統(tǒng)領(lǐng)地位,正如本文前面所說,Kubernetes集群系統(tǒng)每支持一項新功能,引入一項新技術(shù),一定會新引入對應(yīng)的API對象,支持對該功能的管理操作,理解掌握的API,就好比抓住了Kubernetes系統(tǒng)的牛鼻子。Kubernetes系統(tǒng)API的設(shè)計有以下幾條原則:
- 所有API應(yīng)該是聲明式的。正如前文所說,聲明式的操作,相對于命令式操作,對于重復(fù)操作的效果是穩(wěn)定的,這對于容易出現(xiàn)數(shù)據(jù)丟失或重復(fù)的分布式環(huán)境來說是很重要的。另外,聲明式操作更容易被用戶使用,可以使系統(tǒng)向用戶隱藏實現(xiàn)的細節(jié),隱藏實現(xiàn)的細節(jié)的同時,也就保留了系統(tǒng)未來持續(xù)優(yōu)化的可能性。此外,聲明式的API,同時隱含了所有的API對象都是名詞性質(zhì)的,例如Service、Volume這些API都是名詞,這些名詞描述了用戶所期望得到的一個目標(biāo)分布式對象。
- API對象是彼此互補而且可組合的。這里面實際是鼓勵A(yù)PI對象盡量實現(xiàn)面向?qū)ο笤O(shè)計時的要求,即“高內(nèi)聚,松耦合”,對業(yè)務(wù)相關(guān)的概念有一個合適的分解,提高分解出來的對象的可重用性。事實上,Kubernetes這種分布式系統(tǒng)管理平臺,也是一種業(yè)務(wù)系統(tǒng),只不過它的業(yè)務(wù)就是調(diào)度和管理容器服務(wù)。
- 高層API以操作意圖為基礎(chǔ)設(shè)計。如何能夠設(shè)計好API,跟如何能用面向?qū)ο蟮姆椒ㄔO(shè)計好應(yīng)用系統(tǒng)有相通的地方,高層設(shè)計一定是從業(yè)務(wù)出發(fā),而不是過早的從技術(shù)實現(xiàn)出發(fā)。因此,針對Kubernetes的高層API設(shè)計,一定是以Kubernetes的業(yè)務(wù)為基礎(chǔ)出發(fā),也就是以系統(tǒng)調(diào)度管理容器的操作意圖為基礎(chǔ)設(shè)計。
- 低層API根據(jù)高層API的控制需要設(shè)計。設(shè)計實現(xiàn)低層API的目的,是為了被高層API使用,考慮減少冗余、提高重用性的目的,低層API的設(shè)計也要以需求為基礎(chǔ),要盡量抵抗受技術(shù)實現(xiàn)影響的誘惑。
- 盡量避免簡單封裝,不要有在外部API無法顯式知道的內(nèi)部隱藏的機制。簡單的封裝,實際沒有提供新的功能,反而增加了對所封裝API的依賴性。內(nèi)部隱藏的機制也是非常不利于系統(tǒng)維護的設(shè)計方式,例如StatefulSet和ReplicaSet,本來就是兩種Pod集合,那么Kubernetes就用不同API對象來定義它們,而不會說只用同一個ReplicaSet,內(nèi)部通過特殊的算法再來區(qū)分這個ReplicaSet是有狀態(tài)的還是無狀態(tài)。
- API操作復(fù)雜度與對象數(shù)量成正比。這一條主要是從系統(tǒng)性能角度考慮,要保證整個系統(tǒng)隨著系統(tǒng)規(guī)模的擴大,性能不會迅速變慢到無法使用,那么最低的限定就是API的操作復(fù)雜度不能超過O(N),N是對象的數(shù)量,否則系統(tǒng)就不具備水平伸縮性了。
- API對象狀態(tài)不能依賴于網(wǎng)絡(luò)連接狀態(tài)。由于眾所周知,在分布式環(huán)境下,網(wǎng)絡(luò)連接斷開是經(jīng)常發(fā)生的事情,因此要保證API對象狀態(tài)能應(yīng)對網(wǎng)絡(luò)的不穩(wěn)定,API對象的狀態(tài)就不能依賴于網(wǎng)絡(luò)連接狀態(tài)。
- 盡量避免讓操作機制依賴于全局狀態(tài),因為在分布式系統(tǒng)中要保證全局狀態(tài)的同步是非常困難的。
2.6、控制機制設(shè)計原則
- 控制邏輯應(yīng)該只依賴于當(dāng)前狀態(tài)。這是為了保證分布式系統(tǒng)的穩(wěn)定可靠,對于經(jīng)常出現(xiàn)局部錯誤的分布式系統(tǒng),如果控制邏輯只依賴當(dāng)前狀態(tài),那么就非常容易將一個暫時出現(xiàn)故障的系統(tǒng)恢復(fù)到正常狀態(tài),因為你只要將該系統(tǒng)重置到某個穩(wěn)定狀態(tài),就可以自信的知道系統(tǒng)的所有控制邏輯會開始按照正常方式運行。
- 假設(shè)任何錯誤的可能,并做容錯處理。在一個分布式系統(tǒng)中出現(xiàn)局部和臨時錯誤是大概率事件。錯誤可能來自于物理系統(tǒng)故障,外部系統(tǒng)故障也可能來自于系統(tǒng)自身的代碼錯誤,依靠自己實現(xiàn)的代碼不會出錯來保證系統(tǒng)穩(wěn)定其實也是難以實現(xiàn)的,因此要設(shè)計對任何可能錯誤的容錯處理。
- 盡量避免復(fù)雜狀態(tài)機,控制邏輯不要依賴無法監(jiān)控的內(nèi)部狀態(tài)。因為分布式系統(tǒng)各個子系統(tǒng)都是不能嚴格通過程序內(nèi)部保持同步的,所以如果兩個子系統(tǒng)的控制邏輯如果互相有影響,那么子系統(tǒng)就一定要能互相訪問到影響控制邏輯的狀態(tài),否則,就等同于系統(tǒng)里存在不確定的控制邏輯。
- 假設(shè)任何操作都可能被任何操作對象拒絕,甚至被錯誤解析。由于分布式系統(tǒng)的復(fù)雜性以及各子系統(tǒng)的相對獨立性,不同子系統(tǒng)經(jīng)常來自不同的開發(fā)團隊,所以不能奢望任何操作被另一個子系統(tǒng)以正確的方式處理,要保證出現(xiàn)錯誤的時候,操作級別的錯誤不會影響到系統(tǒng)穩(wěn)定性。
- 每個模塊都可以在出錯后自動恢復(fù)。由于分布式系統(tǒng)中無法保證系統(tǒng)各個模塊是始終連接的,因此每個模塊要有自我修復(fù)的能力,保證不會因為連接不到其他模塊而自我崩潰。
- 每個模塊都可以在必要時優(yōu)雅地降級服務(wù)。所謂優(yōu)雅地降級服務(wù),是對系統(tǒng)魯棒性的要求,即要求在設(shè)計實現(xiàn)模塊時劃分清楚基本功能和高級功能,保證基本功能不會依賴高級功能,這樣同時就保證了不會因為高級功能出現(xiàn)故障而導(dǎo)致整個模塊崩潰。根據(jù)這種理念實現(xiàn)的系統(tǒng),也更容易快速地增加新的高級功能,因為不必擔(dān)心引入高級功能影響原有的基本功能。
浙公網(wǎng)安備 33010602011771號