replication controller是kube-controller-manager中一个重要的控制器,主要是通过rs进行控制,确保pods的数量恰好和rs的规定一致。因此replication controller主要对这两类进行watch,一类是replicationset,另一类是pods。本文是replication controller的源码阅读笔记,会包括client-go的Informer机制,希望帮助开始阅读kubernetes源码的小伙伴们,更希望与对kubernetes源码阅读感兴趣的小伙伴儿们交流,有错误的地方也希望能指出,共同进步。
更新日志:
1. 源码分析从kubernetes tag v1.9.0更新到kubernetes tag v1.10.1;(改动很小)
2. 增加了相关的流程示意图;
更新时间:2018年4月14日
replicationController初始化过程:
startReplicationController
cmd/kube-controller-manager/app/core.go
startReplicationController方法
- 协程调用replicationcontroller.NewReplicationManager,构建ReplicationManager;
- 调用ctx.InformerFactory.Core().V1().Pods(),这里调用sharedInformerFactory(client-go/informers/factory.go)的Core().V1().Pods()方法,将会构建PodInformer对象;
- 以此方式,创建rcInformer;
- 运行ReplicationManager;
NewReplicationManager
pkg/controller/replication/replication_controller.go
NewReplicationManager方法
- 在NewReplicationManager中,
- 首先,调用record.NewBroadcaster,创建eventBroadcaster对象,调用eventBroadcaster.StartLogging,接收EventBroadcaster发送的event,输出到logging中;调用 eventBroadcaster.StartRecordingToSink,event输出到EventSink,并调用eventBroadcaster.NewRecorder记录"replication-controller"的事件;
- 将调用NewBaseController;
- 在NewBaseController方法中,
- 构建ReplicaSetController对象
- ReplicaSetController对象定义在pkg/controller/replication/replication_set.go中;
- ReplicaSetController包括podControl,它定义了对Pod的操作,是由RealPodControl去调用apiserver完成创建实现;
- ReplicaSetController包括queue,是worker queue,存放待处理的项;
- 调用rsInformer.Informer().AddEventHandler,构建NewReplicaSetInformer,并注册回调函数AddFunc、UpdateFunc、DeleteFunc;
- AddEventHandler如何注册回调函数?在AddEventHandler方法会将eventhandler包装成listener{handler},然后添加到sharedIndexInformer的processor.listeners中;
- 同时,注册rsInformer的Lister;
- 以此方式,调用podInformer.Informer().AddEventHandler,构建NewPodInformer,并注册相应的回调函数AddFunc、UpdateFunc、DeleteFunc;
- 注册podInformer的Lister;
- 注册rsc.syncHandler;syncHandler负责pod与rc的同步,确保Pod副本数与rc规定的相同;
- 构建ReplicaSetController对象
PodInformer
staging/src/k8s.io/client-go/informers/core/v1/pod.go
NewPodInformer方法
- 定义ListFunc和WatchFunc,构建ListerWatcher对象;
- 构建SharedIndexInformer;
NewSharedIndexInformer
staging/src/k8s.io/client-go/tools/cache/shared_informer.go NewSharedIndexInformer方法
运行ReplicationManager
pkg/controller/replicaset/replica_set.go
Run方法
- 调用controller.WaitForCacheSync方法,等待同步完成;
- 启动rsc.worker,rsc.worker会调用rsc.syncHandler,syncHandler负责pod与rc的同步,确保Pod副本数与rc规定的相同;
Informer机制:
sharedInformerFactory.Start
staging/src/k8s.io/client-go/informers/factory.go
Start方法
- kube-controller-manager.Run方法会调用sharedInformerFactory.Start;
- sharedInformerFactory.Start会调用SharedIndexInformer.Run;
sharedIndexInformer.Run
staging/src/k8s.io/client-go/tools/cache/shared_informer.go
sharedIndexInformer.Run方法
- 调用NewDeltaFIFO,创建queue;
- 定义Deltas处理函数s.HandleDeltas;
- 调用New(cfg),构建sharedIndexInformer的controller;
- 调用s.cacheMutationDetector.Run,检查缓存对象是否变化;
- 调用s.processor.run,将调用sharedProcessor.run,会调用Listener.run和Listener.pop,执行处理queue的函数;
- 调用s.controller.Run,构建Reflector,进行对etcd的缓存;
sharedIndexedInformer.controller.Run
staging/src/k8s.io/client-go/tools/cache/controller.go
Run方法
- 调用NewReflector,构建Reflector;
- Reflector对象,包括ListerWatcher、ObjectType、Queue、FullResyncPeriod;
- 调用r.run,将调用reflector.ListAndWatch,执行r.List、r.watch、r.watchHandler,进行对etcd的缓存;
- 调用c.processLoop,reflector向queue里面添加数据,processLoop会不停去消费这里这些数据;
controller.processLoop
staging/src/k8s.io/client-go/tools/cache/controller.go
processLoop方法
- cache.PopProcessFunc(c.config.Process)将前面HandleDeltas方法传递进去;
DeltaFIFO.Pop
staging/src/k8s.io/client-go/tools/cache/delta_fifo.go
Pop方法
- 主要从DeltaFIFO取出object,然后调用HandleDeltas方法进行处理;
处理DeltaFIFO
staging/src/k8s.io/client-go/tools/cache/shared_informer.go HandleDeltas方法
- 调用s.processor.distribute方法,将调用Listener.add,负责将watch的资源传到listener;
Listener.add/pop/run
staging/src/k8s.io/client-go/tools/cache/shared_informer.go sharedProcessor.run方法
sharedProcessor.add方法
sharedProcessor.pop方法
- listenser的add方法负责将notify装进pendingNotifications;
- pop函数取出pendingNotifications的第一个notify,输出到nextCh channel;
- run函数则负责取出notify,然后根据notify的类型(增加、删除、更新)触发相应的处理函数,这些函数在ReplicaSetController注册,分别是:rsc.addPod、rsc.updatePod、rsc.deletePod、rsc.enqueueReplicaSet、rsc.updateRS、rsc.enqueueReplicaSet
rsc.addPod
pkg/controller/replicaset/replica_set.go
addPod方法
- 首先会根据pod返回rc,当pod不属于任何rc时,则返回。找到rc以后,更新rm.expectations.CreationObserved这个rc的期望值,也就是假如一个rc有4个pod,现在检测到创建了一个pod,则会将这个rc的期望值减少,变为3。然后将这个rc放入队列;
- 调用rsc.enqueueReplicaSet,将调用rsc.queue.Add;
rsc.worker
pkg/controller/replicaset/replica_set.go
worker方法
- 调用rsc.syncHandler,这里会调用rsc.syncReplicaSet,syncReplicaSet负责pod与rc的同步,确保Pod副本数与rc规定的相同;