1.核心流程

kubelet最核心的功能就是根据master的指示,在节点上创建并管理pod。目前对于kubelet而言,有三种途径来获取所管理的pod清单:

  • 文件 - 通过启动参数–config指定配置目录,定期检查变更。
  • HTTP Endpoint - 通过--manifest-url参数指定,定期检查更新。
  • API Server - 通过API Server监听etcd目录,实时同步pod清单。

通过API Server监听Pod清单,并在节点上维护对应的Pod实例,这是整个kubelet进程的核心主流程。下图近似描述了这个过程:

注意:在实际研究过程中,发现go语言实现的系统在调用逻辑上和Java/C++这些语言实现的系统有很大差异。go语言除了对象之间相互方法调用之外,还存在大量的goroutine间通过channel发送消息调用的情况。因此,从逻辑上来讲,go语言的调用事实上是并发的,类似于网状的。而不是传统的同步调用,线性的关系。因此,感觉很难用UML图来表示对象间的调用顺序。上图仅仅是把关键的对象及方法入口表示出来而已,而且有很多省略。当中如果有错误或更好的表述方式,也请告知作者。

2.核心结构及调用关系

2.1 Kubelet

/pkg/kubelet/kubelet.go文件中的Kubelet结构体是整个kubelet进程的核心数据结构,它持有了所有关联的实体对象。Kubelet有两个主要的入口方法:

  • NewMainKubelet - 创建并初始化一个Kubelet结构(将所有关联实例都初始化好)。
  • Run - 启动所有辅助的goroutines以及上文中提到的主流程。

NewMainKubelet方法中,调用了一个makePodSourceConfig的私有方法,该方法会返回一个PodConfig对象指针。其中有一个field叫做updates chan kubetypes.PodUpdate,用于传递pod更新消息。

updates通道一边连接着从三种来源获取pod更新信息的goroutines。一边被kubelet的主流程消费,即获取pod更新信息,并同步操作Pod实例。

kubelet的主流程方法入口是Kubelet.syncLoopIteration,用于不断分发updates通道中的消息。

2.2 PodWorkers

/pkg/kubelet/pod_workers.go文件中的podWorkers结构,是一个协程池。podWorkders会为每个pod单独起一个goroutine,专门用于消费该pod相关的update信息,实施pod的操作。

podWorkers有两个关键方法:

  • UpdatePod - update入口,启动并管理每个pod的update协程。
  • managePodLoop - worker的实际逻辑,最终调用Kubelet.syncPod方法。

在managePodLoop每次Pod同步完成之后,会调用wrapUp方法。该方法用于周期性同步pod,即使没有收到API Server推送的变更。

wrapUp方法会在podWorkers的workQueue中push下次发生同步的时间戳。同时kubelet.syncLoopIteration方法会周期性从podWorkers.workQueue中拉取当前时刻需要同步的pod列表,并触发SyncPod操作。

2.3 kubeGenericRuntimeManager

1、Kubelet关键模块 文档中有描述,该结构体实现了kubecontainer.Runtime接口,封装了Container & Image相关的操作。

主流程中调用的是该结构体的SyncPod方法,它会计算出当前该Pod上所需要执行的操作,通过CRI接口执行。

2.4 dockerService & kubeDockerClient

dockershim中对CRI接口的实现,kubeGenericRuntimeManagerdockerService之间实际上通过gRPC来通讯。

kubeDockerClient是对libdocker.Interface接口的封装,通过HTTP(s)和docker daemon通讯。

转载于:https://my.oschina.net/zhuhui/blog/3081719

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐