Reflector
Reflector原理
reflector在client-go里面的主要作用是与apiserver进行交互,获取自定义资源数据更新到Delta FIFO队列里面,所以它主要分为两部分功能,一部分是list和watch的功能,另一部分是更新缓存的功能。
Reflector的创建
func NewReflector(lw ListerWatcher, expectedType interface{}, store Store, resyncPeriod time.Duration) *Reflector {
...
}
参数说明:
lw
:interface,包含了interface Lister和Watcher。通过ListerWatcher获取初始化指定资源的列表和监听指定资源变化事件expectedType
:期望监听和获取的资源类型,比如pod
deployment
等等store
:指定存储,需要实现Store这个interface。resyncPeriod
:同步周期。
List和Watch
list和watch是reflector主要核心功能之一,它可以保证Controller或者Operator具有可靠性,实时性和顺序性,可靠性是由List和Watch共同来完成的,实时性是由Watch来完成的,
List
:指定类型资源对象的全量更新(Controller或者Operator启动的时候会调用,比如资源类型为pod时,调用的是下面这种API,来获取pod的全量更新)。并将其更新到缓存中。
curl -iv http://127.0.0.1:8001/api/v1/namespaces/default/pods
Watch
:指定类型资源对象的增量更新(假如要监听pod的变化时,可以在List这个API上加一个参数watch=true
就可以监听资源对象的事件变化)。
curl -iv http://127.0.0.1:8001/api/v1/namespaces/default/pods\?watch=true
K8S API文档:
https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#list-pod-v1-core
ResourceVersion
与Bookmarks
ResourceVersion
在K8S中每一个资源对象都有一个ResourceVersion,当资源对象发生变更时ResourceVersion就会发生递增的变更,使对应到ETCD的reversion的变更
- 保证客户端数据一致性和顺序性
- 并发控制(可以保证多个客户端并发去更改资源对象时,出现的并发问题)
Bookmarks
- 减少apiserver负载(高版本的apiserver才支持Bookmarks)
- 更新客户端保存的最近一次ResourceVersion
所以说我们的客户端当接受到bookmark的事件的时候,我们可以从这个事件里面的ResourceVersion提取出来,然后更新我们本地的ResourceVersion,然后接着以这个ResourceVersion去watch我们的资源对象的变更。
Reflector
与RESTClient
client-go提供的client与Reflector有什么关系呢?
Reflector如果要跟apiserver进行交互的话,就会通过RESTClient或者是其他的client。以下例子是informer里面的,它实现了相应的接口,并提供了list和watch方法,里面的逻辑就是调用的clientset。
...
&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)
},
},
...