kubernetes client-go

簡介

Kubernetes官方從2016年8月份開始问芬,將Kubernetes資源操作相關(guān)的核心源碼抽取出來标沪,獨立出來一個項目Client-go贮配,作為官方提供的Go client囊卜。Kubernetes的部分代碼也是基于這個client實現(xiàn)的,所以對這個client的質(zhì)量越妈、性能等方面還是非常有信心的季俩。

client-go是一個調(diào)用kubernetes集群資源對象API的客戶端,即通過client-go實現(xiàn)對kubernetes集群中資源對象(包括deployment叮称、service、ingress藐鹤、replicaSet瓤檐、pod、namespace娱节、node等)的增刪改查等操作挠蛉。大部分對kubernetes進(jìn)行前置API封裝的二次開發(fā)都通過client-go這個第三方包來實現(xiàn)

主要package

  • kubernetes
    訪問 Kubernetes API的一系列的clientset
  • discovery
    通過Kubernetes API 進(jìn)行服務(wù)發(fā)現(xiàn)
  • dynamic
    對任意Kubernetes對象執(zhí)行通用操作的動態(tài)client
  • plugin/pkg/client/auth
    可選的身份驗證插件,用于從外部來源獲取憑據(jù)肄满。
  • transport
    啟動連接和鑒權(quán)auth
  • tools/cache
    controllers控制器

關(guān)鍵組件

  • Reflector
    reflector可以通過ListAndWatch方法對指定的Kubernetes資源進(jìn)行監(jiān)聽谴古,資源可以是Kubernetes內(nèi)置的資源類型,也可以是CRD稠歉。當(dāng)一個reflector收到新資源創(chuàng)建的通知時掰担,會通知相應(yīng)的list API獲取對應(yīng)資源模型并將其寫入到一個Delta FIFO的工作隊列中
  • ClientSet
    提供了直接從Kubernetes API Server 中獲取Object的機制,當(dāng)然使用Lister從本地Cache中獲取Objects的方法優(yōu)先級會高于直接從API Server讀取怒炸,以最大程度上減輕API server的負(fù)載
  • Indexer(線程安全)
    indexer的作用是對目標(biāo)object生成相應(yīng)的存儲索引带饱,在內(nèi)部實現(xiàn)上,indexer可以支持多種索引方式阅羹,同時利用一個線程安全的本地存儲持久化對應(yīng)的object和索引鍵勺疼,默認(rèn)情況下indexer會使用/的組合形式作為目標(biāo)object的索引鍵
  • Lister
    從本地Index中獲取Objecrts的工作機制,可以在client-go中的tools/cache包中找到其具體實現(xiàn)
  • Informer
    Client-go包中一個相對較為高端的設(shè)計在于Informer的設(shè)計捏鱼,我們知道我們可以直接通過Kubernetes API交互执庐,但是考慮一點就是交互的形式,Informer設(shè)計為List/Watch的方式导梆。Informer在初始化的時先通過List去從Kubernetes API中取出資源的全部object對象轨淌,并同時緩存迂烁,然后后面通過Watch的機制去監(jiān)控資源,這樣的話猿诸,通過Informer及其緩存婚被,我們就可以直接和Informer交互而不是每次都和Kubernetes API交互。
    Informer另外一塊內(nèi)容在于提供了事件handler機制梳虽,并會觸發(fā)回調(diào)址芯,這樣上層應(yīng)用如Controller就可以基于回調(diào)處理具體業(yè)務(wù)邏輯。因為Informer通過List窜觉、Watch機制可以監(jiān)控到所有資源的所有事件谷炸,因此只要給Informer添加ResourceEventHandler 實例的回調(diào)函數(shù)實例取實現(xiàn)
    OnAdd(obj interface{}) OnUpdate(oldObj, newObj interface{}) 和 OnDelete(obj interface{})
    
    這三個方法,就可以處理好資源的創(chuàng)建禀挫、更新和刪除操作
    Kubernetes中都是各種controller的實現(xiàn)旬陡,各種controller都會用到Informer

Demo

集群內(nèi)
package main

import (
    "context"
    "fmt"
    "k8s.io/apimachinery/pkg/api/errors"
    metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    "k8s.io/client-go/kubernetes"
    "k8s.io/client-go/rest"
    "time"
)

func main() {
    // creates the in-cluster config
    config, err := rest.InClusterConfig()
    if err != nil {
        panic(err.Error())
    }
    // creates the clientset
    clientset, err := kubernetes.NewForConfig(config)
    if err != nil {
        panic(err.Error())
    }
    for {
        // get pods in all the namespaces by omitting namespace
        // Or specify namespace to get pods in particular namespace
        pods, err := clientset.CoreV1().Pods("").List(context.TODO(), metav1.ListOptions{})
        if err != nil {
            panic(err.Error())
        }
        fmt.Printf("There are %d pods in the cluster\n", len(pods.Items))

        // Examples for error handling:
        // - Use helper functions e.g. errors.IsNotFound()
        // - And/or cast to StatusError and use its properties like e.g. ErrStatus.Message
        _, err = clientset.CoreV1().Pods("default").Get(context.TODO(), "example-xxxxx", metav1.GetOptions{})
        if errors.IsNotFound(err) {
            fmt.Printf("Pod example-xxxxx not found in default namespace\n")
        } else if statusError, isStatus := err.(*errors.StatusError); isStatus {
            fmt.Printf("Error getting pod %v\n", statusError.ErrStatus.Message)
        } else if err != nil {
            panic(err.Error())
        } else {
            fmt.Printf("Found example-xxxxx pod in default namespace\n")
        }

        time.Sleep(10 * time.Second)
    }
}
集群外
package main

import (
    "context"
    "flag"
    "fmt"
    "k8s.io/apimachinery/pkg/api/errors"
    metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    "k8s.io/client-go/kubernetes"
    "k8s.io/client-go/tools/clientcmd"
    "k8s.io/client-go/util/homedir"
    "path/filepath"
    "time"
)

func main() {
    var kubeconfig *string
    if home := homedir.HomeDir(); home != "" {
        kubeconfig = flag.String("kubeconfig", filepath.Join(home, ".kube", "config"), "(optional) absolute path to the kubeconfig file")
    } else {
        kubeconfig = flag.String("kubeconfig", "", "absolute path to the kubeconfig file")
    }
    flag.Parse()

    // use the current context in kubeconfig
    config, err := clientcmd.BuildConfigFromFlags("", *kubeconfig)
    if err != nil {
        panic(err.Error())
    }

    // create the clientset
    clientset, err := kubernetes.NewForConfig(config)
    if err != nil {
        panic(err.Error())
    }
    for {
        pods, err := clientset.CoreV1().Pods("").List(context.TODO(), metav1.ListOptions{})
        if err != nil {
            panic(err.Error())
        }
        fmt.Printf("There are %d pods in the cluster\n", len(pods.Items))

        // Examples for error handling:
        // - Use helper functions like e.g. errors.IsNotFound()
        // - And/or cast to StatusError and use its properties like e.g. ErrStatus.Message
        namespace := "default"
        pod := "example-xxxxx"
        _, err = clientset.CoreV1().Pods(namespace).Get(context.TODO(), pod, metav1.GetOptions{})
        if errors.IsNotFound(err) {
            fmt.Printf("Pod %s in namespace %s not found\n", pod, namespace)
        } else if statusError, isStatus := err.(*errors.StatusError); isStatus {
            fmt.Printf("Error getting pod %s in namespace %s: %v\n",
                pod, namespace, statusError.ErrStatus.Message)
        } else if err != nil {
            panic(err.Error())
        } else {
            fmt.Printf("Found pod %s in namespace %s\n", pod, namespace)
        }
        time.Sleep(10 * time.Second)
    }

}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市语婴,隨后出現(xiàn)的幾起案子描孟,更是在濱河造成了極大的恐慌,老刑警劉巖砰左,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件匿醒,死亡現(xiàn)場離奇詭異,居然都是意外死亡缠导,警方通過查閱死者的電腦和手機廉羔,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來僻造,“玉大人憋他,你說我怎么就攤上這事∷柘鳎” “怎么了竹挡?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長立膛。 經(jīng)常有香客問我此迅,道長,這世上最難降的妖魔是什么旧巾? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任耸序,我火速辦了婚禮,結(jié)果婚禮上鲁猩,老公的妹妹穿的比我還像新娘坎怪。我一直安慰自己,他們只是感情好廓握,可當(dāng)我...
    茶點故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布搅窿。 她就那樣靜靜地躺著嘁酿,像睡著了一般。 火紅的嫁衣襯著肌膚如雪男应。 梳的紋絲不亂的頭發(fā)上闹司,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天,我揣著相機與錄音沐飘,去河邊找鬼游桩。 笑死,一個胖子當(dāng)著我的面吹牛耐朴,可吹牛的內(nèi)容都是我干的借卧。 我是一名探鬼主播,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼筛峭,長吁一口氣:“原來是場噩夢啊……” “哼铐刘!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起影晓,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤镰吵,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后挂签,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體疤祭,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年竹握,在試婚紗的時候發(fā)現(xiàn)自己被綠了画株。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片辆飘。...
    茶點故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡啦辐,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出蜈项,到底是詐尸還是另有隱情芹关,我是刑警寧澤,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布紧卒,位于F島的核電站侥衬,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏跑芳。R本人自食惡果不足惜轴总,卻給世界環(huán)境...
    茶點故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望博个。 院中可真熱鬧怀樟,春花似錦、人聲如沸盆佣。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至虑灰,卻和暖如春吨瞎,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背穆咐。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工颤诀, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人庸娱。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓着绊,卻偏偏與公主長得像,于是被迫代替她去往敵國和親熟尉。 傳聞我的和親對象是個殘疾皇子归露,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,033評論 2 355

推薦閱讀更多精彩內(nèi)容