kubelet源码分析(一)——kubelet启动流程及pod状态变化感知和消费流程

目录

1、kubelet启动流程

1.1 cmd/kubelet/app/server.go  Run方法

1.2 cmd/kubelet/app/server.go  run方法

1.3 cmd/kubelet/app/server.go  RunKubelet方法

1.4 cmd/kubelet/app/server.go  CreateAndInitKubelet方法

1.5 cmd/kubelet/app/server.go  startKubelet方法

2、pod状态变化感知流程

2.1 pkg/kubelet/kubelet.go makePodSourceConfig函数

2.2 pkg/kubelet/config/apiserver.go NewSourceApiServer函数

2.3 pkg/kubelet/config/config.go Merge函数

3、pod消费流程


1、kubelet启动流程

函数调用图:

1.1 cmd/kubelet/app/server.go  Run方法

initForOS通过对操作系统的判断,如果是windows系统需要做一些预先的特殊处理;

run方法即通过传入的kubeDeps参数开始执行启动操作。

1.2 cmd/kubelet/app/server.go  run方法

进入run方法,开始主要执行对参数的再一次验证,以及新的结构体的初始化。后续开始构建一些重要的客户端,包括eventClient主要处理事件的上报,与apiserver打交道;heartbeatClient主要处理心跳操作,与之后的PLEG相关;csiClient主要与CSI接口相关。配置完成之后,最终进入RunKubelet方法。

1.3 cmd/kubelet/app/server.go  RunKubelet方法

RunKubelet方法最重要的方法有两个:CreateAndInitKubeletstartKubelet,可以理解为CreateAndInitKubelet为参数的配置,startKubelet为最终的启动。

1.4 cmd/kubelet/app/server.go  CreateAndInitKubelet方法

CreateAndInitKubelet方法通过调用NewMainKubelet返回Kubelet结构体。在NewMainKubelet中,主要的配置有:
1、PodConfig。通过makePodSourceConfig可以发现kubelet获取Pod的来源有以下途径:静态Pod、静态Pod的URL地址以及kube-apiserver;
2、容器与镜像的GC参数。
3、驱逐Pod策略。
最终通过参数填充Kubelet结构体,完成kubelet结构体参数的最终配置。

1.5 cmd/kubelet/app/server.go  startKubelet方法

startKubelet方法内部调用了最终的Run方法

可以看到,在该方法内,完成的就是最终的kubelet的任务,通过多个goroutine完成。包括以下系列:
1、volumeManager,volume相关管理;
2、syncNodeStatus,定时同步Node状态;
3、updateRuntimeUp,定时更新Runtime状态;
4、syncNetworkUtil,定时同步网络状态;
5、podKiller,定时清理死亡的pod;
6、statusManager,pod状态管理;
7、probeManager,pod探针管理;
8、启动PLEG, 即PodLifecycleEventGenerator,用来记录Pod生命周期中对应的各种事件。
9、syncLoop,最重要的主进程,不停监听外部数据的变化执行pod的相应操作。
至此,kubelet启动过程完成。启动主要完成的任务就是参数的配置和多个任务的启动,通过构造一个循环进程不停监听外部事件的变化,执行对应的pod处理工作,这也就是kubelet所需要负责的任务。

2、pod状态变化感知流程

函数调用图:

2.1 pkg/kubelet/kubelet.go makePodSourceConfig函数

makePodSourceConfig中多处调用了cfg.Channel,可以发现传入了三类source(file、http、api),也就是表示pod的变更来自于这三类source。

cfg.Channel(kubetypes.FileSource)
cfg.Channel(kubetypes.HTTPSource)
cfg.Channel(kubetypes.ApiserverSource)

只看apiserver这类源相关的代码就好了,道理都是一样的。

调用cfg.channel生成updatechannel,将updatechannel作为参数传给NewSourceApiServer函数,NewSourceApiServer内部将listwatch发现的pods变化写入updatechannel队列中

2.2 pkg/kubelet/config/apiserver.go NewSourceApiServer函数

// NewSourceApiserver creates a config source that watches and pulls from the apiserver.
func NewSourceApiserver(c clientset.Interface, nodeName types.NodeName, updates chan<- interface{}) {
	lw := cache.NewListWatchFromClient(c.CoreV1().RESTClient(), "pods", metav1.NamespaceAll, fields.OneTermEqualSelector(api.PodHostField, string(nodeName)))
	newSourceApiserverFromLW(lw, updates)
}

可以发现实际上kubelet创建了一个listwatch去watch所有namespace的、绑定到本node上的pod。将listwatch发现的pods变化写入updatechannel队列中

2.3 pkg/kubelet/config/config.go Merge函数

看注释可以了解到:

  • pod的变化有多个来源
  • 最终会将变化push到update channel中

稍微浏览下代码即可发现:merge()将入参的change解析分类,然后又push到podStorage的updates中。

3、pod消费流程


makePodSourceConfig的返回类型PodConfig包含updates channel,

赋值给了kubeDeps.PodConfig,我们只要找到谁消费了kubeDeps.PodConfig就能知道pod的变化最终在哪里消费了。

kubeDeps.PodConfig, err = makePodSourceConfig(kubeCfg, kubeDeps, nodeName, bootstrapCheckpointPath)

根据kubeDeps.PodConfig的调用关系(使用IDE查看谁调用了PodConfig),发现kubeDeps.PodConfig是在RunKubelet中被传给了startKubelet,然后一路被传到pkg/kubelet/kubelet.go路径下的syncLoop了。

调用链如下图

syncLoop是处理pod变化的主loop,一旦观察变换就会同步期望状态和运行状态。

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值