k8s client-go源码分析 informer源码分析(3)-Reflector源码分析
1.Reflector概述
Reflector从kube-apiserver中list&watch资源对象,然后将对象的变化包装成Delta并将其丢到DeltaFIFO中。简单点来说,就是将Etcd 的对象及其变化反射到DeltaFIFO中。
Reflector首先通过List操作获取全量的资源对象数据,调用DeltaFIFO的Replace方法全量插入DeltaFIFO,然后后续通过Watch操作根据资源对象的变化类型相应的调用DeltaFIFO的Add、Update、Delete方法,将对象及其变化插入到DeltaFIFO中。
Reflector的健壮性处理机制
Reflector有健壮性处理机制,用于处理与apiserver
断连后重新进行List&Watch
的场景。也是因为有这样的健壮性处理机制,所以我们一般不去直接使用客户端的Watch
方法来处理自己的业务逻辑,而是使用informers
。
Reflector核心操作
Reflector的两个核心操作:
(1)List&Watch;
(2)将对象的变化包装成Delta然后扔进DeltaFIFO。
informer概要架构图
通过下面这个informer的概要架构图,可以大概看到Reflector在整个informer中所处的位置及其作用。
2.Reflector初始化与启动分析
2.1 Reflector结构体
先来看到Reflector结构体,这里重点看到以下属性:
(1)expectedType:放到Store中(即DeltaFIFO中)的对象类型;
(2)store:store会赋值为DeltaFIFO,具体可以看之前的informer初始化与启动分析即可得知,这里不再展开分析;
(3)listerWatcher:存放list方法和watch方法的ListerWatcher interface实现;
// k8s.io/client-go/tools/cache/reflector.go
type Reflector struct {
// name identifies this reflector. By default it will be a file:line if possible.
name string
// The name of the type we expect to place in the store. The name
// will be the stringification of expectedGVK if provided, and the
// stringification of expectedType otherwise. It is for display
// only, and should not be used for parsing or comparison.
expectedTypeName string
// The type of object we expect to place in the store.
expectedType reflect.Type
// The GVK of the object we expect to place in the store if unstructured.
expectedGVK *schema.GroupVersionKind
// The destination to sync up with the watch source
store Store
// listerWatcher is used to perform lists and watches.
listerWatcher ListerWatcher
// period controls timing between one watch ending and
// the beginning of the next one.
period time.Duration
resyncPeriod time.Duration
ShouldResync func() bool
// clock allows tests to manipulate time
clock clock.Clock
// lastSyncResourceVersion is the resource version token last
// observed when doing a sync with the underlying store
// it is thread safe, but not synchronized with the underlying store
lastSyncResourceVersion string
// lastSyncResourceVersionMutex guards read/write access to lastSyncResourceVersion
lastSyncResourceVersionMutex sync.RWMutex
// WatchListPageSize is the requested chunk size of initial and resync watch lists.
// Defaults to pager.PageSize.
WatchListPageSize int64
}
2.2 Reflector初始化-NewReflector
NewReflector为Reflector的初始化方法,返回一个Reflector结构体,这里主要看到初始化Reflector的时候,需要传入ListerWatcher interface的实现。
// k8s.io/client-go/tools/cache/reflector.go
func NewReflector(lw ListerWatcher, expectedType interface{}, store Store, resyncPeriod time.Duration) *Reflector {
return NewNamedReflector(naming.GetNameFromCallsite(internalPackages...), lw, expectedType, store, resyncPeriod)
}
// NewNamedReflector same as NewReflector, but with a specified name for logging
func NewNamedReflector(name string, lw ListerWatcher, expectedType interface{}, store Store, resyncPeriod time.Duration) *Reflector {
r := &Reflector{
name: name,
listerWatcher: lw,
store: store,
period: time.Second,
resyncPeriod: resyncPeriod,
clock: &clock.RealClock{},
}
r.setExpectedType(expectedType)
return r
}
2.3 ListerWatcher interface
ListerWatcher interface定义了Reflector
应该拥有的最核心的两个方法,即List
与Watch
,用于全量获取资源对象以及监控资源对象的变化。关于List
与Watch
什么时候会被调用,怎么被调用,在后续分析Reflector核心处理方法的时候会详细做分析。
// k8s.io/client-go/tools/cache/listwatch.go
type Lister interfa