k8s编程-operator-SharedInformer

640 阅读2分钟

概要

  • 什么是SharedInformer
  • 演示SharedInformer监听资源变化的过程

什么是SharedInformer

首先先要解释下Informer。 在k8s中,需要保证controller中持有object的准确信息。为了实现这一点,就需要与apiserver进行通讯,来保证状态一致。Informer就是用来完成这个功能的。

前置提到的Reflector, Indexer,DeltaFIFO 都属于Informer的一部分。

每个controller都持有一个Informer,如果每个Informer的cache都是独占的,无疑会造成很大的性能损耗。为了提升性能,降低损耗。 这里使用了SharedInformer。 详情 shared informer

image.png

主要作用

  • 缓存资源的最新数据。创建Indexer/Clientset(通过listerwatcher)/DeltaFIFO/Controller(包含Reflector),将各个资源连接起来。
  • 根据资源对象的变化事件来通知我们注册的事件处理方法

创建

  • NewSharedIndexInformer:创建Informer的基本方法
  • NewDeploymentInformer:创建内建资源对象对应的Informer的方法
  • NewSharedInformerFactory:通过map存储创建过的Informer,达到复用共享的目的。
type sharedIndexInformer struct {
    indexer                         Indexer
    controller                      Controller
    processor                       *sharedProcessor
    cacheMutationDetector           MutationDetector
    listerWatcher                   ListerWatcher
    objectType                      runtime.Object
    resyncCheckPeriod               time.Duration
    defaultEventHandlerResyncPeriod time.Duration
    clock                           clock.Clock
    started, stopped                bool
    startedLock                     sync.Mutex
    blockDeltas                     sync.Mutex
    watchErrorHandler               WatchErrorHandler
    transform                       TransformFunc
}

实践

通过如下代码,创建一个informmer,观察资源的变化情况。将要进行如下操作

  • 执行程序,预期:观察到现有资源的add
  • 创建pod,预期:观察到add和update
  • 删除pod,预期:观察到delete和update

代码

package main

import (
   "fmt"

   "k8s.io/client-go/informers"
   "k8s.io/client-go/kubernetes"
   "k8s.io/client-go/tools/cache"
   "k8s.io/client-go/tools/clientcmd"
)

func main() {
   //create config
   config, err := clientcmd.BuildConfigFromFlags("", clientcmd.RecommendedHomeFile)
   if err != nil {
      panic(err)
   }

   //create client
   clientset, err := kubernetes.NewForConfig(config)
   if err != nil {
      panic(err)
   }

   //create informer in namespace "default"
   //factory := informers.NewSharedInformerFactory(clientset, 0)   // in all namespace
   factory := informers.NewSharedInformerFactoryWithOptions(clientset, 0, informers.WithNamespace("default"))

   // 拿到Pod对应的informer,注册EventHandler
   // 当Pod发生变化时,会触发EventHandler
   // 未注册的handler,不会触发,可以在 `ResourceEventHandler`中看到
   informer := factory.Core().V1().Pods().Informer()

   //register event handler
   informer.AddEventHandler(cache.ResourceEventHandlerFuncs{
      AddFunc: func(obj interface{}) {
         fmt.Println("add Event")
      },
      UpdateFunc: func(old, new interface{}) {
         fmt.Println("update Event")
      },
      DeleteFunc: func(obj interface{}) {
         fmt.Println("delete Event")
      },
   })


   //start factory
   stopCh := make(chan struct{})
   factory.Start(stopCh)
   // 等待同步完成
   factory.WaitForCacheSync(stopCh)
   <-stopCh
}

执行结果

如下图,整体执行结果符合预期

image.png

参考

Understanding Kubernetes controllers part III – informers – LeftAsExercise

A Deep Dive Into Kubernetes Informers (arriqaaq.com)