写点什么

Kubelet 源码剖析

  • 2019-11-28
  • 本文字数:3539 字

    阅读完需:约 12 分钟

Kubelet 源码剖析

本篇文章主要介绍了 kubelet 服务启动和创建 pod 的流程,给想要阅读 kubelet 源码的同学一个参考。

前言

“Together we will ensure that Kubernetes is a strong and open container management framework for any application and in any environment – whether in a private, public or hybrid cloud,” Google senior VP Urs Hölzlesaid in the announcement today.


本文 Kubelet 版本: 1.7.4

1 Kubelet 介绍

在 Kubernetes 集群中,在每个 Node 节点上都会启动一个 kubelet 服务进程。该进程用于处理 Master 节点下发到本节点的任务,管理 Pod 及 Pod 中的容器。每个 Kubelet 进程会在 APIServer 上注册节点自身信息,定期向 Master 节点汇报节点资源的使用情况,并通过 cAdvise 监控容器和节点资源。

2 Kubelet 功能

  • Pod 管理

  • 容器的健康检测

  • 容器监控

3 Kubelet 代码结构

➜  kubelet git:(master) tree.├── BUILD├── OWNERS├── app│   ├── BUILD│   ├── OWNERS│   ├── auth.go│   ├── options│   │   ├── BUILD│   │   ├── container_runtime.go│   │   ├── options.go│   │   └── options_test.go│   ├── plugins.go│   ├── server.go│   ├── server_linux.go│   ├── server_test.go│   └── server_unsupported.go└── kubelet.go
2 directories, 15 files
复制代码


// kubelet 服务的入口 (main)


  • cmd/kubelet/kubelet.go


// 主要负责校验参数,创建和 api-server 交互的 client 及对运行 kubelet 权限检测,启动 Kubelet 等等


  • cmd/kubelet/app/server.go


除了入口,kubelet 其它的主要功能实现在 pkg/kubelet 下。这里就不一一介绍了,在下面的时序图中,会标记 pkg 中用到了哪些文件,并主要实现了什么功能。

4 Kubelet 服务启动流程


上面的时序图就是整个 kubelet 的启动流程。


// 主要对 kubelet 的 NewKubeletServer 结构体进行参数校验


  • validateConfig


// 创建与控制节点 api-server 交互的 client (kubeClient, eventClient)


  • CreateAPIServerClientConfig


// 对运行 kubelet 进程的用户的权限验证


  • checkPermission


在 RunKubelet 中主要做 CreateAndInitKubelet 和 startKubelet 两件事:


func CreateAndInitKubelet(...) (k kubelet.KubeletBootstrap, err error) {    k, err = kubelet.NewMainKubelet(....)    if err != nil {        return nil, err    }
k.BirthCry()
k.StartGarbageCollection()
return k, nil}
复制代码


NewMainKubelet 实例化一个 kubelet 对象,并对 kubelet 内部各个 component 进行初始化工作,如:


  • containerGC // 容器的垃圾回收

  • statusManager // pod 状态的管理

  • imageManager // 镜像的管路

  • probeManager // 容器健康检测

  • gpuManager // GPU 的支持

  • PodCache // Pod 缓存的管理

  • secretManager // secret 资源的管理

  • configMapManager // configMap 资源的管理

  • InitNetworkPlugin // 网络插件的初始化


// 对 pod 的管理, e.g., CRUD


  • PodManager


// pod 元数据的来源 (FILE, URL, api-server)


  • makePodSourceConfig


// 磁盘空间的管理


  • diskSpaceManager


// 容器运行时的选择(docker 或 rkt)


  • ContainerRuntime


// 通知 api-server 服务 kubelet 启动


  • BirthCry


// 开启垃圾回收服务


  • StartGarbageCollection


当之前所有的预处理工作处理完成之后,准备启动我们的 kubelet 服务 startKubelet:


func startKubelet() {    // start the kubelet    go wait.Until(func() { k.Run(podCfg.Updates()) }, 0, wait.NeverStop)       // start the kubelet server    if kubeCfg.ReadOnlyPort > 0 {        go wait.Until(func() {            k.ListenAndServeReadOnly(net.ParseIP(kubeCfg.Address), uint(kubeCfg.ReadOnlyPort))        }, 0, wait.NeverStop)    }}
复制代码


startKubelet 方法中的第一个 goroutine 负责启动 kubelet,在 Run 中主要做的事儿就是启动 diskSpaceManager, volumeManager, statusManager, probeManager 及注册节点等相关服务组件,并最后执行 syncLoop 也就是创建 pod 的入口。


而后面则创建一个 kubelet http server,通过该 server 可以获取 pod 及 node 的相关信息。

5 Pod 的创建流程


syncLoop 是 kubelet 的主循环方法,它从不同的管道 (FILE, URL, api-server) 监听到 pod 的变化,并把它们聚合起来。当有新的 pod 变化发生时,它会调用对应的函数,保证 Pod 处于期望的状态。


func (kl *Kubelet) syncLoop(updates <-chan kubetypes.PodUpdate, handler SyncHandler) {    for {        kl.syncLoopIteration(updates, handler...)     }}
复制代码


kl.syncLoopIteration 这个方法会对多个管道进行遍历,如果有 pod 动作,则会调用相应的 Handler。


下面是对应的 Interface.


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}
复制代码


我们以创建 Pod 为例,它会调用对应的 HandlePodAdditionsHandler 进行处理。HandlePodAdditions 做的任务就是通过 canAdmitPod 方法校验 Pod 能否在该计算节点创建 (e.g., 磁盘空间)。之后把创建 Pod 的事交给 dispatchWork。dispatchWork 主要工作就是把接收到的参数封装成 UpdatePodOptions,调用 UpdatePod 方法.


syncPod 是创建 Pod 的核心逻辑。其中有几个主要的方法:


// 根据最新拿到的 pod 配置与当前运行的容器配置进行对比,计算其中的变化 (一个具体的 hash 值),得到需要重启的容器的信息


  • computePodContainerChanges


// 创建一个 PodSandBox


  • createPodSandBox


func (m *kubeGenericRuntimeManager) createPodSandbox(pod *v1.Pod, attempt uint32) (string, string, error) {    podSandboxConfig, err := m.generatePodSandboxConfig(pod, attempt)    ......    podSandBoxID, err := m.runtimeService.RunPodSandbox(podSandboxConfig)    ......    return podSandBoxID, "", nil}
复制代码


// 获取 PodSandbox 的配置 (e.g., metadata, clusterDNS, 容器的端口映射等)


  • generatePodSandboxConfig


// 创建并开启一个 Pod 级别的 sandbox


  • RunPodSandbox


在 RunPodSandbox 中主要调用如下几个方法:


// 检测用户是否设置了自己的 pause 镜像,如果没有设置则使用默认的镜像 gcr.io/google_containers/pause-amd64:3.0


  • ensureSandboxImageExists


// 生成创建 pause 容器的配置信息


  • makeSandboxDockerConfig

  • CreateContainer // 创建容器

  • StartContainer // 启动容器


// 设置容器的网络 (kubelet 加载 cni 插件对容器的网络进行设置等)


  • network.SetUpPod


上面的这些操作就把我们 Pod 中的第一个 pause 容器创建并启动了。之后要做的就是把该 Pod 中的其它业务容器逐一的启动。但是在启动真正的业务容器之前,首先会检查用户是否设置了 init_container。如果设置了,则会按 init_container 设置的顺序依次的执行 init_container (注意: 当其中的 init_container 执行失败了,则 Pod 会异常,并且业务容器不会被创建)。当 init_container 执行完成之后,我们真正的业务容器才会被逐一的启动。


业务容器启动的逻辑和 Pod 的初始化 pause 容器的启动的流程基本一致。下面的代码是循环的启动业务容器:


for idx := range podContainerChanges.ContainersToStart {     container := &pod.Spec.Containers[idx]     //.....      if msg, err := m.  startContainer(podSandboxID, podSandboxConfig, container, pod, podStatus, pullSecrets, podI; err != nil {          //.....          continue     }}
复制代码


在 startContainer 方法中主要调用如下方法:


// 检查业务镜像是否存在,不存在则到 Docker/Private Registry 拉取镜像


  • EnsureImageExists


// 生成业务容器的配置信息


  • generateContainerConfig


// 通过 client.CreateContainer 调用 docker engine-api 创建业务容器


  • CreateContainer

  • StartContainer //启动业务容器


// 这个方法的主要作用就是在业务容器起来的时候,首先会执行一个 container hook(PostStart 和 PreStop),做一些预处理工作。只有 container kook 执行成功才会运行具体的业务服务,否则容器异常。


  • runner.Run


这样 Pod 大体的启动流程就描述完了。

6 总结

kubelet 的主干道已经大体介绍完了,kubelet 还有许多中间服务,如 volumeManager, diskSpaceManager, secretManager, configMapManager 以及节点注册等等,接下来有时间会把各个功能组件的基本实现原理介绍给大家。


本文转载自公众号 360 云计算(ID:hulktalk)。


原文链接:


https://mp.weixin.qq.com/s/7V1byf0Q_2OLWG0zh7LDgw


2019-11-28 15:081942

评论

发布
暂无评论
发现更多内容

用Mac做视频剪辑就用fcpx剪辑,Final Cut Pro中文下载

Rose

Final Cut Pro中文版 Final Cut Pro破解版 fcpx 视频剪辑Mac版 fcpx剪辑

The Foundry Nuke 15 for Mac(电影特效合成软件)

展初云

Mac nuke 特效合成软件

关于圆通物流在AppLink上的操作

RestCloud

APPlink

OmniGraffle Pro 7 for mac(绘图软件)

展初云

Mac OmniGraffle Pro 专业绘图软件

CPU 程序性能优化

MegEngineBot

性能优化 cpu 硬件 编译器

InDesign 2024 for mac(页面设计和版面应用程序)

展初云

adobe Mac软件 InDesign 2024 下载 InDesign

适用于M1 /M2 Mac的office365办公软件 Microsoft 365破解版下载

Rose

Microsoft 365 office许可证 office 365

Mac系统下Datagrip打不开、点击没反应?

秃头小帅oi

「一体化信息建设」,江苏人社如何完成数据安全管控(成果篇)

BinTools图尔兹

运维 数据安全 数据库管理 数据库操作

登上CHINA DAILY!用友向全球展现中国数智力量

用友BIP

企业数智化

业内首发!用友BIP全球司库助力大型企业实现虚假贸易“零容忍”!

用友BIP

全球司库 虚假贸易

浅析建筑行业财务管理数智化转型

用友BIP

企业数智化

什么是软件定制开发?|app网站小程序定制

Geek_16d138

网站建设 app定制开发 软件定制开发

异构集成:财务共享如何成为数据聚合、分发的控制枢纽

用友BIP

财务共享

潜水员戴夫Dave The Diver 主线游戏攻略 潜水员戴夫 Mac游戏中文版下载

Rose

Dave The Diver 潜水员戴夫游戏攻略 Mac游戏推荐 潜水员戴夫中文版下载

专业ai无损放大工具-Topaz Gigapixel AI汉化一键激活版

Rose

无损放大 Topaz Gigapixel AI中文 Topaz Gigapixel AI下载 Topaz Gigapixel AI破解

oneAPI & OpenVINO™ 联合开发者大会开启:英特尔持续开源创新,助力 AI 开发落地

E科讯

Amazon EC2 新手初探:创建第一个 EC2 实例

王强

Amazon EC2 亚马逊云服务

物理机和云服务器到底哪个好

Geek_f19a80

服务器

【Spring Cloud 】基于微服务架构的智慧工地云平台源码带APP

源码星辰

智慧工地 智慧工地云平台

编程和数学计算软件MATLAB R2023b for Mac v23.2.0

展初云

matlab Mac软件 MATLAB R2023b

OmniGraffle Pro 思维导图工具 密钥激活 附 安装教程

加油,小妞!

mac思维导图 OmniGraffle Pro下载

Luminar Neo 创意图像编辑工具 支持M1

加油,小妞!

图像处理 Luminar Neo下载

7天!早鸟票免费倒计时!2023开放原子开发者大会等你来!

开放原子开源基金会

Java 开源 程序员 开发者大会 C++

喜讯!云起无垠入选《2023年中国AIGC创新企业榜》

云起无垠

轻松一刻|Walrus CLI与CI/CD工具集成,轻松部署2048游戏

SEAL安全

游戏 CI/CD Walrus 企业号11月PK榜

Kubelet 源码剖析_文化 & 方法_王希刚_InfoQ精选文章