作者
|张慧,网易伏羲私有云质量保障负责人/开源参与者
背景
为什么要反复读源码,是因为大部分时候学习一手的知识效果远比二手要好,学习 n 手的知识效果远比 (n+1) 手的要好。
Version
k8s版本 v1.13 (因为目前长期使用和接触的是这个版本)
'kubelet' 是什么就不说了,它的主要代码集中在 'kubernetes' 项目下的 /pkg/kubelet 位置,总的来说项目结构是相当的清晰。下面是一级目录的简单说明。
- apis/ kubelet 的 api 相关
- cadvisor/ 容器指标采集系统,https://github.com/google/cadvisor
- certificate/ 证书相关
- checkpoint/ checkpoint 功能 (没看前真不知道这功能)
- checkpointmanager/ checkpoint 管理
- client/ 用来访问 kubelet 的 client?
- cloudresource/ 用来和云服务交互的部分
- cm/ cgroups manager (cgroups or container?)
- config/ pod config 相关?
- configmap/ configmap 相关
- container/ CRI 相关
- custommetrics/ 同文件名
- dockershim/ docker interface
- envvars/ 容器里的一些环境变量
- events/ 一堆事件的 constant
- eviction/ pod eviction,这个亲切
- images/ 容器镜像相关,主要是 pull 和 gc
- kubeletconfig/ kubelet config (凭什么不是上面那个 config 改名)
- kuberuntime/ kubelet runtime 相关
- leaky/ emmm... 就是一些要弄死的代码,而且看起来已经都弄死了
- lifecycle/ pod lifecycle 相关的接口
- logs/ container log 相关,主要是 rotation 之类的逻辑
- metrics/ prometheus metrics
- mountpod/ volume plugin 相关?
- network/ 用来配置 pod dns 的
- nodelease/ 又是一个不清楚的功能,看起来和租户相关?
- nodestatus/ 定义了很多节点状态更新用的 setter
- pleg/ pod lifecycle event generator
- pod/ pod manager
- preemption/ 优先级抢占相关
- prober/ pod liveness or readiness probe
- qos/ 算 oom 分的
- remote/ 貌似实现了 cri 定义的一些 service?
- secret/ 挂载 secret 相关
- server/ kubelet 提供的 exec,portforward 等 API的 server
- stats/ CRI stats provider
- status/ pod status manager
- sysctl/ sysctl 相关 (并不知道干什么用)
- token/ service account token 相关
- types/ emmm... 一些 types?
- util/ 一些 utils
- volumemanager/ 数据卷管理
- winstats/ windows 节点相关
内容还是很多的,浏览思路是以 pod 的整个生命周期为线索,抓住主线代码,为此罗列以下几个关键问题:
除此之外按照 feature 的视角来看还有:
pod 的整个生命周期往往要从它被 controller 创建开始聊起。然而本文的主要关注点在 kubelet 相关的代码上,因此更关心 pod 被调度到某个节点,也就是当 pod 的 nodeName 字段不为空后会发生什么。
从什么地方找出 pod 相关的代码呢?我们可以看到 /pkg/kubelet 文件夹下有一个叫做 kubelet.go 的文件,显然这是 kubelet 主体代码的入口。
很快我们发现里面有一个叫做 Kubelet 的结构体和一个叫做 NewMainKubelet 以及一个 (kl *Kubelet) Run(updates <-chan kubetypes.PodUpdate) 的函数。
其中 Kubelet 是 kubelet 的核心结构体,而 NewMainKubelet 是构造函数,Run 则是入口函数。
看看 Run 这个函数做了什么:
kl.syncLoop 接受两个参数,第一个是 <-chan kubetypes.PodUpdate,第二个是 SyncHandler,SyncHandler 定义如下
// SyncHandler is an interface implemented by Kubelet, for testability
type SyncHandler interface {
HandlePodAdditions(pods []*v1.Pod)
HandlePodUpdates(pods []*v1.Pod)
HandlePodRemoves(pods []*v1.Pod)
HandlePodReconcile(pods []*v1.Pod)
HandlePodSyncs(pods []*v1.Pod)
HandlePodCleanups() error
}
在 kl.syncLoop 中调用了 kl.syncLoopIteration,接收了以下几种 chan:
- configCh <-chan kubetypes.PodUpdate
- syncCh <-chan time.Time,定时触发的 resync 操作
- housekeepingCh <-chan time.Time,定时触发的清理操作
- plegCh <-chan *pleg.PodLifecycleEvent
其中 configCh 会触发 HandlePodAdditions,HandlePodUpdates,HandlePodRemoves,HandlePodReconcile 四种操作。而 syncCh 和 plegCh 会触发 HandlePodSyncs 操作,housekeepingCh 会触发 HandlePodCleanups 操作。
到这个时候 pod 的生命周期处理的入口基本上找到了,看到这新的问题来了:
敬请期待 Kubernetes 源码分析之 kubelet(二)