深入了解Kubernetes REST API的工作方式
在哪裏以及如何定義從REST路徑到處理REST調用的函數的映射?
與etcd的交互發生在哪裏?
從客戶端發出請求到保存在etcd中對象的端到端路徑是怎樣的?
Kubernetes REST框架
Kubernetes REST實現可大致分為三個部分,如下圖所示。
客戶端/服務器功能通過k8s.io包中的各種庫實現。服務器端實現分布在多個包中。
服務器端的根目錄包是apiserver, 其包含有endpoints,server,registry和storage等重要的包。
客戶端在client-go包中實現,其包含的主要包是rest。
幾個關鍵Kubernetes概念
1)組(Group)
KubernetesREST API以層次結構組織,並以/apis為根。 一個組為根下的一組REST資源集定義一個邏輯名稱。例如API組名為apps,它在層次結構中就表示為/apis/apps。
可以使用如下命令檢查所有可用的API組:
kubectl get --raw/apis | python -mjson.tool
2)版本(Version)
KubernetesREST API使用版本。版本名用於定義REST資源端點,這些資源短點在組內不斷演變。典型的版本名稱有v1,v1alpha1,v1beta1。可以使用如下命令查找API組的所有可用版本:
kubectl get-raw /apis/
例如,想找apps組下的所有可用版本,可使用如下命令:
kubectl get --raw/apis/apps | python -mjson.tool
3)類型(Type)
表示概念的命名實體(例如:Pod,Deployment,Service等)。
4)種類(Kind)
Kubernetes類型的JSON/YAML表示。
5)資源(Resource)
處理特定種類的REST請求的端點/路徑。資源在api層次結構中通用表示為:
/apis///namespaces//
例如, deployments可表示為
/apis/apps/v1/namespaces/default/deployments
服務器端
服務器端集中探究以下問題:
A: 服務器中註冊了哪些資源?
B: 與etcd的交互發生在哪裏?
1)genericapiserver.go
文件先定義APIGroupInfo類型用於保存關於API組的信息,例如存在哪些版本以及在這些版本中定義了哪些資源。其次,定義GenericAPIServer類型,並實現為API組註冊REST端點的InstallAPIGroup方法。該方法在api組版本實例中內部調用InstallREST方法。為運行服務器端,GenericAPIServer還包含Run()方法。
2)groupversion.go
文件先定義APIGroupVersion類型,用於承載關於某api組的特定版本的信息,例如引用提供實際REST端點實現(store.go)的對象的引用。還定義InstallREST方法,內部調用安裝程序上的Install方法來註冊該版本的REST資源。
3)installer.go
文件定義實現Install方法的APIInstaller類型。Install方法使用GroupVersion實例中的REST實現對象(請參見第2點),以將REST路徑註冊到go-restful庫中的處理函數映射。當使用這個庫時,模式是為一個特定的REST路徑定義一個可調用的handler
函數。該模式在installer.go中用於設置處理對應於不同資源端點。
例如:ws.GET(action.Path).To(handler), 其中handler是從GroupVersion實例的REST實現對象中獲得的函數。它被定義為處理action.Path上的GET請求時被調用。
4)master.go
文件先定義了包含指向GenericAPIServer實例的指針的Master類型。還定義了InstallAPIs方法,通過調用genericapiserver的InstallAPIGroup方法啟動註冊工作流程。在創建Master的新實例時,InstallAPIs方法被調用。
5)registry/rest/rest.go
文件定義了不同的各種接口,應該被任何想要提供Kubernetes-like REST端點的後端實現。該文件中的關鍵接口是:Storage和StandardStorage。REST實現對象的引用屬於rest.Storage接口類型,該對象由在groupversion.go中的APIGroupVersion維護。
6)registry/generic/registry/store.go
文件定義了實現rest.StandardStorage接口的Store類型。方法實現在由Store類型維護的Storage對象上的調用。
7)storage/Interface.go
文件定義了一個名為Interface的接口,包含一些方法。如果我們想可用於實際持久化的store,必須實現這些方法。對於‘Interface‘接口中所有方法,一個關鍵點是它們只返回error而沒有其他的內容。如果任何數據需要由方法返回,將通過一個指針作為參數傳遞的對象返回。作為一個例子,檢查簽名的Get方法。
8)storage/etcd3/store.go
文件定義了實現storage.Interface的Store類型它使用etcd 的clientv3庫與etcd3進行交互。
客戶端
在客戶端,我們主要探究REST調用如何進行?
1)request.go
文件定義了Request類型,實現用於在資源上進行REST調用的方法。進行調用的模式是先創建一個NewRequest對象,然後使用流式樣方法鏈來調用REST方法(GET,POST,PUT,DELETE)。資源和名稱空間的名稱是創建完整端點所必需的,它們通過鏈式方法調用進行定義。
2)client.go
文件首先定義了一個名為Interface的接口,它包含返回Request對象指針(在request.go中定義)的REST方法包裝器。其次定義了實現Interface接口的REST Client類型。
進行REST調用的模式是首先創建一個NewRESTClient,然後通過其中一個REST方法包裝體獲取NewRequest對象。一旦NewRequest對象可用,REST調用就像上面解釋的那樣使用方法鏈進行。
探究
-
Kubernetes代碼擁有豐富的文檔,這有助於理解一段代碼作用。
-
包含類型隱含地實現方法的地方,可以很方便的在Interfaces中統計所有方法,進而很容易明白該類型實現了哪些方法。 (註冊表包很好地實現了這一點,但installer.go是一個不會發生這種情況的例子。)
- Golang導入別名可以幫助確定一個方法來自哪個包。雖然代碼確實使用了別名,但還有更廣泛的使用它們的空間。
深入了解Kubernetes REST API的工作方式