client-go如何監聽自定義資源

如何使用 client-go 監聽自定義資源

在 Kubernetes 中使用 client-go 監聽自定義資源(Custom Resource,簡稱 CR)需要借助 Dynamic ClientCustom Informer,因為 client-go 的標準 Clientset 只支持內置資源(如 Pod、Deployment)。自定義資源由 CustomResourceDefinition(CRD)或 Operator 定義,監聽它們需要動態處理其 Group、Version 和 Resource(GVR)。以下是詳細步驟和實現方法。


前提條件

  • CRD 已部署:確保你的自定義資源定義(CRD)已在集群中注冊。
    • 示例:myresource.example.com/v1,Kind 為 MyResource
  • 依賴
    • client-go(推薦與集群版本匹配,例如 v0.28.0 對應 Kubernetes 1.28)。
    • 添加依賴:
      go get k8s.io/client-go@v0.28.0
      
  • 權限:確保 ServiceAccount 有權訪問 CRD(通過 RBAC 配置)。

方法 1:使用 Dynamic Client 和 Informer

Dynamic Clientclient-go 提供的通用客戶端,支持任意資源類型。結合 SharedInformer,可以監聽自定義資源。

步驟

  1. 初始化 Dynamic Client

    package mainimport ("context""log""time""k8s.io/apimachinery/pkg/apis/meta/v1/unstructured""k8s.io/apimachinery/pkg/runtime/schema""k8s.io/client-go/dynamic""k8s.io/client-go/rest""k8s.io/client-go/tools/cache""k8s.io/client-go/tools/clientcmd"
    )func getDynamicClient() dynamic.Interface {config, err := rest.InClusterConfig()if err != nil {config, err = clientcmd.BuildConfigFromFlags("", "/path/to/kubeconfig")if err != nil {log.Fatalf("Failed to create config: %v", err)}}client, err := dynamic.NewForConfig(config)if err != nil {log.Fatalf("Failed to create dynamic client: %v", err)}return client
    }
    
  2. 定義 GVR

    • 指定自定義資源的 Group、Version 和 Resource。
    • 示例:myresource.example.com/v1,資源名為 myresources
      gvr := schema.GroupVersionResource{Group:    "example.com",Version:  "v1",Resource: "myresources",
      }
      
  3. 創建 Dynamic Informer

    func main() {client := getDynamicClient()// 創建 Dynamic Informer Factoryfactory := dynamicinformer.NewDynamicSharedInformerFactory(client, time.Minute*30)informer := factory.ForResource(gvr).Informer()// 添加事件處理函數informer.AddEventHandler(cache.ResourceEventHandlerFuncs{AddFunc: func(obj interface{}) {unstructuredObj := obj.(*unstructured.Unstructured)name := unstructuredObj.GetName()namespace := unstructuredObj.GetNamespace()log.Printf("CR Added: %s/%s", namespace, name)},UpdateFunc: func(oldObj, newObj interface{}) {oldUnstructured := oldObj.(*unstructured.Unstructured)newUnstructured := newObj.(*unstructured.Unstructured)log.Printf("CR Updated: %s/%s", newUnstructured.GetNamespace(), newUnstructured.GetName())},DeleteFunc: func(obj interface{}) {unstructuredObj := obj.(*unstructured.Unstructured)log.Printf("CR Deleted: %s/%s", unstructuredObj.GetNamespace(), unstructuredObj.GetName())},})// 啟動 Informerctx, cancel := context.WithCancel(context.Background())defer cancel()factory.Start(ctx.Done())factory.WaitForCacheSync(ctx.Done())// 保持運行<-ctx.Done()
    }
    
  4. 獲取緩存數據

    lister := factory.ForResource(gvr).Lister()
    items, err := lister.List(labels.Everything())
    if err != nil {log.Printf("Failed to list CRs: %v", err)
    } else {for _, item := range items {unstructuredObj := item.(*unstructured.Unstructured)log.Printf("Current CR: %s/%s", unstructuredObj.GetNamespace(), unstructuredObj.GetName())}
    }
    

說明

  • GVR:通過 kubectl api-resources 查看自定義資源的準確 GVR。
  • Unstructured:自定義資源以 unstructured.Unstructured 類型返回,需手動解析字段。
  • 依賴:需要導入 k8s.io/client-go/dynamic/informer

方法 2:生成類型化客戶端和 Informer(推薦生產環境)

如果你的 CRD 有明確的 Go 類型(通過代碼生成器生成),可以使用類型化的客戶端和 Informer。這種方法需要更多前期工作,但更安全和直觀。

步驟

  1. 生成代碼

    • 使用 controller-toolsk8s.io/code-generator 生成 CRD 的客戶端代碼。
    • 示例 CRD 文件(myresource_v1.yaml):
      apiVersion: apiextensions.k8s.io/v1
      kind: CustomResourceDefinition
      metadata:name: myresources.example.com
      spec:group: example.comnames:kind: MyResourceplural: myresourcesscope: Namespacedversions:- name: v1served: truestorage: trueschema:openAPIV3Schema:type: objectproperties:spec:type: objectproperties:replicas:type: integer
      
    • 生成命令:
      mkdir -p pkg/apis/example.com/v1
      controller-gen crd paths=./pkg/apis/example.com/v1 output:crd:dir=./manifests
      controller-gen object paths=./pkg/apis/example.com/v1
      k8s.io/code-generator/generate-groups.sh all ./pkg/client ./pkg/apis example.com:v1
      
  2. 注冊類型

    • pkg/apis/example.com/v1/types.go 中定義類型:
      package v1import (metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
      )type MyResourceSpec struct {Replicas int32 `json:"replicas"`
      }type MyResource struct {metav1.TypeMeta   `json:",inline"`metav1.ObjectMeta `json:"metadata,omitempty"`Spec              MyResourceSpec `json:"spec,omitempty"`
      }type MyResourceList struct {metav1.TypeMeta `json:",inline"`metav1.ListMeta `json:"metadata,omitempty"`Items           []MyResource `json:"items"`
      }
      
  3. 創建 Informer

    package mainimport ("context""log""time""k8s.io/client-go/tools/cache"examplev1 "your/module/pkg/apis/example.com/v1"exampleclientset "your/module/pkg/client/clientset/versioned"exampleinformers "your/module/pkg/client/informers/externalversions"
    )func main() {config, err := rest.InClusterConfig()if err != nil {log.Fatalf("Failed to create config: %v", err)}client, err := exampleclientset.NewForConfig(config)if err != nil {log.Fatalf("Failed to create clientset: %v", err)}factory := exampleinformers.NewSharedInformerFactory(client, time.Minute*30)informer := factory.Example().V1().MyResources().Informer()informer.AddEventHandler(cache.ResourceEventHandlerFuncs{AddFunc: func(obj interface{}) {myResource := obj.(*examplev1.MyResource)log.Printf("MyResource Added: %s/%s, Replicas: %d", myResource.Namespace, myResource.Name, myResource.Spec.Replicas)},UpdateFunc: func(oldObj, newObj interface{}) {newResource := newObj.(*examplev1.MyResource)log.Printf("MyResource Updated: %s/%s", newResource.Namespace, newResource.Name)},DeleteFunc: func(obj interface{}) {myResource := obj.(*examplev1.MyResource)log.Printf("MyResource Deleted: %s/%s", myResource.Namespace, myResource.Name)},})ctx, cancel := context.WithCancel(context.Background())defer cancel()factory.Start(ctx.Done())factory.WaitForCacheSync(ctx.Done())<-ctx.Done()
    }
    

說明

  • 類型安全:使用生成的類型(如 *examplev1.MyResource),避免手動解析。
  • 依賴:需要自定義的客戶端包(pkg/client)。
  • 復雜度:前期生成代碼較繁瑣,但長期維護更方便。

注意事項

  1. CRD 注冊
    • 確保 CRD 已應用(kubectl apply -f myresource_v1.yaml)。
    • 檢查:
      kubectl get crd myresources.example.com
      
  2. 權限
    • 為 ServiceAccount 配置 RBAC:
      apiVersion: rbac.authorization.k8s.io/v1
      kind: ClusterRole
      metadata:name: myresource-reader
      rules:
      - apiGroups: ["example.com"]resources: ["myresources"]verbs: ["get", "list", "watch"]
      ---
      apiVersion: rbac.authorization.k8s.io/v1
      kind: ClusterRoleBinding
      metadata:name: myresource-reader-binding
      subjects:
      - kind: ServiceAccountname: defaultnamespace: default
      roleRef:kind: ClusterRolename: myresource-readerapiGroup: rbac.authorization.k8s.io
      
  3. 性能
    • 使用 WithNamespace 或標簽過濾減少監聽范圍。
  4. 錯誤處理
    • Watch 失敗時,Informer 會自動重試,需關注日志。

驗證

  1. 創建自定義資源

    apiVersion: example.com/v1
    kind: MyResource
    metadata:name: test-resourcenamespace: default
    spec:replicas: 3
    
    kubectl apply -f test-resource.yaml
    
  2. 運行程序,觀察日志輸出

    MyResource Added: default/test-resource, Replicas: 3
    

總結

  • Dynamic Client
    • 適合快速實現,無需生成代碼。
    • 使用 unstructured.Unstructured 處理數據。
  • 類型化客戶端
    • 適合生產環境,類型安全,需生成代碼。
    • 使用特定類型(如 *MyResource)操作。
  • 選擇建議
    • 測試或簡單場景:Dynamic Client。
    • 長期項目或 Operator:類型化客戶端。

如果你有具體的 CRD 定義或需求(例如監聽特定字段),可以告訴我,我會進一步定制代碼!


---

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/75722.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/75722.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/75722.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

C++軟件開發架構

文章目錄 1.全局消息通信MsgHandler.h單元測試(QTest)MsgHandlerUnitTest.hMsgHandlerUnitTest.cpp 2.實例間通信InstMsgHandler.h單元測試InstMsgHandlerUnitTest.hInstMsgHandlerUnitTest.cpp 1.全局消息通信 1. 適用于類與類單個對象實例之間的通信&#xff0c;多個對象需要…

AI Agent設計模式一:Chain

概念 &#xff1a;線性任務流設計 ? 優點&#xff1a;邏輯清晰易調試&#xff0c;適合線性處理流程? 缺點&#xff1a;缺乏動態分支能力 from typing import TypedDictfrom langgraph.graph import StateGraph, END# 定義后續用到的一些變量 class CustomState(TypedDict):p…

Git三劍客:工作區、暫存區、版本庫深度解析

一、引言&#xff1a;為什么需要理解Git的核心區域&#xff1f; 作為開發者&#xff0c;Git是日常必備的版本控制工具。但你是否曾因以下問題感到困惑&#xff1f; 修改了文件&#xff0c;但 git status 顯示一片混亂&#xff1f; git add 和 git commit 到底做了什么&#x…

Python數據類型-list

列表(List)是Python中最常用的數據類型之一&#xff0c;它是一個有序、可變的元素集合。 1. 列表基礎 創建列表 empty_list [] # 空列表 numbers [1, 2, 3, 4, 5] # 數字列表 fruits [apple, banana, orange] # 字符串列表 mixed [1, hello, 3.14, True] # 混合類型…

Keepalive+LVS+Nginx+NFS高可用項目

項目架構 分析 主機規劃 主機系統安裝應用網絡IPclientredhat 9.5無NAT172.25.250.115/24lvs-masterrocky 9.5ipvsadm&#xff0c;keepalivedNAT172.25.250.116/24 VIP 172.25.250.100/32lvs-backuprocky 9.5ipvsadm&#xff0c;keepalivedNAT172.25.250.117/24 VIP 172.25.2…

【視覺與語言模型參數解耦】為什么?方案?

一些無編碼器的MLLMs統一架構如Fuyu&#xff0c;直接在LLM內處理原始像素&#xff0c;消除了對外部視覺模型的依賴。但是面臨視覺與語言模態沖突的挑戰&#xff0c;導致訓練不穩定和災難性遺忘等問題。解決方案則是通過參數解耦方法解決模態沖突。 在多模態大語言模型&#xf…

AI比人腦更強,因為被植入思維模型【43】蝴蝶效應思維模型

giszz的理解&#xff1a;蝴蝶效應我們都熟知&#xff0c;就是說一個微小的變化&#xff0c;能帶動整個系統甚至系統的空間和時間的遠端&#xff0c;產生巨大的鏈式反應。我學習后的啟迪&#xff0c;簡單的說&#xff0c;就是不要忽視任何微小的問題&#xff0c;更多時候&#x…

AI 數理邏輯基礎之統計學基本原理(上)

目錄 文章目錄 目錄統計學統計學基本概念描述性統計數據可視化圖表工具 匯總統計統計數據的分布情況&#xff1a;中位數、眾數、平均值統計數據的離散程度&#xff1a;極差、方差、標準差、離散系數 相關分析Pearson 線性關系相關系數Spearman 單調關系相關系數 回歸分析回歸模…

無招回歸阿里

這兩天&#xff0c;無招回歸阿里的新聞被刷屏了。無招創業成立的兩氫一氧公司無招的股份也被阿里收購&#xff0c;無招以這種姿態回歸阿里&#xff0c;并且出任釘釘的 CEO。有人說&#xff0c;這是對 5 年前“云釘一體”戰略的糾偏。現在確實從云優先到 AI 優先&#xff0c;但云…

算法題(114):矩陣距離

審題&#xff1a; 本題需要我們找出所有0距離最近的1的曼哈頓距離 思路&#xff1a; 方法一&#xff1a;多源bfs 分析曼哈頓距離&#xff1a; 求法1&#xff1a;公式法&#xff0c;帶入題目公式&#xff0c;利用|x1-x2||y1-y2|求出 求法2&#xff1a;曼哈頓距離就是最短距離 本…

LLM 性能優化有哪些手段?

LLM(大語言模型)性能優化是一個多維度、多層次的系統工程,涉及從提示工程到模型微調,從推理加速到系統架構優化等多個方面。以下是當前主流的優化手段及其技術細節: 一、提示工程(Prompt Engineering) 提示工程是優化LLM性能最直接、成本最低的方法,適用于快速原型開發…

群體智能避障革命:RVO算法在Unity中的深度實踐與優化

引言&#xff1a;游戲群體移動的挑戰與進化 在《全面戰爭》中萬人戰場恢弘列陣&#xff0c;在《刺客信條》鬧市里人群自然涌動&#xff0c;這些令人驚嘆的場景背后&#xff0c;都離不開一個關鍵技術——群體動態避障。傳統路徑規劃算法&#xff08;如A*&#xff09;雖能解決單…

I.MX6ULL 交叉編譯環境配置與使用

一、什么是交叉編譯 我們一般開發程序在自己的電腦上開發&#xff0c;運行的時候將程序燒錄到板子運行。但我們的開發平臺是X86架構&#xff0c;而I.MX6ULL是ARM架構&#xff0c;所以需要一個在 X86 架構的 PC 上運行&#xff0c;可以編譯 ARM 架構代碼的 GCC 編譯器&#xff0…

Harmony OS“一多” 詳解:基于窗口變化的斷點自適應實現

一、一多開發核心概念&#xff08;18N模式&#xff09; 目標&#xff1a;一次開發多端部署 解決的問題&#xff1a; 1、界面級一多&#xff1a;適配不同屏幕尺寸 2、功能級一多&#xff1a;設備功能兼容性處理(CanIUser) 3、工…

SpringMvc獲取請求數據

基本參數 RequestMapping("save5") ResponseBody public User save5(String name, int age) {User user new User();user.setName(name);user.setAge(age);return user; } 在url中將name與age進行編寫&#xff0c;通過框架可以提取url中的name與age&#xff0c;這…

大模型持續學習方案解析:災難性遺忘的工業級解決方案

引言 隨著大型語言模型&#xff08;LLMs&#xff09;如 GPT 系列、BERT 等在自然語言處理領域取得突破性進展&#xff0c;它們強大的理解和生成能力已經滲透到各行各業。然而&#xff0c;這些模型通常是在海量靜態數據集上進行一次性預訓練的。現實世界是動態變化的&#xff0…

推薦系統(二十二):基于MaskNet和WideDeep的商品推薦CTR模型實現

在上一篇文章《推薦系統&#xff08;二十一&#xff09;&#xff1a;基于MaskNet的商品推薦CTR模型實現》中&#xff0c;筆者基于 MaskNet 構建了一個簡單的模型。筆者所經歷的工業級實踐證明&#xff0c;將 MaskNet 和 Wide&Deep 結合應用&#xff0c;可以取得不錯的效果&…

【爬蟲案例】采集 Instagram 平臺數據幾種方式(python腳本可直接運行)

更多內容請見: 爬蟲和逆向教程-專欄介紹和目錄 文章目錄 一、概述1.1 Instagram基礎信息1.2 Instagram平臺架構核心技術棧1.3 采集提示1.4 幾種采集方案對比二、四種采集方案分析三、寫爬蟲采集Instagram案例3.1 采集作品信息并下載視頻或圖片(無需登錄)3.2 explore接口的采…

OFP--2018

文章目錄 AbstractIntroductionRelated Work2D object detection3D object detection from LiDAR3D object detection from imagesIntegral images 3D Object Detection ArchitectureFeature extractionOrthographic feature transformFast average pooling with integral imag…

LINUX 4 tar -zcvf -jcvf -Jcvf -tf -uf

cp -r mv: 1.移動文件到目錄 2.文件改名 3.目錄改名 s 上面是打包 下面是打包并壓縮