天天看點

kubernetes設計理念

一、kubernetes設計理念與分布式系統 

API設計原則:

對于雲計算系統,系統API實際上處于系統設計的統領地位,K8S叢集系統每支援一項新功能,引入一項新技術,一定會新引入對應的API對象,支援對該功能的管理操作。

1.所有API應該是聲明式的。聲明式操作相對于指令式操作,對于重複操作的效果更加穩定,這對于容易出現資料丢失或重複的分布式環境而言很重要。另外聲明式操作更容易被使用者使用,對使用者隐藏細節,同時保留系統未來持續優化的可能性。

2.API對象是彼此互補而且可組合的。提倡API對象盡量實作面向對象的設計要求,達到“高内聚,低耦合”,對業務子產品有個合适的分解。本質上K8S這種分布式系統管理平台,也是一種業務系統,隻不過它的業務就是排程和管理容器服務。

3.高層API以操作意圖為設計基礎。高層設計一定是從業務出發,而不是技術的角度。針對K8S的高層API設計,一定是以K8S的業務為基礎出發,也就是以系統排程管理容器的操作意圖為設計基礎。

4.低層API根據高層API的控制需要進行設計。設計實作低層API的目的是為了被高層API使用,考慮減少備援,提高重用性的目的,低層API的設計也要以需求為基礎,盡量抵抗受技術實作影響的誘惑。

5.盡量避免簡單封裝,不要有在外部API無法顯式知道的内部隐藏的機制。簡單的封裝實際上沒有提供新功能,反而增加了對所封裝API的依賴性。内部隐藏的機制也是非常不利于系統維護的設計方式。如PetSet和ReplicaSet, 本來就是兩種Pod集合,K8S就用不同API對象來定義它們,而不會說隻用同一個ReplicaSet, 内部通過特殊算法再來區分這個ReplicaSet是有狀态還是無狀态的。

6.API操作複雜度與對象數量成正比。這條主要是從系統性能角度考慮,要保證系統随着系統規模的擴大,性能不會迅速變慢到無法使用,則最低限定就是API的操作複雜度不能超過O(N), N是對象數量,否則系統就不具備水準伸縮了。

7.API對象狀态不能依賴于網絡連接配接。在分布式環境下,網絡連接配接斷開是經常發生的事情,要保證API對象狀态能應對網絡的不穩定性,API對象的狀态就不能依賴于網絡連接配接狀态。

8.盡量避免讓操作機制依賴于全局狀态,因為在分布式系統中要保證全局狀态的同步是比較困難的。

控制機制設計原則:

1.控制邏輯應該隻依賴于目前狀态。

為了保證分布式系統的穩定可靠,對于經常出現局部錯誤的分布式系統,如果控制邏輯隻依賴目前狀态,那麼就非常容易将一個暫時出現故障的系統恢複到正常狀态,因為你隻要将該系統重置到某個穩定狀态,就可以自信的知道系統的所有控制邏輯會開始按照正常方式運作。

2.假設任何錯誤的可能,并做容錯處理。

在一個分布式系統中出現局部和臨時錯誤是大機率事件。錯誤可能來自于實體系統故障,外部系統故障也可能來自于系統自身的代碼錯誤,依靠自己實作的代碼不會出錯來保證系統穩定其實也是難以實作的,是以要設計對任何可能錯誤的容錯處理。

3.盡量避免複雜狀态機,控制邏輯不要依賴于無法監控的内部狀态。

因為分布式系統各個子系統都是不能嚴格通過程式内部保持同步的,是以如果兩個子系統的控制邏輯如果互相有影響,那麼子系統就一定要能互相通路到影響控制邏輯的狀态,否則,就等同于系統裡存在不确定的控制邏輯。

4.假設任何操作都可能被任何操作對象拒絕,甚至被錯誤解析。

由于分布式系統的複雜性以及各子系統的相對獨立性,不同子系統經常來自不同的開發團隊,是以不能奢望任何操作被另一個子系統以正确的方式處理,要保證出現錯誤的時候,操作級别的錯誤不會影響到系統穩定性。

5.每個子產品都可以在出錯後自動恢複。

由于分布式系統中無法保證系統各個子產品是始終連接配接的,是以每個子產品要有自我修複的能力,保證不會因為連接配接不到其他子產品而自我崩潰。

6.每個子產品都可以在必要時優雅地降級服務。

即要求在設計實作子產品時劃厘清楚基本功能和進階功能,保證基本功能不會依賴進階功能,這樣同時就保證了不會因為進階功能出現故障而導緻整個子產品崩潰。根據這種理念實作的系統,也更容易快速地增加新的進階功能,以為不必擔心引入進階功能影響原有的基本功能。

二、kubernetes核心技術概念和API對象

API對象是K8s叢集中的管理操作單元。K8s叢集系統每支援一項新功能,引入一項新技術,一定會新引入對應的API對象,支援對該功能的管理操作。例如副本集Replica Set對應的API對象是RS。

每個API對象都有3大類屬性:中繼資料metadata、規範spec和狀态status。中繼資料是用來辨別API對象的,每個對象都至少有3個中繼資料:namespace,name和uid;除此以外還有各種各樣的标簽labels用來辨別和比對不同的對象,例如使用者可以用标簽env來辨別區分不同的服務部署環境,分别用env=dev、env=testing、env=production來辨別開發、測試、生産的不同服務。規範描述了使用者期望K8s叢集中的分布式系統達到的理想狀态(Desired State),例如使用者可以通過複制控制器Replication Controller設定期望的Pod副本數為3;status描述了系統實際目前達到的狀态(Status),例如系統目前實際的Pod副本數為2;那麼複制控制器目前的程式邏輯就是自動啟動新的Pod,争取達到副本數為3。

K8s中所有的配置都是通過API對象的spec去設定的,也就是使用者通過配置系統的理想狀态來改變系統,這是k8s重要設計理念之一,即所有的操作都是聲明式(Declarative)的而不是指令式(Imperative)的。聲明式操作在分布式系統中的好處是穩定,不怕丢操作或運作多次,例如設定副本數為3的操作運作多次也還是一個結果,而給副本數加1的操作就不是聲明式的,運作多次結果就錯了。

1.Pod

K8s有很多技術概念,同時對應很多API對象,最重要的也是最基礎的是微服務Pod。Pod是在K8s叢集中運作部署應用或服務的最小單元,它是可以支援多容器的。Pod的設計理念是支援多個容器在一個Pod中共享網絡位址和檔案系統,可以通過程序間通信和檔案共享這種簡單高效的方式組合完成服務。Pod對多容器的支援是K8s最基礎的設計理念。比如你運作一個作業系統發行版的軟體倉庫,一個Nginx容器用來釋出軟體,另一個容器專門用來從源倉庫做同步,這兩個容器的鏡像不太可能是一個團隊開發的,但是他們一塊兒工作才能提供一個微服務;這種情況下,不同的團隊各自開發建構自己的容器鏡像,在部署的時候組合成一個微服務對外提供服務。

Pod是K8s叢集中所有業務類型的基礎,可以看作運作在K8s叢集中的小機器人,不同類型的業務就需要不同類型的小機器人去執行。目前K8s中的業務主要可以分為長期伺服型(long-running)、批處理型(batch)、節點背景支撐型(node-daemon)和有狀态應用型(stateful application);分别對應的小機器人控制器為Deployment、Job、DaemonSet和PetSet,本文後面會一一介紹。

2.複制控制器(Replication Controller,RC)

RC是K8s叢集中最早的保證Pod高可用的API對象。通過監控運作中的Pod來保證叢集中運作指定數目的Pod副本。指定的數目可以是多個也可以是1個;少于指定數目,RC就會啟動運作新的Pod副本;多于指定數目,RC就會殺死多餘的Pod副本。即使在指定數目為1的情況下,通過RC運作Pod也比直接運作Pod更明智,因為RC也可以發揮它高可用的能力,保證永遠有1個Pod在運作。RC是K8s較早期的技術概念,隻适用于長期伺服型的業務類型,比如控制小機器人提供高可用的Web服務。

3.副本集(Replica Set,RS)

RS是新一代RC,提供同樣的高可用能力,差別主要在于RS後來居上,能支援更多種類的比對模式。副本集對象一般不單獨使用,而是作為Deployment的理想狀态參數使用。

4.部署(Deployment)

部署表示使用者對K8s叢集的一次更新操作。部署是一個比RS應用模式更廣的API對象,可以是建立一個新的服務,更新一個新的服務,也可以是滾動更新一個服務。滾動更新一個服務,實際是建立一個新的RS,然後逐漸将新RS中副本數增加到理想狀态,将舊RS中的副本數減小到0的複合操作;這樣一個複合操作用一個RS是不太好描述的,是以用一個更通用的Deployment來描述。以K8s的發展方向,未來對所有長期伺服型的的業務的管理,都會通過Deployment來管理。

5.服務(Service)

RC、RS和Deployment隻是保證了支撐服務的微服務Pod的數量,但是沒有解決如何通路這些服務的問題。一個Pod隻是一個運作服務的執行個體,随時可能在一個節點上停止,在另一個節點以一個新的IP啟動一個新的Pod,是以不能以确定的IP和端口号提供服務。要穩定地提供服務需要服務發現和負載均衡能力。服務發現完成的工作,是針對用戶端通路的服務,找到對應的的後端服務執行個體。

在K8S叢集中,用戶端需要通路的服務就是Service對象。每個Service會對應一個叢集内部有效的虛拟IP, 叢集内部通過虛拟IP通路一個服務。在K8S叢集中微服務的負載均衡是通過kube-proxy實作的。kube-proxy是K8S叢集内部的負載均衡器。它是一個分布式代理伺服器,在K8S的每個節點上都有一個。這一特性展現了它的伸縮性優勢,需要通路服務的節點越多,提供負載均衡能力的kube-proxy就越多,高可用節點也随之增多。

6.任務(Job)

Job是K8S用來控制批處理型任務的API對象。批處理業務與長期伺服long-running業務的主要差別是批處理業務的運作有頭有尾,而長期伺服業務在使用者不停止的情況下永遠運作。Job管理的Pod根據使用者的設定把任務成功完成就自動退出了。成功完成的标志根據不同的spec.completions政策而不同:單Pod型任務有一個Pod成功就标志完成;定數成功型任務保證有N個任務全部成功;工作隊列型任務根據應用确認的全局成功而标志成功。

7.背景支撐服務集(DaemonSet)

背景支撐型服務的核心關注點在K8S叢集中的節點(實體機或虛拟機),要保證每個節點上都有一個此類Pod運作。節點可能是所有叢集節點也可能是通過nodeSelector標明的一些特定節點。典型的背景支撐服務包括存儲、日志、監控等,在每個節點上支援K8S叢集運作的服務。

8.有狀态服務集(PetSet)

RC和RS主要是控制提供無狀态服務的,其所控制的Pod的名字是随機設定的,一個Pod出故障了就被丢棄,在另一個地方重新開機一個新Pod, 名字變了、名字和啟動在哪兒都不重要,重要的隻是Pod總數;而PetSet是用來控制有狀态服務,PetSet中的每個Pod的名字都是事先确定的,不能更改。PetSet中Pod的名字是用來關聯與該Pod的對應狀态。

9.叢集聯邦(Federation)

K8s在1.3版本裡釋出了beta版的Federation功能。在雲計算環境中,服務的作用距離範圍從近到遠一般可以有:同主機(Host,Node)、跨主機同可用區(Available Zone)、跨可用區同地區(Region)、跨地區同服務商(Cloud Service Provider)、跨雲平台。K8s的設計定位是單一叢集在同一個地域内,因為同一個地區的網絡性能才能滿足K8s的排程和計算存儲連接配接要求。而聯合叢集服務就是為提供跨Region跨服務商K8s叢集服務而設計的。

每個K8s Federation有自己的分布式存儲、API Server和Controller Manager。使用者可以通過Federation的API Server注冊該Federation的成員K8s Cluster。當使用者通過Federation的API Server建立、更改API對象時,Federation API Server會在自己所有注冊的子K8s Cluster都建立一份對應的API對象。在提供業務請求服務時,K8s Federation會先在自己的各個子Cluster之間做負載均衡,而對于發送到某個具體K8s Cluster的業務請求,會依照這個K8s Cluster獨立提供服務時一樣的排程模式去做K8s Cluster内部的負載均衡。而Cluster之間的負載均衡是通過域名服務的負載均衡來實作的。

所有的設計都盡量不影響K8s Cluster現有的工作機制,這樣對于每個子K8s叢集來說,并不需要更外層的有一個K8s Federation,也就是意味着所有現有的K8s代碼和機制不需要因為Federation功能有任何變化。

10.存儲卷(Volume)

K8s叢集中的存儲卷跟Docker的存儲卷有些類似,隻不過Docker的存儲卷作用範圍為一個容器,而K8s的存儲卷的生命周期和作用範圍是一個Pod。每個Pod中聲明的存儲卷由Pod中所有的容器共享。K8S支援非常多的存儲卷類型。支援多種公有雲平台的存儲,包括AWS, Google, Azure雲;支援多種分布式存儲包括GlusterFS和Ceph;也支援較容易使用的主機本地目錄hostPath和NFS.

K8s還支援使用Persistent Volume Claim即PVC這種邏輯存儲,使用這種存儲,使得存儲的使用者可以忽略背景的實際存儲技術(例如AWS,Google或GlusterFS和Ceph),而将有關存儲實際技術的配置交給存儲管理者通過Persistent Volume來配置。

11.持久存儲卷(Persistent Volume,PV)和持久存儲卷聲明(Persistent Volume Claim,PVC)

PV和PVC使得K8s叢集具備了存儲的邏輯抽象能力,使得在配置Pod的邏輯裡可以忽略對實際背景存儲技術的配置,而把這項配置的工作交給PV的配置者,即叢集的管理者。存儲的PV和PVC的這種關系,跟計算的Node和Pod的關系是非常類似的;PV和Node是資源的提供者,根據叢集的基礎設施變化而變化,由K8s叢集管理者配置;而PVC和Pod是資源的使用者,根據業務服務的需求變化而變化,有K8s叢集的使用者即服務的管理者來配置。

12.節點(Node)

K8S叢集中的計算能力由Node提供,最初Node稱為服務節點Minion, 後來改名為node。K8s叢集中的Node相當于Mesos叢集中的slave節點,是所有Pod運作所在的工作主機,可以是實體機也可以是虛拟機,工作主機的統一特征是上面要運作kubelet管理節點上運作的容器。

13.密鑰對象(Secret)

Secret是用來儲存和傳遞密碼、密鑰、認證憑證這些敏感資訊對象的。Secret可以避免敏感資訊明文寫在配置檔案裡。

14.使用者帳戶(User Account)和服務帳戶(Service Account)

使用者帳戶為人提供賬戶辨別,而服務賬戶為計算機程序和K8s叢集中運作的Pod提供賬戶辨別。使用者帳戶和服務帳戶的一個差別是作用範圍;使用者帳戶對應的是人的身份,人的身份與服務的namespace無關,是以使用者賬戶是跨namespace的;而服務帳戶對應的是一個運作中程式的身份,與特定namespace是相關的。

15.名字空間(Namespace)

namespace為k8s叢集提供虛拟隔離作用,K8S叢集初始有兩個namespace, default和kube-system, 此外管理者可以建立新namespace以滿足需求。

16.RBAC通路授權(Role-based Access Control, RBAC)

k8s在1.3版本中釋出了基于角色的通路控制的授權模式。相對于基于屬性的通路控制(Attribute-based Access Control, ABAC), RBAC主要引入了角色Role和角色綁定RoleBinding的概念。

17.Conclusion總結

從K8S的系統架構、技術概念和設計理念上可以看到兩個最核心的設計理念:容錯性和易擴充性。容錯性是保證K8S系統穩定性和安全生的基礎,易擴充性是保證K8S對使用者更加友好,是快速疊代增加新功能的基礎。

本文轉移開源中國-

kubernetes設計理念