[TOC]
Kubernetes的client-go庫介紹
client-go的作用
基本介紹
Kubernetes官方從2016年8月份開始,將Kubernetes資源操作相關的核心原始碼抽取出來,獨立出來一個專案Client-go,作為官方提供的Go client。Kubernetes的部分程式碼也是基於這個client實現的,所以對這個client的質量、效能等方面還是非常有信心的。
client-go是一個呼叫kubernetes叢集資源物件API的客戶端,即通過client-go實現對kubernetes叢集中資源物件(包括deployment、service、ingress、replicaSet、pod、namespace、node等)的增刪改查等操作。大部分對kubernetes進行前置API封裝的二次開發都通過client-go這個第三方包來實現。
原始碼簡介
主要package
主要的幾個package包的功能說明:
- kubernetes: 訪問 Kubernetes API的一系列的clientset
- discovery:通過Kubernetes API 進行服務發現
- dynamic:對任意Kubernetes物件執行通用操作的動態client
- transport:啟動連線和鑑權auth
- tools/cache:controllers控制器
Client結構
-
RESTClient:RESTClient是最基礎的,相當於的底層基礎結構,可以直接通過 是RESTClient提供的RESTful方法如Get(),Put(),Post(),Delete()進行互動
- 同時支援Json 和 protobuf
- 支援所有原生資源和CRDs
- 但是,一般而言,為了更為優雅的處理,需要進一步封裝,通過Clientset封裝RESTClient,然後再對外提供介面和服務
-
Clientset:Clientset是呼叫Kubernetes資源物件最常用的client,可以操作所有的資源物件,包含RESTClient。需要指定Group、指定Version,然後根據Resource獲取
- 優雅的姿勢是利用一個controller物件,再加上Informer
-
DynamicClient:Dynamic client 是一種動態的 client,它能處理 kubernetes 所有的資源。不同於 clientset,dynamic client 返回的物件是一個 map[string]interface{},如果一個 controller 中需要控制所有的 API,可以使用dynamic client,目前它在 garbage collector 和 namespace controller中被使用。
- 只支援JSON
RESTClient
RESTClient 封裝了指定資源URL的通用Kubernetes API的訪問姿勢
Clientset
/Users/meitu/Documents/work_Meitu/goDev/Applications/src/k8s.io/client-go/kubernetes/clientset.go
Clientset 是一系列的clients的group組合,注意每個group在一個Clientset中只包含一個版本。
Clientset包含了appsV1、coreV1,這中間包含了RESTClient,因此Clientset是基於RESTClient的。
dynamic client
dynamic client針對的是所有資源,但是隻支援Json;
主要原始碼路徑在:/Users/meitu/Documents/work_Meitu/goDev/Applications/src/k8s.io/client-go/dynamic
type ResourceInterface interface {
Create(obj *unstructured.Unstructured, options metav1.CreateOptions, subresources ...string) (*unstructured.Unstructured, error)
Update(obj *unstructured.Unstructured, options metav1.UpdateOptions, subresources ...string) (*unstructured.Unstructured, error)
UpdateStatus(obj *unstructured.Unstructured, options metav1.UpdateOptions) (*unstructured.Unstructured, error)
Delete(name string, options *metav1.DeleteOptions, subresources ...string) error
DeleteCollection(options *metav1.DeleteOptions, listOptions metav1.ListOptions) error
Get(name string, options metav1.GetOptions, subresources ...string) (*unstructured.Unstructured, error)
List(opts metav1.ListOptions) (*unstructured.UnstructuredList, error)
Watch(opts metav1.ListOptions) (watch.Interface, error)
Patch(name string, pt types.PatchType, data []byte, options metav1.UpdateOptions, subresources ...string) (*unstructured.Unstructured, error)
}
複製程式碼
Informer
Client-go包中一個相對較為高階的設計在於Informer的設計,我們知道我們可以直接通過Kubernetes API互動,但是考慮一點就是互動的形式,Informer設計為List/Watch的方式。Informer在初始化的時先通過List去從Kubernetes API中取出資源的全部object物件,並同時快取,然後後面通過Watch的機制去監控資源,這樣的話,通過Informer及其快取,我們就可以直接和Informer互動而不是每次都和Kubernetes API互動。
Informer另外一塊內容在於提供了事件handler機制,並會觸發回撥,這樣上層應用如Controller就可以基於回撥處理具體業務邏輯。因為Informer通過List、Watch機制可以監控到所有資源的所有事件,因此只要給Informer新增ResourceEventHandler 例項的回撥函式例項取實現OnAdd(obj interface{}) OnUpdate(oldObj, newObj interface{}) 和 OnDelete(obj interface{})
這三個方法,就可以處理好資源的建立、更新和刪除操作
Kubernetes中都是各種controller的實現,各種controller都會用到Informer。
物件資源的操作介面
預設的每一種資源物件都有一個interface,封裝了物件的CURD方法和list/watch方法
如 Deployment(/檔案路徑Users/meitu/Documents/work_Meitu/goDev/Applications/src/k8s.io/client-go/kubernetes/typed/apps/v1/deployment.go
):
type DeploymentInterface interface {
Create(*v1.Deployment) (*v1.Deployment, error)
Update(*v1.Deployment) (*v1.Deployment, error)
UpdateStatus(*v1.Deployment) (*v1.Deployment, error)
Delete(name string, options *metav1.DeleteOptions) error
DeleteCollection(options *metav1.DeleteOptions, listOptions metav1.ListOptions) error
Get(name string, options metav1.GetOptions) (*v1.Deployment, error)
List(opts metav1.ListOptions) (*v1.DeploymentList, error)
Watch(opts metav1.ListOptions) (watch.Interface, error)
Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.Deployment, err error)
DeploymentExpansion
}
複製程式碼
如Service(檔案路徑/Users/meitu/Documents/work_Meitu/goDev/Applications/src/k8s.io/client-go/kubernetes/typed/core/v1/service.go
)
// ServiceInterface has methods to work with Service resources.
type ServiceInterface interface {
Create(*v1.Service) (*v1.Service, error)
Update(*v1.Service) (*v1.Service, error)
UpdateStatus(*v1.Service) (*v1.Service, error)
Delete(name string, options *metav1.DeleteOptions) error
Get(name string, options metav1.GetOptions) (*v1.Service, error)
List(opts metav1.ListOptions) (*v1.ServiceList, error)
Watch(opts metav1.ListOptions) (watch.Interface, error)
Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.Service, err error)
ServiceExpansion
}
複製程式碼
這也就是說明,在Kubernetes中,所有物件資源的操作方式都是統一的,有個interface當做虛基類,包含資源的所有操作方法,然後各個子類繼承然後實現它們,子類中的實現定義會針對不同的資源有不同詮釋
client-go中的設計思想
client-go 和 controller的架構設計
github上關於client-go的設計有一副概覽圖如下:
evernotecid://5FE43ADA-E2E0-493A-9B2A-64DC8D9CB22F/appyinxiangcom/4068038/ENNote/p2171?hash=6cfd2f55a147ce7733d84bbacda91850
主要是兩大塊:
- client-go元件本身
- controller上層控制器
上圖相對較為複雜,有很多細節,我自己結合原始碼的理解如下:
evernotecid://5FE43ADA-E2E0-493A-9B2A-64DC8D9CB22F/appyinxiangcom/4068038/ENResource/p8319
client-go元件
-
Reflector:通過Kubernetes API監控Kubernetes的資源型別
- 採用List、Watch機制
- 可以Watch任何資源包括CRD
- 新增object物件到FIFO佇列,然後Informer會從佇列裡面取資料
-
Informer:controller機制的基礎
- 迴圈處理object物件
- 從Reflector取出資料,然後將資料給到Indexer去快取
- 提供物件事件的handler介面
- 迴圈處理object物件
-
Indexer:提供object物件的索引,是執行緒安全的,快取物件資訊
controller元件
-
Informer reference: controller需要建立合適的Informer才能通過Informer reference操作資源物件
-
Indexer reference: controller建立Indexer reference然後去利用索引做相關處理
-
Resource Event Handlers:Informer會回撥這些handlers
-
Work queue: Resource Event Handlers被回撥後將key寫到工作佇列
- 這裡的key相當於事件通知,後面根據取出事件後,做後續的處理
-
Process Item:從工作佇列中取出key後進行後續處理,具體處理可以通過Indexer reference
-
controller可以直接建立上述兩個引用物件去處理,也可以採用工廠模式,官方都有相關示例
參考
Accessing Kubernetes CRDs from the client-go package
Kubernetes Deep Dive: Code Generation for CustomResources