kubelet分析(一)-config-v1.5.2
kubelet在Kubernetes中负责具体与物理设备打交道,负责pod所对应的相关资源的管理,如container, volume, network等。本次分析将介绍kubelet的config,看kubelet是如何把pod的信息从apiserver,或file,或http同步到kublet中的。其中,apiserver渠道代表从ETCD中获取pod的变化;file渠道代表从文件获取源的变化,如static pod;http渠道我还没用过。
Mux
关于Mux,在”kube-proxy分析(一)-config-v1.5.2”中已介绍过。现直接拷贝过来。
Mux可以创建多条channel,并与相关config的storage配合把这些channel中的数据进行合并。Mux定义在/pkg/util/config/config.go中:
|
|
其中,Merger负责把数据进行合并;sources中记录了名称及对应的channel。
可以使用NewMux()函数生成Mux:
|
|
在创建Mux时需要指定Merger,而sources中的channel目前为空。那么,如何建立source channel,又如何把source channel中的内容交Merger处理呢?来看Mux的Channel()方法:
|
|
Channel()方法会创建一个channel,并启动一个routine调用listen(),最后把channel返回。listen()就是监听刚创建的channel,然后通过merger.Merge()处理数据。所以,通过调用Mux的Channel()方法,我们可以获取到一个channel,我们只要往这个channel中写数据即可,Mux自动会把数据交给merger处理。
再来看下什么是Merger,Merger概念定义在/pkg/util/config/config.go中:
|
|
可以看出,只要实现了Merge()方法的结构体都可以称为Merger,很简洁。
podStorage
podStorage是对多个渠道过来的数据的一个汇总的存储场所,即可以理解为是一个Merger,定义在/pkg/kubelet/config/config.go中:
|
|
可以看到,podStorage有一个updates,作为所有的整理好的数据集中地;还有pods字段用来存储分类好的pods。所以podStorage的主要工作流程为:消费Mux返回的channel中的数据,调用Merge()对数据进行处理,最后把整理好的数据发送到updates中。
先来看podStorage的Merge():
|
|
一般来说,podStorage的mode为PodConfigNotificationIncremental。可以看出,Merge()调用merge()把指定source的数据进行整理,把数据分类到adds, updates, deletes, removes, reconciles等channel中。
merge()定义如下:
|
|
merge()消费的渠道中的数据的update.Op一般为kubetypes.SET,由updatePodsFunc完成分类。
根据merge()和checkAndUpdatePod(),我们可以小结下各channel的逻辑:
- adds:表示kubelet需要新增的pods,其内的数据动作为kubetypes.ADD;
- updates:表示kubelet需要更新的pods,其内的数据动作为kubetypes.UPDATE;
- deletes:表示kubelet需要”删除”的pods,这些pods的 DeletionTimestamp被标记,其内的数据动作为kubetypes.DELETE;
- removes:表示kubelet需要删除的pods,这些pods在kubelet侧有,但对应的渠道侧没有,其内的数据动作为kubetypes.REMOVE;
- reconciles: 表示kubelet需要更新status的pods,其内的数据动作为kubetypes.RECONCILE。
这里要注意下,每次update中都存储有全量的pods。updatePodsFunc会对全量的pods进行归类,然后在类别上加入OP标签以标识这些pods需要的操作。
PodConfig
PodConfig是负责管理整个pod同步,定义在/pkg/kubelet/config/config.go:
|
|
PodConfig主要有如下字段:
- pods: 是一个podStorage,用来汇总数据;
- mux: 为Mux;
- updates:即pods podStorage中的updates字段,所有处理过的事件都会汇总到这供外部的消费者消费;
- sources:记录config中的渠道名称。
PodConfig实现有Channel()方法:
|
|
Channel()方法会调用mux的Channel(),启动整个merge流程。
那么,外部如何获取存储有处理好的汇总数据集中地updates channel呢?所以,PodConfig还实现了Updates():
|
|
Updates()很简单,直接返回updates channel。
apiserver渠道
以apiserver渠道渠道为例来看下渠道,即source的实现,定义在/pkg/kubelet/config/apiserver.go中:
|
|
NewSourceApiserver()会通过listwatch机制把变化发送到参数中的channel,即mux生成的channel,也是merger需要处理数据所在的channel。
调用
/pkg/kubelet/kubelet.go的makePodSourceConfig()中会对pod source config进行设置:
|
|
可见,makePodSourceConfig()会生成一个新的config,然后调用NewSourceFile(), NewSourceURL(), NewSourceApiserver()生成三个渠道。三个渠道的数据都会放入属于自己的channel中,而该channel是通过PodConfig的Channel()生成的。现在整个PodConfig就能汇总加工3个渠道的数据了。外部只要调用PocConfig的Updates()即可获取这些处理好的数据所有的channel,相当方便。