查看原文
其他

Kubernetes 源码分析之 kubelet(一)

CNCF 2022-11-11

The following article is from 薛定谔的喵0314 Author 张慧

作者

|张慧,网易伏羲私有云质量保障负责人/开源参与者



背景为什么要反复读源码,是因为大部分时候学习一手的知识效果远比二手要好,学习 n 手的知识效果远比 (n+1) 手的要好。
Version
k8s版本 v1.13 (因为目前长期使用和接触的是这个版本)

Overview

'kubelet' 是什么就不说了,它的主要代码集中在 'kubernetes' 项目下 /pkg/kubelet 位置,总的来说项目结构是相当的清晰。下面是一级目录的简单说明。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
- 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 的整个生命周期为线索,抓住主线代码,为此罗列以下几个关键问题:
  • 如何创建 pod
  • 如何 sync pod 状态
  • 如何调用 API 创建 container
  • pod 的 configmap 和 secret 如何管理
  • pod 的 volume 如何管理
  • pod 的 network 如何管理
  • 如何删除 pod
除此之外按照 feature 的视角来看还有:
  • metrics 采集
  • remote command 相关的实现
  • eviction 功能的实现
  • CRI 相关的实现
  • 其他

Pod Lifecycle

pod 的整个生命周期往往要从它被 controller 创建开始聊起。然而本文的主要关注点在 kubelet 相关的代码上,因此更关心 pod 被调度到某个节点,也就是当 pod 的 nodeName 字段不为空后会发生什么。


从 kubelet.go 开始聊起

从什么地方找出 pod 相关的代码呢?我们可以看到 /pkg/kubelet 文件夹下有一个叫做 kubelet.go 的文件,显然这是 kubelet 主体代码的入口。很快我们发现里面有一个叫做 Kubelet 的结构体和一个叫做 NewMainKubelet 以及一个 (kl *Kubelet) Run(updates <-chan kubetypes.PodUpdate) 的函数。其中 Kubelet 是 kubelet 的核心结构体,而 NewMainKubelet 是构造函数,Run 则是入口函数。看看 Run 这个函数做了什么:
  • 初始化了 kl.logServer
  • 检查了 kl.kubeClient,之所以这里可能为空是因为 apiserver 可以是 kubelet 拉起来的
  • 运行 kl.cloudResourceManager
  • 运行 kl.initializeModules
    • 注册 prometheus metrics
    • 初始化 kubelet 所需的文件夹
    • 初始化 container 日志文件夹
    • 运行管理镜像 GC 的模块 kl.imageManager
    • 运行证书管理模块 kl.serverCertificateManager
    • 运行 OOM 监控模块 kl.oomWatcher
    • 运行资源分析模块 kl.resourceAnalyzer
  • 运行 volume 管理组件 kl.volumeManager
  • 如果 apiserver 已经运行了
    • 运行 goroutine 定时同步 node 状态
    • 快速进行一次状态同步
    • 运行 kl.nodeLeaseController
  • 运行 goroutine 同步 container runtime uptime
  • 运行 goroutine 同步 iptables 规则 (暂未明白这个同步的意义)
  • 运行 kl.podKiller
  • 运行 pod 状态管理模块 kl.statusManager
  • 运行 pod 探针模块 kl.probeManager
  • 运行 pleg (pod lifecycle event generator) 模块 kl.pleg
  • 运行主循环 kl.syncLoop
kl.syncLoop 接受两个参数,第一个是 <-chan kubetypes.PodUpdate,第二个是 SyncHandler,SyncHandler 定义如下
1
2
3
4
5
6
7
8
9
// 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:

1
2
3
4
- 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 的生命周期处理的入口基本上找到了,看到这新的问题来了:

  • <-chan kubetypes.PodUpdate 到底是怎么触发的,对应的四个操作都做了什么

  • HandlePodSyncs 和上述四个操作什么关系(凭什么你叫 sync)

  • HandlePodCleanups 和 HandlePodRemoves 的区别

  • 为什么需要定时触发 syncCh

  • 为什么需要 housekeeping

  • pleg 模块到底做了什么


敬请期待 Kubernetes 源码分析之 kubelet(二)


文章转载自薛定谔的喵0314点击这里阅读原文了解更多




来贡献几分钟提交:2020年CNCF中国云原生问卷

问卷链接(https://www.wjx.cn/jq/97146486.aspx




扫描二维码联系我们!




CNCF (Cloud Native Computing Foundation)成立于2015年12月,隶属于Linux  Foundation,是非营利性组织。 

CNCF云原生计算基金会)致力于培育和维护一个厂商中立的开源生态系统,来推广云原生技术。我们通过将最前沿的模式民主化,让这些创新为大众所用。请长按以下二维码进行关注。

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存