Kubernetes的client-go庫介紹

吳德寶AllenWu發表於2018-10-19

[TOC]

Kubernetes的client-go庫介紹

client-go的作用

github上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

Kubernetes的client-go庫介紹

主要是兩大塊:

  • client-go元件本身
  • controller上層控制器

上圖相對較為複雜,有很多細節,我自己結合原始碼的理解如下:

evernotecid://5FE43ADA-E2E0-493A-9B2A-64DC8D9CB22F/appyinxiangcom/4068038/ENResource/p8319

Kubernetes的client-go庫介紹

client-go元件

  • Reflector:通過Kubernetes API監控Kubernetes的資源型別

    • 採用List、Watch機制
    • 可以Watch任何資源包括CRD
    • 新增object物件到FIFO佇列,然後Informer會從佇列裡面取資料
  • Informer:controller機制的基礎

    • 迴圈處理object物件
      • 從Reflector取出資料,然後將資料給到Indexer去快取
    • 提供物件事件的handler介面
  • 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

client-go under the hood

Kubernetes Deep Dive: Code Generation for CustomResources

kubernetes client-go

Kubernetes Informer 詳解

如何用 client-go 擴充 Kubernetes 的 API

Using Kubernetes API from Go

相關文章