前言

本文主要会介绍笔者在学习Kubernetes DaemonSet Controller的实现原理时所总结的知识点,其中会涉及到DaemonSet Controller的实现原理、控制循环以及版本控制等方面的相关内容。 笔者也会将自己的理解在文中进行阐述,这也算是在和大家交流心得的一个过程。若文中有错误的理解和概念,请大家及时纠正;吸纳大家的建议,对于我来说也是很重要的学习过程之一。


(目录)


1.相关概念

DaemonSet所创建的Pod对象会有以下几种特性:

  1. Pod运行在Kubernetes集群里的每一个节点(Node)上

  2. 每个节点上只有一个Pod对象

  3. 当有新的节点加入 Kubernetes 集群后,该Pod会自动地在新节点上被创建出来;而当旧节点被删除后,它上面的Pod也相应地会被自动回收掉


2.调度Pod

在Kubernetes v1.11 之前,由于调度器尚不完善,因此DaemonSet是由DaemonSet Controller自行调度的。实现方式为直接设置Pod的spec.nodename字段,这样就可以跳过调度器来直接调度相关Pod对象了。

在Kubernetes v1.11后,DaemonSet则不再直接配置Pod对象的相关属性,而是通过设定nodeAffinity和tolerations来让相关的调度器来协助调度Pod


3.实现原理

3.1 保证Node上只运行一个Pod

DaemonSet Controller首先从API Server中获取所有的Node列表,然后遍历所有的Node并检查每一个Node上是不是运行了一个携带了指定label的Pod对象。 这里会出现以下几种情况:

  1. 没有查找到相关Pod对象 则此时需要在这个Node上创建一个带有指定label的Pod。

  2. 查找到相关Pod对象但不只一个 此时需要把多余的Pod对象从Node上删除掉,保证该Node上只运行一个此类Pod对象。

  3. 查找到相关Pod对象且只有一个 则说明这个Node是正常的,无需任何操作。

Tips: DaemonSet实际上是利用了Kubernetes的label selector来实现上述功能。

3.2 保证Node上永远会被调度Pod

DaemonSet Controller会在创建Pod时自动在Pod对象里加上一个nodeAffinity定义。在nodeAffinity定义中会指定Pod所“亲近”的Node name。即DaemonSet Controller使用节点亲和性来保证为每一个Node上都分配了一个DaemonSet Pod

同时,DaemonSet Controller还会给Pod自动加上一系列的Tolerations,这些Tolerations定义了Pod能够容忍指定Node上的一些Taint。而这些Taint往往都是Node在发生一些异常情况时才会被添加上的污点。给Pod增加能够“容忍”这些“污点”就是要保证即使Node发生了异常,Kubernetes也能够不断的尝试往异常Node上调度和运行DaemonSet Pod,直到Pod成功在Node(Node恢复正常状态)上创建和运行。即DaemonSet Controller使用污点机制来保证每个Node上始终都会被调度一个DaemonSet Pod

Tips: DaemonSet Controller在向Kubernetes发起请求之前直接会去修改根据模板所创建的Pod对象,即DaemonSet是直接操作Pod对象的截屏2024-03-12 14.25.27.png

3.3 控制循环

2393007-20211223084611671-2008124571.png

DaemonSet的控制循环逻辑主体思路为:

  1. 检查每个Node 遍历所有Node,然后根据Node上是否有被管理Pod的情况来决定是否要创建或者删除一个Pod。

  2. (可选)为Pod配置节点亲和性 在创建每个Pod的时候,DaemonSet Controller会自动给Pod加上一个nodeAffinity,从而保证这个 Pod只会在指定节点上启动。

  3. (可选)为Pod配置污点容忍 在创建每个Pod的时候,DaemonSet Controller会自动给Pod加上一个Toleration,从而忽略Node的相关“污点”。

  4. (可选)删除对于Pod 如果发现一个Node上运行了多个DaemonSet Pod,则删除多余的Pod。


4.版本控制

DaemonSet使用ControllerRevision对象来实现DaemonSet的版本管理控制

Tips: 更多关于ControllerRevision对象的知识可以参考笔者的另一篇文章

每对现有的DaemonSet对象做一次PATCH操作(等价于执行一次 kubectl apply -f “旧的 DaemonSet 对象”),Kubernetes就会为其创建一个ControllerRevision对象并把修改前的DaemonSet对象整体定义记录到其中。