Kubernetes設計的4個原則

EAWorld發表於2020-04-06

Kubernetes設計的4個原則

引言:

今天我要帶給大家的是2018年底,在西雅圖舉辦的Kubecon的一場分享,來自谷歌K8s團隊的工程師Saad Ali分享的《Kubernetes設計原則》。這場會議雖然已經過去一年多了,但是我覺得本會議的內容非常值得學習,我們大都知道K8s是如何工作的,但是本文帶我們瞭解k8s背後的設計原則,以及為什麼要這樣設計。
對於跨雲和本地環境在分散式系統上管理和部署工作負載,Kubernetes很快變得不可或缺。
雖然現在大多數人都熟悉如何使用Kubernetes,但很少有人知道其背後的“為什麼”?為什麼Kubernetes API看起來是這樣的?為什麼Kubernetes元件僅透過Kubernetes API相互互動?當您可以輕鬆地直接從pod引用卷時,為什麼會有PersistentVolumeClaim物件?
為了回答這些問題並幫助您對Kubernetes進行更深入的瞭解,本講座將揭示支撐Kubernetes設計的原理。

原則1. Kubernetes APIs 

宣告性的而非命令性的

我們從最簡單的一個例子開始,要如何在一臺節點上啟動需要執行的任務。
Kubernetes設計的4個原則
最簡單的方式就是傳送一個命令,啟動容器。
Kubernetes設計的4個原則
但是這樣做的話,如果容器,節點崩潰,或者節點臨時不可訪問的時候,使用者就必須監控和儲存每一個節點和容器的狀態,捕獲所有的異常,並做異常處理。也就是說把所有的複雜的異常處理的邏輯交給客戶端來做。
這就引入了Kubernetes的第一個設計原則:
Kubernetes APIs 是宣告性的而非命令性的 ( Kubernetes APIs are declarative rather then imperative )
命令式:

  • 使用者:提供一系列的指令來驅動系統達到制定狀態。

  • 系統:執行指令

  • 使用者:監控系統,根據系統狀態,提供進一步的指令

宣告式:

  • 使用者:定義期望的狀態

  • 系統:向著指定的狀態工作

下圖是一個宣告式API的例子:

1、使用者建立一個API物件

Kubernetes設計的4個原則

2、所用的元件並行工作來達到該狀態。

Kubernetes設計的4個原則

宣告式的API支援自動恢復。例如:

1、節點B掛了

Kubernetes設計的4個原則

2、系統自主地把Pod移動到健康的節點A上

Kubernetes設計的4個原則

這裡需要注意主節點只是儲存了Pod的定義宣告,而不會向節點B傳送命令,如果那樣做,主節點就會變得和我們之前提到的客戶端一樣,複雜而脆弱,且難以擴充套件。這就引入了K8s的第二個設計原則:
Kubernetes控制平面是透明的,沒有隱藏的內部API ( The Kubernetes control plane is transparent. There are no hidden internal APIs. )

原則2.  Kubernetes控制平面

透明的,沒有隱藏的內部API

之前:

  • 主節點:提供一系列的指令來驅動節點達到制定狀態。

  • 節點:執行主節點發來的指令

  • 主節點:監控每一個節點,根據節點狀態,提供進一步的指令

現在:

  • 主節點:定義想要達到的狀態

  • 節點:獨立工作以達到主節點定義的狀態

我們來看一個Pod建立的例子:
如下圖所示,所有的元件都監視Kubernetes API,然後決定自己應該怎麼做。
Kubernetes設計的4個原則
使用者呼叫API宣告要建立的Pod
Kubernetes設計的4個原則
節點建立Pod的定義
Kubernetes設計的4個原則

Scheduler透過API觀察到Pod A的定義,透過排程運算,決定要在Node B上建立Pod A,並透過API更新主節點上的Pod A的定義。

Kubernetes設計的4個原則
Node B觀察到Pod A的定義是在自己的管轄範圍,啟動Pod A
Kubernetes設計的4個原則
使用者透過API刪除 Pod A
Kubernetes設計的4個原則
節點B發現 Pod A被刪除
Kubernetes設計的4個原則
節點B刪除Pod A
Kubernetes設計的4個原則
這樣做的能促成一個更簡單,更健壯的系統設計,並很容易從故障狀態中恢復。系統沒有單點故障,主節點的職責非常簡單。
這樣做的另一個好處是,系統更容易擴充套件和組合。因為沒有內部隱藏的API,使用者可以很容易的用自定的元件替代已有元件,或者增加自定義的功能。
K8s還有很對物件對業務是很重要的,例如儲存密碼的密匙檔案secret,配置configmap,或者下行API提供Pod的基本資訊。那麼應用程式必須修改為呼叫KubeAPI來或者這些資訊麼?
這就引入了Kubernetes的第三個設計原則:
滿足使用者的需求 ( Meet the user where they are )

原則3.  滿足使用者的需求 

之前:

  • 應用程式必須被修改為知道K8s的存在,呼叫KubeAPI

現在:

  • 應用程式可以從環境變數載入配置檔案或者密匙檔案,所以不需要修改


Kubernetes設計的4個原則

我們可以舉一個例子,是關於遠端儲存的。

Kubernetes設計的4個原則

如上圖所示,Pod可以直接引用一個遠端的儲存卷(GCE PD,AWS EBS,NFS等),kubernetes會自動使得該卷被用於Pod。但是這樣做的話,有一個問題,如果你要遷移到一個新的基礎架構上,那麼它就不工作了。於是這就引入了kubernetes設計的第四個原則:

可移植的工作負載 ( Workload portability )

原則4. 可移植的工作負載

持久卷(PersistentVolumn,PV)和持久卷宣告(PersistenVolumnClaim, PVC)就是這樣一個例子。

Kubernetes設計的4個原則

Kubernetes設計的4個原則

如上圖所示,透過PVC的抽象,使用者Pod並不直接引用GCE PD或者EBS,這樣就使得該Pod可以在不同的基礎架構中互相遷移,做到可移植。就像作業系統一樣,該設計使得系統應用和底層的硬體或者架構實現分離解耦。

總結

本文總結了Kubecon 2018的一場由谷歌高階軟體工程師、kubernete開發人員Saad Ali分享的《Kubernetes設計原則》。其中的四個設計原則分別是:

  1. Kubernetes APIs 是宣告性的而非命令性的

  2. Kubernetes控制平面是透明的,沒有隱藏的內部API

  3. 滿足使用者的需求

  4. 可移植的工作負載

透過該分享,我們可以發現,K8s的背後設計原則的原因,其實它軟體設計的一些一般性原則是一致的,雖然物件導向已經不在是什麼流行的術語,但是本文中的設計原則和麵向物件的設計原則高度一致。
  • 物件要對自己負責。在設計物件的時候,物件應該儘可能的封裝內部的狀態,對自己負責,我們設計一輛可行駛的車。一種設計是兩個物件,driver和car,然後diver.run(car)。而更好的設計是 不需要driver,或者把dirver看成Car的一個屬性,這樣就是Car.run()。第二種設計更符合物件導向的設計原則。這正是宣告式API背後的原則,元件對自己負責

  • Kube API類似物件的介面,物件對修改封閉,對擴充套件開放。透過開放的API,使用者可以很容易的實現功能擴充套件,但是你無法修改已有的元件,你可以開發自定義的元件來替換已有的元件

  • 可移植性的設計利用了類似物件導向的多型,同多定義抽象介面PVC,隱藏具體的實現細節。

希望本文的分享能幫助你理解K8s背後的設計原則。

參考:

  • (該分享的影片,已新增中英文字幕)

Kubernetes設計的4個原則

關於作者陶剛,Splunk資深軟體工程師,架構師,畢業於北京郵電大學,現在在溫哥華負責Splunk機器學習雲平臺的開發,曾經就職於SAP,EMC,Lucent等企業,擁有豐富的企業應用軟體開發經驗,熟悉軟體開發的各種技術,平臺和開發過程,在商務智慧,機器學習,資料視覺化,資料採集,網路管理等領域都有涉及。

關於EAWorld:微服務,DevOps,資料治理,移動架構原創技術分享。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31562043/viewspace-2672530/,如需轉載,請註明出處,否則將追究法律責任。

相關文章