☰
Go client-go 实战:从 Informer 到 Lister 高级用法
2026/10/1 17:07:08 网站建设 项目流程

Go client-go 实战:从 Informer 到 Lister 高级用法

K8s Operator 开发离不开 client-go。本文系统讲清 client-go 的核心 API 与最佳实践。

一、client-go 三大基础组件

  • Clientset:高级抽象,提供 typed / dynamic client
  • Informer:本地 cache 监听 API server 推送
  • Lister:从 Informer 缓存里取数据,本地查询快

二、Clientset 简单使用

import"k8s.io/client-go/kubernetes"import"k8s.io/client-go/tools/clientcmd"cfg,_:=clientcmd.BuildConfigFromFlags("",kubeconfig)clientset,_:=kubernetes.NewForConfig(cfg)pods,_:=clientset.CoreV1().Pods("default").List(ctx,metav1.ListOptions{})for_,pod:=rangepods.Items{fmt.Println(pod.Name)}

直接 call API Server 会带来 list/transform 负担,影响主流程。

三、SharedInformerFactory

factory:=informers.NewSharedInformerFactoryWithOptions(clientset,30*time.Second,informers.WithNamespace("default"),)podInformer:=factory.Core().V1().Pods()

factory 同一资源只走一份 watcher。

四、Lister + Indexer

podLister:=podInformer.Lister()pods,_:=podLister.Pods("default").List(labels.Everything())

Lister 直接从 indexer / cache 取,不打 API server。

五、Indexer 自定义索引

podInformer.Informer().GetIndexer().AddIndexers(map[string]IndexFunc{"podIP":func(objinterface{})([]string,error){pod:=obj.(*v1.Pod)return[]string{pod.Status.PodIP},nil},})podsByIP,_:=podLister.ByIndex("podIP","10.0.0.1")

方便快速查询。

六、EventHandler 监听

podInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{OnAdd:func(objinterface{}){p:=obj.(*v1.Pod)log.Printf("POD ADDED: %s",p.Name)},OnUpdate:func(old,newinterface{}){// 监听变化},OnDelete:func(objinterface{}){// 清理资源},})

七、Workqueue + 限速

import"k8s.io/client-go/util/workqueue"queue:=workqueue.NewRateLimitingQueue(workqueue.DefaultControllerRateLimiter())podInformer.Informer().AddEventHandler(&cache.ResourceEventHandlerFuncs{OnAdd:func(objinterface{}){key,_:=cache.MetaNamespaceKeyFunc(obj)queue.Add(key)},})gofunc(){for{key,_:=queue.Get()deferqueue.Done(key)iferr:=process(key.(string));err!=nil{queue.AddRateLimited(key)return}queue.Forget(key)}}()

八、Dynamic Client

无类型时用:

import"k8s.io/client-go/dynamic"dyn,_:=dynamic.NewForConfig(cfg)gvr:=schema.GroupVersionResource{Group:"apps",Version:"v1",Resource:"deployments"}unstr,_:=dyn.Resource(gvr).Namespace("default").Get(ctx,"myapp",metav1.GetOptions{})

适合写通用 K8s 工具。

九、Discovery

import"k8s.io/client-go/discovery"discoveryClient,_:=discovery.NewDiscoveryClientForConfig(cfg)apiGroups,_,_:=discoveryClient.ServerGroupsAndResources()

动态发现 API。

十、踩坑清单

  1. Informer 启动后再入队——否则会 miss 事件
  2. ResyncPeriod不要设 0,会触发全量重做
  3. Lister Get 不报错:可能数据仍是空
  4. Workqueue 别忘了 ShutDown

十一、实战:自定义控制器

funcprocess(keystring)error{ns,name,_:=cache.SplitMetaNamespaceKey(key)pod,err:=lister.Pods(ns).Get(name)iferr!=nil{returnerr}returnbusinessLogic(pod)}

标准 Operator 流程:

Informer → Workqueue → Worker → Reconcile → Status Update

十二、生产实战:cluster-operator

Deployment:

apiVersion:apps/v1kind:Deploymentmetadata:name:controllernamespace:controller-systemspec:replicas:1template:spec:serviceAccountName:controllercontainers:-name:controllerimage:my/controller:v1

十三、总结与展望

client-go 是 K8s 编程的"圣杯"。Informer + Lister + Workqueue 三件套让资源高效监听 + 优雅处理。掌握它能写出生产级 Operator。

未来:controller-runtime 抽象层越来越普及,复杂 K8s 平台开发门槛进一步降低。

十四、参考文献

  • client-go 仓库
  • sample-controller 示例
  • Programming Kubernetes book

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询