关于云计算:源码解析一文读懂-Kubelet

43次阅读

共计 4706 个字符,预计需要花费 12 分钟才能阅读完成。

本文次要介绍 kubelet 性能、外围组件,以及启动流程的源码剖析,总结了 kubelet 的工作原理。

kubelet 简介

从官网的架构图中很容易就能找到 kubelet

执行 kubelet -h 看到 kubelet 的性能介绍:

  • kubelet 是每个 Node 节点上都运行的次要“节点代理”。应用如下的一个向 apiserver 注册 Node 节点:主机的 hostname;笼罩 host 的参数;或者云提供商指定的逻辑。
  • kubelet 基于 PodSpec 工作。PodSpec 是用 YAML 或者 JSON 对象来形容 Pod。Kubelet 承受通过各种机制(次要是 apiserver)提供的一组 PodSpec,并确保外面形容的容器良好运行。

除了由 apiserver 提供 PodSpec,还能够通过以下形式提供:

  • 文件
  • HTTP 端点
  • HTTP 服务器

kubelet 性能演绎一下就是上报 Node 节点信息,和治理(创立、销毁)Pod。性能看似简略,理论不然。每一个点拿进去都须要很大的篇幅来讲,比方 Node 节点的计算资源,除了传统的 CPU、内存、硬盘,还提供扩大来反对相似 GPU 等资源;Pod 不仅仅有容器,还有相干的网络、安全策略等。

kubelet 架构

重要组件

kubelet 的架构由 N 多的组件组成,上面简略介绍下比拟重要的几个:

PLEG

Pod Lifecycle Event Generator,字面意思 Pod 生命周期事件(ContainerStartedContainerDiedContainerRemovedContainerChanged)生成器。

其保护着 Pod 缓存;定期通过 ContainerRuntime 获取 Pod 的信息,与缓存中的信息比拟,生成如上的事件;将事件写入其保护的通道(channel)中。

PodWorkers

处理事件中 Pod 的同步。外围办法 managePodLoop() 间接调用 kubelet.syncPod() 实现 Pod 的同步:

  • 如果 Pod 正在被创立,记录其提早
  • 生成 Pod 的 API Status,即 v1.PodStatus:从运行时的 status 转换成 api status
  • 记录 Pod 从 pendingrunning 的耗时
  • StatusManager 中更新 pod 的状态
  • 杀掉不应该运行的 Pod
  • 如果网络插件未就绪,只启动应用了主机网络(host network)的 Pod
  • 如果 static pod 不存在,为其创立镜像(Mirror)Pod
  • 为 Pod 创立文件系统目录:Pod 目录、卷目录、插件目录
  • 应用 VolumeManager 为 Pod 挂载卷
  • 获取 image pull secrets
  • 调用容器运行时(container runtime)的 #SyncPod() 办法

PodManager

存储 Pod 的冀望状态,kubelet 服务的不同渠道的 Pod

StatsProvider

提供节点和容器的统计信息,有 cAdvisorCRI 两种实现。

ContainerRuntime

顾名思义,容器运行时。与遵循 CRI 标准的高级容器运行时进行交互。

Deps.PodConfig

PodConfig 是一个配置多路复用器,它将许多 Pod 配置源合并成一个繁多的统一构造,而后按程序向监听器传递增量变更告诉。

配置源有:文件、apiserver、HTTP

#syncLoop

接管来自 PodConfig 的 Pod 变更告诉、定时工作、PLEG 的事件,以及 ProbeManager 的事件,将 Pod 同步到 冀望状态

PodAdmitHandlers

Pod admission 过程中调用的一系列处理器,比方 eviction handler(节点内存有压力时,不会驱赶 QoS 设置为 BestEffort 的 Pod)、shutdown admit handler(当节点敞开时,不解决 pod 的同步操作)等。

OOMWatcher

从系统日志中获取容器的 OOM 日志,将其封装成事件并记录。

VolumeManger

VolumeManager 运行一组异步循环,依据在此节点上调度的 pod 确定须要附加 / 挂载 / 卸载 / 拆散哪些卷并执行操作。

CertificateManager

解决证书轮换。

ProbeManager

实际上蕴含了三种 Probe,提供 probe 后果缓存和通道。

  • LivenessManager
  • ReadinessManager
  • StartupManager

EvictionManager

监控 Node 节点的资源占用状况,依据驱赶规定驱赶 Pod 开释资源,缓解节点的压力。

PluginManager

PluginManager 运行一组异步循环,依据此节点确定哪些插件须要注册 / 勾销注册并执行。如 CSI 驱动和设施管理器插件(Device Plugin)。

CSI

Container Storage Interface,由存储厂商实现的存储驱动。

设施管理器插件(Device Plugin)

Kubernetes 提供了一个 设施插件框架,你能够用它来将零碎硬件资源公布到 Kubelet。

供应商能够实现设施插件,由你手动部署或作为 DaemonSet 来部署,而不用定制 Kubernetes 自身的代码。指标设施包含 GPU、高性能 NIC、FPGA、InfiniBand 适配器以及其余相似的、可能须要特定于供应商的初始化和设置的计算资源。

kubelet 的启动流程

要剖析 kubelet 的启动流程,能够从 kubelet 运行形式着手。找一个 Node 节点,很容易就能找到 kubelet 的过程。因为其是以 systemd 的形式启动,也能够通过 systemctl 查看其状态。

kubelet 启动命令

kubelet 的启动命令(minikube 环境)

$ ps -aux | grep '/kubelet' | grep -v grep
root        4917  2.6  0.3 1857652 106152 ?      Ssl  01:34  13:05 /var/lib/minikube/binaries/v1.21.0/kubelet --bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --config=/var/lib/kubelet/config.yaml --container-runtime=docker --hostname-override=1.21.0 --kubeconfig=/etc/kubernetes/kubelet.conf --node-ip=192.168.64.5

或者

$ systemctl status kubelet.service
● kubelet.service - kubelet: The Kubernetes Node Agent
     Loaded: loaded (/usr/lib/systemd/system/kubelet.service; disabled; vendor preset: enabled)
    Drop-In: /etc/systemd/system/kubelet.service.d
             └─10-kubeadm.conf
     Active: active (running) since Sun 2021-06-13 01:34:42 UTC; 11h ago
       Docs: http://kubernetes.io/docs/
   Main PID: 4917 (kubelet)
      Tasks: 15 (limit: 38314)
     Memory: 39.4M
     CGroup: /system.slice/kubelet.service
             └─4917 /var/lib/minikube/binaries/v1.21.0/kubelet --bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --config=/var/lib/kubelet/config.yaml --container-runtime=docker --hostname-override=1.21.0 --kubeconfig=/etc/kubernetes/kubelet.conf --node-ip=192.168.64

源码剖析

git@github.com:kubernetes/kubernetes.git 仓库获取代码,应用最新的 release-1.21 分支。

  • cmd/kubelet/kubelet.go:35main 办法为程序入口。

    • 调用 NewKubeletCommand 办法,创立 command
    • 执行 command

      • cmd/kubelet/app/server.go:434Run 办法。

        • 调用 RunKubelet 办法。

          • 调用 createAndInitKubelet 办法,创立并初始化 kubelet

            • pkg/kubelet/kubelet.goNewMainKubelet 办法,创立 kubelet 的 各种组件。共十几个组件,见 kubelet 的构架。
            • 调用 BirtyCry 办法:放出 Starting 事件
            • 调用 StartGarbageCollection 办法,开启 ContainerGCImageGC
          • 调用 startKubelet 办法(大量应用 goroutine 和通道)

            • goroutine:kubelet.Run()

              • 初始化模块

                • metrics 相干
                • 创立文件系统目录目录
                • 创立容器日志目录
                • 启动 ImageGCManager
                • 启动 ServerCertificateManager
                • 启动 OOMWatcher
                • 启动 ResourceAnalyzer
              • goroutine:VolumeManager.Run() 开始解决 Pod Volume 的卸载和挂载
              • goroutine:状态更新 fastStatusUpdateOnce()(更新 Pod CIDR -> 更新 ContainerRuntime 状态 -> 更新 Node 节点状态)
              • goroutine:NodeLeaseController.Run() 更新节点租约
              • goroutine:podKiller.PerformPodKillingWork 杀掉未被正确处理的 pod
              • StatusManager.Start() 开始向 apiserver 更新 Pod 状态
              • RuntimeClassManager.Start()
              • PLEG.Start():继续从 ContainerRuntime 获取 Pod/ 容器的状态,并与 kubelet 本地 cache 中的比拟,生成对应的 Event
              • syncLoop() 重点,继续监控并解决来自文件、apiserver、http 的变更。包含 Pod 的减少、更新、优雅删除、非优雅删除、和谐。
        • 启动 server,裸露 /healthz 端点
        • 告诉 systemd kuberlet 服务曾经启动

kubelet 的工作原理

  1. 来动态文件、apiserver 以及 HTTP 申请的 Pod 配置变更,被发送到 kubelet.syncLoop
  2. PLEG 会定期通过容器运行时获取节点上 Pod 的状态,与其缓存中的 Pod 信息进行比拟,封装成事件,进入 PLEG 的通道
  3. 定期检查工作队列中的 Pod
  4. ProbeManager 的通道中的 Pod
  5. 以上 1~4,都会进入 syncLoopIteration,并从对应的通道中获取到对应 Pod,将 Pod 的信息保留到 PodManager;而后分发给 PodWorker,实现一些列的同步工作。

总结

kubelet 启动流量就讲到这里,尽管简单,还是有迹可循。只有理解了 kubelet 在 Kubernetes 中的定位及角色,就很容易了解其工作流量。

前面会再深入分析 Pod 创立及启动流程。

延长浏览

  • Kubernetes 源码解析 – Informer
  • Kubernetes 源码解析 – HPA 程度主动伸缩如何工作

    文章对立公布在公众号 云原生指北

正文完
 0