k8s源码分析 pdf_k8s源码阅读 replication controller的Informer机制

本文详细解析了k8s replication controller的工作原理,特别是Informer机制。replication controller通过watch replicationsets和pods确保副本数正确。初始化过程中涉及NewReplicationManager、NewBaseController,使用Informer监听并同步资源。Informer机制包括SharedIndexInformer、Reflector、DeltaFIFO等组件,协同确保数据同步和事件处理。syncHandler负责维护Pod与ReplicationController的同步。
摘要由CSDN通过智能技术生成

094d13b2643c7f6b0d9769da349004af.png

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初始化过程:

400671cd56a951bd462f58e37a0f30b7.png

startReplicationController

cmd/kube-controller-manager/app/core.go 
startReplicationController方法
  1. 协程调用replicationcontroller.NewReplicationManager,构建ReplicationManager;
    1. 调用ctx.InformerFactory.Core().V1().Pods(),这里调用sharedInformerFactory(client-go/informers/factory.go)的Core().V1().Pods()方法,将会构建PodInformer对象;
    2. 以此方式,创建rcInformer;
  2. 运行ReplicationManager;

67e6bb4d297ae375fa775e2642bcdc46.png

NewReplicationManager

pkg/controller/replication/replication_controller.go
NewReplicationManager方法
  1. 在NewReplicationManager中,
    1. 首先,调用record.NewBroadcaster,创建eventBroadcaster对象,调用eventBroadcaster.StartLogging,接收EventBroadcaster发送的event,输出到logging中;调用 eventBroadcaster.StartRecordingToSink,event输出到EventSink,并调用eventBroadcaster.NewRecorder记录"replication-controller"的事件;
    2. 将调用NewBaseController;
  2. 在NewBaseController方法中,
    1. 构建ReplicaSetController对象
      1. ReplicaSetController对象定义在pkg/controller/replication/replication_set.go中;
      2. ReplicaSetController包括podControl,它定义了对Pod的操作,是由RealPodControl去调用apiserver完成创建实现;
      3. ReplicaSetController包括queue,是worker queue,存放待处理的项;
    2. 调用rsInformer.Informer().AddEventHandler,构建NewReplicaSetInformer,并注册回调函数AddFunc、UpdateFunc、DeleteFunc
    3. AddEventHandler如何注册回调函数?在AddEventHandler方法会将eventhandler包装成listener{handler},然后添加到sharedIndexInformer的processor.listeners中;
    4. 同时,注册rsInformer的Lister;
    5. 以此方式,调用podInformer.Informer().AddEventHandler,构建NewPodInformer,并注册相应的回调函数AddFunc、UpdateFunc、DeleteFunc;
    6. 注册podInformer的Lister;
    7. 注册rsc.syncHandler;syncHandler负责pod与rc的同步,确保Pod副本数与rc规定的相同;

dfb6a71a5320c12d242f74d2523ad93d.png

PodInformer

staging/src/k8s.io/client-go/informers/core/v1/pod.go 
NewPodInformer方法
  1. 定义ListFunc和WatchFunc,构建ListerWatcher对象;
  2. 构建SharedIndexInformer;

f2d6dc63b5679b55f7df9124f032f21e.png

NewSharedIndexInformer

staging/src/k8s.io/client-go/tools/cache/shared_informer.go NewSharedIndexInformer方法

b2a320304b4d91c0d92ba1ef4361aeb4.png

运行ReplicationManager

pkg/controller/replicaset/replica_set.go 
Run方法
  1. 调用controller.WaitForCacheSync方法,等待同步完成;
  2. 启动rsc.worker,rsc.worker会调用rsc.syncHandler,syncHandler负责pod与rc的同步,确保Pod副本数与rc规定的相同;

d908d57a4ccf64040272a36fc010cec3.png

Informer机制:

21ea0d961c429de09d0d6a691c35ec5f.png

sharedInformerFactory.Start

staging/src/k8s.io/client-go/informers/factory.go 
Start方法
  1. kube-controller-manager.Run方法会调用sharedInformerFactory.Start;
  2. sharedInformerFactory.Start会调用SharedIndexInformer.Run;

3471fe4285bdca0b3b93802f902b9c88.png

sharedIndexInformer.Run

staging/src/k8s.io/client-go/tools/cache/shared_informer.go 
sharedIndexInformer.Run方法
  1. 调用NewDeltaFIFO,创建queue;
  2. 定义Deltas处理函数s.HandleDeltas;
  3. 调用New(cfg),构建sharedIndexInformer的controller;
  4. 调用s.cacheMutationDetector.Run,检查缓存对象是否变化;
  5. 调用s.processor.run,将调用sharedProcessor.run,会调用Listener.run和Listener.pop,执行处理queue的函数;
  6. 调用s.controller.Run,构建Reflector,进行对etcd的缓存;

64685f228be2c4e51a148333e1172c89.png

sharedIndexedInformer.controller.Run

staging/src/k8s.io/client-go/tools/cache/controller.go 
Run方法
  1. 调用NewReflector,构建Reflector;
  2. Reflector对象,包括ListerWatcher、ObjectType、Queue、FullResyncPeriod;
  3. 调用r.run,将调用reflector.ListAndWatch,执行r.List、r.watch、r.watchHandler,进行对etcd的缓存;
  4. 调用c.processLoop,reflector向queue里面添加数据,processLoop会不停去消费这里这些数据;

98dcf92287c2cb5ba5cc59f428c5dbd2.png

controller.processLoop

staging/src/k8s.io/client-go/tools/cache/controller.go 
processLoop方法
  1. cache.PopProcessFunc(c.config.Process)将前面HandleDeltas方法传递进去;

1a3f1c1afbd7d54da6bd46030b08da63.png

DeltaFIFO.Pop

staging/src/k8s.io/client-go/tools/cache/delta_fifo.go 
Pop方法
  1. 主要从DeltaFIFO取出object,然后调用HandleDeltas方法进行处理;

a8fd877c508af9d084a18b97c094cab8.png

处理DeltaFIFO

staging/src/k8s.io/client-go/tools/cache/shared_informer.go HandleDeltas方法
  1. 调用s.processor.distribute方法,将调用Listener.add,负责将watch的资源传到listener;

8e23ab510d9eb1e6393ebf320fb6d444.png

Listener.add/pop/run

staging/src/k8s.io/client-go/tools/cache/shared_informer.go sharedProcessor.run方法
sharedProcessor.add方法
sharedProcessor.pop方法
  1. listenser的add方法负责将notify装进pendingNotifications;
  2. pop函数取出pendingNotifications的第一个notify,输出到nextCh channel;
  3. run函数则负责取出notify,然后根据notify的类型(增加、删除、更新)触发相应的处理函数,这些函数在ReplicaSetController注册,分别是:rsc.addPod、rsc.updatePod、rsc.deletePod、rsc.enqueueReplicaSet、rsc.updateRS、rsc.enqueueReplicaSet

2ecf9ad31ec6075ad4f6f7e4ea1d4c5c.png

rsc.addPod

pkg/controller/replicaset/replica_set.go 
addPod方法
  1. 首先会根据pod返回rc,当pod不属于任何rc时,则返回。找到rc以后,更新rm.expectations.CreationObserved这个rc的期望值,也就是假如一个rc有4个pod,现在检测到创建了一个pod,则会将这个rc的期望值减少,变为3。然后将这个rc放入队列;
  2. 调用rsc.enqueueReplicaSet,将调用rsc.queue.Add;

498754d5c12e9115848003954e11e063.png

rsc.worker

pkg/controller/replicaset/replica_set.go 
worker方法
  1. 调用rsc.syncHandler,这里会调用rsc.syncReplicaSet,syncReplicaSet负责pod与rc的同步,确保Pod副本数与rc规定的相同;

dff1b9c3a4f0814aa57223ff24c93f2d.png
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值