概述
以C/S的视角看,List-Watch发生在2个地方,一个是client-go中,一个在api-server中。
- client-go向api-server发起list和watch请求,通信方式是HTTP2的chunk模式
- api-server向etcd发起list和watch,将数据缓存在内存的一个环形数组中,resourceVersion从小到大有序
细节
源码索引
client-go: reflector
client-go中负责向api-server发起list-watch的核心组件是reflector,我们可以找到它的定义:
staging/src/k8s.io/client-go/tools/cache/reflector.go
type Reflector struct {
listerWatcher ListerWatcher
}
// ListAndWatch first lists all items and get the resource version at the moment of call,
// and then use the resource version to watch.
func (r *Reflector) ListAndWatch(stopCh <-chan struct{}) error {
pager := pager.New(pager.SimplePageFunc(func(opts metav1.ListOptions) (runtime.Object, error) {
return r.listerWatcher.List(opts)
}))
w, err := r.listerWatcher.Watch(options)
}
暂且不管listerWatcher是如何实现的,可以从源码中精准地判断list和watch是2个不同的操作。
informerFactory: options
NewSharedInformerFactoryWithOptions 方法让用户可以传递ListOptions,那么这个Options是如何其作用的呢,以PodInformer为例。
type sharedInformerFactory struct {
client kubernetes.Interface
namespace string
tweakListOptions internalinterfaces.TweakListOptionsFunc
lock sync.Mutex
defaultResync time.Duration
customResync map[reflect.Type]time.Duration
informers map[reflect.Type]cache.SharedIndexInformer
// startedInformers is used for tracking which informers have been started.
// This allows Start() to be called multiple times safely.
startedInformers map[reflect.Type]bool
}
type podInformer struct {
factory internalinterfaces.SharedInformerFactory
tweakListOptions internalinterfaces.TweakListOptionsFunc
namespace string
}
func (f *podInformer) defaultInformer(client kubernetes.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
return NewFilteredPodInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
}
func NewFilteredPodInformer(client kubernetes.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
return cache.NewSharedIndexInformer(
&cache.ListWatch{
ListFunc: func(options metav1.ListOptions) (runtime.Object, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.CoreV1().Pods(namespace).List(context.TODO(), options)
},
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.CoreV1().Pods(namespace).Watch(context.TODO(), options)
},
},
&corev1.Pod{},
resyncPeriod,
indexers,
)
}
api-server: watchCache
watchCache 是缓存对象的环形缓冲区
type watchCache struct {
cache []*watchCacheEvent
startIndex int
endIndex int
}
func (w *watchCache) updateCache(event *watchCacheEvent) {
w.resizeCacheLocked(event.RecordTime)
if w.isCacheFullLocked() {
// Cache is full - remove the oldest element.
w.startIndex++
}
w.cache[w.endIndex%w.capacity] = event
w.endIndex++
}
// Creates a cacher based given storageConfig.
func StorageWithCacher() generic.StorageDecorator {
}
func NewCacherFromConfig(config Config) (*Cacher, error) {
}
参考
blog.csdn.net/Matthew__M/… developer.aliyun.com/article/939… zhuanlan.zhihu.com/p/59660536 zhuanlan.zhihu.com/p/33335726